Development Tips

Introduction

Developing a web app with Cooee is designed to be exceptionally easy. However it is definately a departure from developing one with JSF, Struts, Tapestry or whatever flavour of Java gets you going. Putting familiar html concepts to the back of your mind, and working only to an API is not an easy thing to do. As such, below is tidbits of anything and everything that will help you along the way.

A lot of the credit for the information here has to go to the Echo2 forum (forum.nextapp.com/forum). It strikes me though that a centralised place for this info is a much better way to go.

We'll attempt to keep this page as organised as possible, and break it up as appropriate.

Components

SelectFields - Where's my Key-Value gone?

Not best practice

Be aware, the following does not represent best practices.  CellRenderers should be used for defining label/text values in SelectFields (drop downs)

 


Problem: In Html, a Select box (control) has a map with key and value. This allows for a String to be displayed to the user, whilst the system uses a unique value. How does one apply this SelectField or SelectFieldEx because they just have a fixed sequence(0...n) for values.

Answer:
Everything in Cooee is object based. As such, you put an object into a list model for a select field, and you ask the select field for the selected object back. This means that if you have say 3 values :

Grade 2  | 2
Grade 3  | 3
Grade 4  | 4

You will need to wrap them up into an appropriate object. The easiest way to do this is a simply two property object that overrides the toString method. Something like this would work:

ObjectWrapper
public class ObjectWrapper
{
   int key;
   String text;

   public ObjectWrapper(int key, String text)
   {
      //   ... setvals ...
   }
   public String toString()
   {
        return text;
   }
   // ... stuff ...
}

Of course this is not the only way to do this. The wonders of Cooee and Objects mean that given an arbitary object, lets say "GradeSchoolData", that doesn't override the toString() method, we can implement a custom renderer that knows how to interact with this object. As such, you suddenly don't need to define a wrapper and code to set up your wrappers.

Which solution you use is entirely up to your development taste and style.

How do I put a link in a label?

Question: How can I drop a dynamically built URL in a Label?

Answer:
The lead developer of EPNG specifies that the best way to acheive this is through the following :
"You could use a DirectHtml component from EPNG and place some <a href="" > code in it. This is the probably the most light weight way to do it."

Personally I wouldn't take this approach - Cooee is all about abstracting developers away from the evils of HTML. What would be better is a HTMLLink component, or some kind of HTML link enabled label - sadly we don't have that (Contribute to Cooee!).

The other option here is to create a new component based on a button. The default Cooee button renders much like text - with no borders, button facades, etc. It's essentially a big fat link - so we can take advantage of that.

A developer on the Echo2 forum (http://forum.nextapp.com/forum/index.php?showtopic=3111&hl=link) suggests something along the lines of this:

Hyperlink
import org.karora.cooee.app.Button;
import org.karora.cooee.app.Color;
import org.karora.cooee.app.Font;
import org.karora.cooee.app.MutableStyle;
import org.karora.cooee.app.button.AbstractButton;
import org.karora.cooee.app.event.ActionEvent;
import org.karora.cooee.app.event.ActionListener;
import org.karora.cooee.webcontainer.command.BrowserOpenWindowCommand;

public class Hyperlink extends Button implements ActionListener {

public static MutableStyle DEFAULT_STYLE = new MutableStyle();
static
{
    DEFAULT_STYLE.setProperty(AbstractButton.PROPERTY_FONT, new Font(null, Font.UNDERLINE, null));
    DEFAULT_STYLE.setProperty(AbstractButton.PROPERTY_FOREGROUND, Color.BLUE);
    DEFAULT_STYLE.setProperty(AbstractButton.PROPERTY_DISABLED_FOREGROUND, Color.LIGHTGRAY);
    DEFAULT_STYLE.setProperty(AbstractButton.PROPERTY_ROLLOVER_ENABLED, true);
    DEFAULT_STYLE.setProperty(AbstractButton.PROPERTY_ROLLOVER_FOREGROUND, Color.BLACK);
}

public Hyperlink()
{
         this("", null);
}

public Hyperlink(String text)
{
         this(text, null);
}

public Hyperlink(String text, String url)
{
         setStyle(DEFAULT_STYLE);
         setText(text);
         setUrl(url);
         addActionListener(this);
}

public String getUrl()
{
         return getToolTipText();
}

public void setUrl(String url) {
   if (url \!= null && \!"".equals(url))
   {
             setToolTipText(url);
             setEnabled(true);
   }
   else
   {
             setEnabled(false);
   }
}

public void actionPerformed(ActionEvent e)
{
         getApplicationInstance().enqueueCommand(new BrowserOpenWindowCommand(getToolTipText(), "", ""));
}
}

Which will do the job - essentially such that when the button is clicked, a the browser will be instructed to open a new window. In your solution, you may want to look at abstracting out the difference between text and a html link - and essentially creating a composite component that sits on a composite and creates labels and buttons appropriately.

Setting the selection on a table

Question: In Cooee, how do I set the selection of a particular row in a table? I know I can do this in Swing, but I just can't do it in Cooee!

Answer:
Swing allows you to do this directly on the Table object in this sort of manner:

aTable.changeSelection( rowNum, colNum, false, true )

However in Cooee, tables use whats known as a SelectionModel (for which there are a few different flavours of). As such, you will need to ask the selection model to set the selection as you see fit.

This can be done by something along the following:

aTable.getSelectionModel().setSelectedIndex(int index, boolean selected)

Setting focus on a component

Question: My users have a habit of being bad - if they try and save my page without typing the magic words into the special text field, I want Cooee to set the focus back on my special text field!

Answer:
Get nicer users that are never bad. Hey look, a flying pig! Seriously though, this is quite easy to achieve using something along these lines:

ApplicationInstance.setFocusedComponent(Component newValue)

Or check out the API at: http://www.karora.org/projects/cooee/apidocs/org/karora/cooee/app/ApplicationInstance.html#setFocusedComponent(org.karora.cooee.app.Component)

Rich Text Area

Question: Can I make this read only?

Answer:
The lead developer of EPNG suggests no. For some unknown reason, the object declares methods such as "setEditable", that do precisely nothing. Consequently this may be something for the Cooee project to look at. However this post: http://forum.nextapp.com/forum/index.php?showtopic=3620, provides a component "ERichTextArea", which apparently addresses some of the issues Echo2/EPNG users have experienced with said component.

The please wait message

Question: How do I change the please wait message that pops up?

Answer: Check out http://forum.nextapp.com/forum/index.php?showtopic=4109

When should I use Columns, Rows and Grids for component layout? How are they effected by "LayoutData"?

Column and Row allow you to line up other components either vertically or horizontally. And as a bonus they support "partial updates" so only the changed children will be sent down over the wire, which if they change a lot can give you extra performance (and if they change very little it means squat)

Grid is a like a combination of Column and Row and again for lining up other components in a "grid like" fashion.

LayoutData controls how the components work inside the Column/Row/Grid container.

How do I center align labels in rows?

Something like the following should help:

Label label = new Label("Hello World");

Row row = new Row();
row.setAlignment(Alignment.ALIGN_CENTER);
row.add(label);

ContentPane contentPane = new ContentPane();
contentPane.add(row);
return contentPane;

Sandbox Components

Whenever I start dragging a widget, its shadow doesn't stay right under the mouse cursor but (far) below or to the side.

You may need to check if you have set setDragContainer() to a "container" (Container or Pane) which provides correct on-screen coordinates. Even though your WidgetDash is placed in a Column/Row or whatever other than a Pane/Container, these have to be inside a pane/container (parent).

Framework

Application Startup

Question: When the Cooee application starts, where does the initial HTML come from?

Answer:
There is a class org.karora.cooee.webrender.BaseHtmlDocument. This class is called to generate the initial html for a Cooee application.

The result of the class will be something along the lines of:

<head>
<style />
</head>
<body>
<form style="padding:0px;margin:0px;" action="#" id="$contentID" onsubmit="return false;">
   <div id="loadStatus">
      <text>//</text>
   </div>
</form>
</body>

''Where $contentID is the content id provided by the framework''

When the ClientEngine reads this html, it will immediately replace the "loadStatus" with whatever it has defined for the loading status. This may very well change before the release of Cooee 1.1.

The Debug Console

Question: How do I bring up the Cooee Debugging Console?

Answer: Append ?debug to the end of your application URI. eg: If your Cooee Servlet is called demo, and accessed via "http://localhost:8080/demo", you can bring up the debug console by accessing the servlet via "http://localhost:8080/demo?debug"

Deploying

General Deployment

OSGI is off topic for this question set

Question: How do I deploy a Cooee application?

Answer:
Firstly, ensure you're reasonably familiar with the high level workings of a web container like tomcat. This will give you a basic idea as to what needs to be done.
However the basic approach for deploying a Cooee webapp goes something like:

  • Install tomcat
  • Build a war file of your echo application (Giving the war file a reasonable name like "MyApp")
  • Put war file in 'webapp' folder of tomcat server
  • Start tomcat (tomcat will create a build of the war file)
  • Navigate to localhost:8080 / MyApp (or whatever you called the jar)

Although if you were super dooper clever and used Maven, you could just do this:

mvn jetty:run

Although I wouldn't be doing that in a production environment.

Disabling Debug Mode

Question: How do I prevent users from starting the Echo2/Cooee Debug Mode?

Answer: This is controlled by the servlet init parameter "echo2.debug". Set this parameter to false.

Labels

 
(None)
  1. Jul 13, 2007

    Anonymous says:

    i've tried to use mvn jetty:run but got an errror, tried this & worked for me..:...

    i've tried to use mvn jetty:run but got an errror, tried this & worked for me..:

    mvn org.mortbay.jetty:maven-jetty-plugin:run

Add Comment