Posts Tagged GWT

Porting Swing’s Action pattern to GXT (Ext-GWT)

ext_logoWhile working with GWT and GXT, it occurred to me that there was no equivalent in either to Swing’s Action architecture… So I set myself to implement an equivalent functionality in GXT.

The Swing legacy

In a word, the action architecture is an implementation of the Command design pattern, with the Action class being an abstraction of a command which is not bound to a specific UI component. Action implements ActionListener, which lets users perform it, namely by calling its actionPerformed method. An Action may also contain additional meta-information such as a name, a description, an icon, etc.

The cool thing with actions is that many Swing components (such as a JButton or a JMenuItem) are action-aware, which means that they can be constructed from an action instance. The data required to build the UI component, such as the button’s label, is taken from the Action’s meta-data. When the component is activated (read: clicked), the corresponding action’s actionPerformed method is then called.

Furthermore, if the action is disabled, then the corresponding UI component becomes disabled too. If you used the same Action instance to construct several UI components, they will all reflect the action’s disabled status! Now this is starting to get interesting…

Let’s see if we can make this happen with GXT.

Step 1: the Action classes

First we need an ActionListener interface:

import com.extjs.gxt.ui.client.event.BaseEvent;

public interface ActionListener {

    /**
     * Invoked when an action occurs.
     */
    void actionPerformed(BaseEvent e);

}

This is quite similar to Java’s original ActionListener interface, except that we use GXT’s BaseEvent instead of Java’s ActionEvent, for obvious reasons. The original ActionListener also inherited EventListener, which is not needed here.

Next we need an Action interface that allows UI components to fetch what they need to construct themselves (name, etc.). The original Action interface contains

  • a set of String constants that define the names of the properties (NAME, SHORT_DESCRIPTION, SMALL_ICON, etc.)
  • methods to get/set those properties
  • methods to add/remove a PropertyChangeListener so that we can be notified of changes

In native Java, the property-related methods are implemented completely in AbstractAction using ArrayTable and SwingPropertyChangeSupport, which means I would have to add a lot of code to duplicate the functionality.

Fortunately, GXT has a class called BaseModel which provides exactly the same set of functionality: named properties plus support for change listeners. So I slightly modified the Action interface so that GXT’s BaseModel would directly implement the property-related methods:

  • Object getValue(String key) becomes <X> X get(String key)
  • void putValue(String key, Object value) becomes <X> X set(String key, X value)
  • void addPropertyChangeListener(PropertyChangeListener listener) becomes void addChangeListener(ChangeListener... listener)
  • void removePropertyChangeListener(PropertyChangeListener listener) becomes void removeChangeListener(ChangeListener... listener)

Here is the full listing (most comments removed for brevity; see original Action Javadoc):

import com.extjs.gxt.ui.client.data.ChangeListener;

public interface Action extends ActionListener {
    /**
     * Useful constants that can be used as the storage-retrieval key
     * when setting or getting one of this object's properties (text
     * or icon).
     */
    public static final String DEFAULT = "Default";
    public static final String NAME = "Name";
    public static final String SHORT_DESCRIPTION = "ShortDescription";
    public static final String LONG_DESCRIPTION = "LongDescription";
    public static final String SMALL_ICON = "SmallIcon";
    public static final String ACTION_COMMAND_KEY = "ActionCommandKey";
    public static final String ACCELERATOR_KEY = "AcceleratorKey";
    public static final String MNEMONIC_KEY = "MnemonicKey";
    /**
     * The key used for storing the CSS icon style (added)
     */
    public static final String ICON_STYLE = "IconStyle";

    public <X> X get(String key);
    public <X> X set(String key, X value);

    public void setEnabled(boolean b);
    public boolean isEnabled();

    public void addChangeListener(ChangeListener... listener);
    public void removeChangeListener(ChangeListener... listener);
}

A few comments on this:

  • get/set methods are now generic (which must be good),
  • we use GXT’s ChangeListener instead of Java’s PropertyChangeListener, because that’s what GXT’s BaseModel supports
  • not all properties make sense in GXT, but I have kept them nonetheless. You never know…
  • I have added a property ICON_STYLE, which might be useful in a GWT context if we want to provide an icon as a CSS style rather than an Image.

Now we need an implementation of the Action interface that provides default behaviours for get/set methods and property change listeners; thanks to our little changes in Action, we just have to extend GXT’s BaseModel, which will handle most of the job.

import com.extjs.gxt.ui.client.data.BaseModel;

public abstract class AbstractAction extends BaseModel implements Action {

    /**
     * Specifies whether action is enabled; the default is true.
     */
    protected boolean enabled = true;

    public AbstractAction() {
    }

    public AbstractAction(String name) {
        set(Action.NAME, name);
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean newValue) {
        boolean oldValue = this.enabled;

        if (oldValue != newValue) {
            this.enabled = newValue;
            notifyPropertyChanged("enabled", newValue, oldValue);
        }
    }

}

That’s it! The get/set/addChangeListener/removeChangeListener methods are directly implemented by BaseModel and don’t even need to be redeclared here. I have dropped Cloneable and Serializable from the implemented interfaces because it doesn’t make much sense in a GWT context.

Step 2: the UI components

OK, now we have Actions that have properties, can notify changes, and can do something when they are performed. What we need to really make this useful is UI components that can accept an Action and will do what’s needed to translate that into UI stuff.

Let’s extend Menu so that we can call add(Action):

public class Menu extends com.extjs.gxt.ui.client.widget.menu.Menu {

    public boolean add(final Action action) {

        final MenuItem item = new MenuItem(action.get(Action.NAME));

        // Use the action's long description as tooltip
        String longDesc = action.get(Action.LONG_DESCRIPTION);
        if (longDesc != null) {
            item.setToolTip(longDesc);
        }
        item.setEnabled(action.isEnabled());

        item.addSelectionListener(new SelectionListener() {
            public void componentSelected(ComponentEvent event) {
                action.actionPerformed(event);
            }
        });

        // make sure changes in the "enabled" state of the action are propagated
        // to the MenuItem
        action.addChangeListener(new ChangeListener() {
            public void modelChanged(ChangeEvent event) {
                PropertyChangeEvent propertyChangeEvent = (PropertyChangeEvent) event;
                if (propertyChangeEvent.getName().equals("enabled")) {
                    boolean enabled = (Boolean) propertyChangeEvent.getNewValue();
                    item.setEnabled(enabled);
                }
            }
        });

        return add(item);
    }
}

The outline is very simple:

  • create a MenuItem
  • give it name, tooltip, state according to the Action
  • make sure that selecting it will trigger the action
  • make sure that if the “enabled” status of the action changes, the “enabled” status of the MenuItem changes accordingly
  • add the MenuItem

Now let’s do the same for a Button; in this case we’ll add a constructor that takes an Action :

public class Button extends com.extjs.gxt.ui.client.widget.button.Button {

    public Button() {
    }

    public Button(String text) {
        super(text);
    }

    public Button(String text, SelectionListener listener) {
        super(text, listener);
    }

    public Button(final Action action) {
        this(action.get(Action.NAME));

        // Use the action's long description as tooltip
        String longDesc = action.get(Action.LONG_DESCRIPTION);
        if (longDesc != null) {
            setToolTip(longDesc);
        }

        setEnabled(action.isEnabled());

        addSelectionListener(new SelectionListener() {
            public void componentSelected(ComponentEvent event) {
                action.actionPerformed(event);
            }
        });

        // make sure changes in the "enabled" state of the action are propagated
        // to the Button
        action.addChangeListener(new ChangeListener() {
            public void modelChanged(ChangeEvent event) {
                PropertyChangeEvent propertyChangeEvent = (PropertyChangeEvent) event;
                if (propertyChangeEvent.getName().equals("enabled")) {
                    boolean enabled = (Boolean) propertyChangeEvent.getNewValue();
                    setEnabled(enabled);
                }
            }
        });

    }
}

You get the picture, it’s easy to generalize this to any UI component.

Conclusion

With this pattern, you can now easily create a menu item and a button, linked to the same action. If the action becomes unavailable, you call Action.setEnabled(false), and automagically the button and menu item become disabled…

PS: some of the code here is directly taken from the JDK source; I believe this is legit use under the Java Research License, but if it is not, let me know.

, , ,

No Comments

Snow Leopard, Java 6 and GWT

mac-logoRunning GWT’s hosted mode on the Mac requires a 32 bit JVM, which under OS X 10.5 (Leopard) forces us to use Java 5, because Java 6 only has 64 bit libraries.

Problem: OS X 10.6 (Snow Leopard) removes all versions of Java but version 6. Fortunately, Java 6 now has a 32 bit mode, but it can’t be used straightforwardly for hosted mode because GWT insists on having Java 5…

So how do we get GWT’s hosted mode to run? Alex Moffat suggests an elegant solution:

Lombardi Development Blog » Blog Archive » Snow Leopard, Java 6 and GWT.

, , ,

No Comments

Fred Sauer’s GWT for the Enterprise Developer

Freed Sauer has a very interesting presentation online: GWT for the Enterprise Developer @ JBoss World Chicago 2009 (includes GWT 2.0 insight !)

View more documents from Fred Sauer.

,

No Comments

Myths and misconceptions about GWT

Logo GWTHere is, in no particular order, a list of myths and misconceptions that I’ve gathered from reading GWT-related discussions on various websites.

Myth: GWT is a JavaScript library/framework/widget set

GWT is no use for JavaScript programmers, so it doesn’t provide anything as JavaScript: no library, no framework, no widget set. It does provide a Java library, which includes a widget set and JRE emulation classes, but these are all in Java and meant to be used from Java code.

Myth: GWT is a framework

You see this one quite often, and even the wikipedia entry for GWT used to describe it as such. The T in GWT stands for Toolkit, and that’s exactly what it is: a set of tools (in the broad sense), any of which you may or may not use. The difference between a toolkit and a framework is a subtle one, and very hard to explain, but in a word you can say that a framework is about providing reusable behaviour, while a toolkit is about providing reusable functionalities. A framework calls your code, while your code calls a toolkit. GWT provides very little predefined behaviour, and the only time it calls your code is when invoking the entry point of your class, which is the bare minimum.

And of course, you can write frameworks on top of GWT.

Myth: GWT is only for Java programmers

It’s true that GWT lets you program AJAX apps in Java, but you can also see it this way: GWT lets you write AJAX apps with the best state-of-the-art IDEs, debug them, refactor them, test them, all this in a statically-typed object-oriented language (which happens to be Java).

I think this should appeal to more than only the community of Java developers. To tell the truth, I even think that GWT alone makes it worth learning Java.

Myth: GWT generates poorly performing JavaScript

You hear this one often too. Actually it’s quite the opposite: GWT will generate far more optimized code that the vast majority of JavaScript programmers can write. I’m not saying it’s not possible to write more efficient code by hand, it probably is, just like it’s possible to make an application more efficient by hand-writing assembly code, but the improvement you can expect is marginal. So bottom line is: it’s not worth it.

Myth: GWT requires a Java backend

This misconception probably comes from the fact that GWT includes a simple and efficient RPC mechanism for calling server-side methods implemented in Java, but it’s not by far the only option. GWT handles XML and JSON like a charm, and can communicate with any type of server-side implementation over HTTP.

Myth: GWT has a poor palette of UI components

This is not totally untrue, but the thing is: it’s not the point. To be fair, GWT’s builtin widgets can be described as minimalistic, but they are still sufficient to build a complete and rich user interface. However, remember that GWT is not a framework, so it doesn’t have to be complete. If you want a complete palette of rich widgets, you should turn to third-party libraries such as Ext GWT or similar.

Myth: GWT apps have long startup times

Nonsense. Code loading times are not longer than any AJAX app, probably less because the generated JavaScript is obfuscated which makes it quite compact. And if your application is slow to initialize, it’s certainly because you are doing too much during startup: think lazy initialization.

Myth: Your site has to be all-GWT or nothing

Again, nonsense. GWT was designed from the beginning with the goal that it can be integrated into any web page. To add GWT behaviour into any existing web page you just need to add very little HTML code and it’s done.

Myth: UI customization/skinning is limited

GWT relies on CSS for styling. While this has its drawbacks, like the possibility to introduce browser dependencies that GWT tries so hard to avoid otherwise, it means that it opens the whole CSS world to GWT apps. It means you can radically change the appearance of a GWT app without touching a single line of code (this is not theory, we’ve done it). It means you can let web designers to their job of styling the app using the language they know (CSS), while letting developers do their job of providing behaviour using the language they know (Java). Bottom line: GWT skinning is as limited as CSS.

,

1 Comment

Google Eclipe plugin 1.1.0 available

Logo GWTMiguel Méndez:

We wanted to let all of you know that the Google Plugin for Eclipse 1.1.0 is now available. Some of the notable improvements are:
-Support for Eclipse 3.5 (Galileo)
-GWT RPC interface validation with quick fixes
- App Engine DataNucleus enhancer console no longer steals focus on save

Announcement, Relase Notes

, , ,

No Comments

“GWT Basic” exam on javablackbelt.com

logo-javablackbeltI have written the objectives for a GWT basic exam at javablackbelt.com. As you may know, javablackbelt is a community site where users can take tests as well as evaluate and submit questions.
So if you have 5 minutes to spare why don’t you submit a question or two for this exam? :)

,

No Comments

GWT 1.7 Now Available

Logo GWTBruce Johnson:

GWT 1.7 is a minor update that adds better support for Internet Explorer 8, Firefox 3.5, and Safari 4 (…)
Normally, a minor update such as this would have been named 1.6.5 (the previous latest version of GWT was 1.6.4), but we did add the value “ie8″ to the “user.agent” deferred binding property, which could impact projects using custom deferred binding rules that are sensitive to that property.
Thus, we went with GWT 1.7 rather than GWT 1.6.5, to indicate that you may
need to pay attention to that change.

GWT 1.7 Now Available – Google Web Toolkit Contributors | Google Groups.

No Comments

Google Chrome OS – the browser is the OS?

google_chrome_logoLast week Google announced its upcoming OS, Chrome OS. More than the fact that Google is entering the OS market, which was expected, the most significant thing about this announcement is the OS name. Chrome is already the name of the web browser that Google launched 9 months ago.

Chrome is without a doubt the fastest browser in existence. It doesn’t really show in standard static HTML/CSS web pages, however bloated they may be, because I believe all browsers are close to the maximum speed that can be reached when displaying this kind of pages. Where Chrome crushes the competition is when running AJAX applications. The GWT application I’m working on is so much faster on Chrome than any other browser, that you easily forget it’s an AJAX app. Firefox is already much smoother than IE, but Chrome is way ahead in terms of executing JavaScript and giving the user instant feedback. There was a time we considered optimizing the server-side processing or the network usage because we thought that was where most time was lost. Good thing we didn’t, because after trying our application on Chrome, we now know that this would have been useless. The slow parts of or applications were only slow because of inefficient JavaScript execution on IE and (to a lesser extent) Firefox.

So, Chrome gives the best user experience for AJAX apps. But what about the overall computer user experience? Google figured that if you “live on the web”, the OS in you computer is probably getting in the way, because it’s designed to do too many things instead of just letting you get on the web. It’s slow to boot, it’s big, it has a lot of things you don’t need and will never use. So the idea of Google is to remove everything but the bare minimum: a kernel (Linux), a windowing system (no details on that, except it will be “new”) and of course a browser (Chrome). The name Chrome OS was then a logical choice, since the most visible part of this OS will be the Chrome browser.

I read a lot of articles saying that Google was now set to fight Microsoft on the OS field. Is this true? Yes and no. Yes, because it will probably take away a significant part of  Microsoft’s business, that is computers that are designed for online access. That includes netbooks, but not only: a large and growing part of computer users “live on the web” and don’t use their computers for anything else. No, because there will still be some use cases where Chrome OS will not be an option: gaming, video editing, development, all CPU-demanding activities. And we’re only talking about desktop users of course.

So we have a OS with a minimal Linux kernel, and adopting web technologies as the main application building bricks… does that remind you of anything? If not, have a look there

, , , ,

No Comments

GWTUML – Just Enough UML for Wikis

If you ever wanted to embed a UML diagramming tool into a wiki, try this:

Agile Ajax » GWTUML – Just Enough UML for Wikis » Pathfinder Development.

Under the hood GWTUML uses Tatami to leverage the Dojo toolkit.

Congratulations Florian, this is really impressive!

, , ,

No Comments

GWT: keep thinking in Java!

Logo GWTAs a reply to a post on ongwt.com asking about tips for GWT newcomers, someone answered “think in JavaScript, not in Java”. I felt I had to respond, because my experience is totally the opposite, and that’s why I would recommend GWT to anyone who wishes to write AJAX applications while continuing to think in Java (not in JavaScript).

For the record here’s my reply:

“think in JavaScript, not in Java”: I strongly disagree with that!
JavaScript plays the same role for GWT as bytecode does for plain Java: an intermediate language, generated by the compiler, and interpreted by the runtime platform.
As for HTML and CSS, it is true that it helps a lot to know them, especially when the time has come to add styling to your application. This is by design, as explained in the developer’s guide: “instead of attempting to encapsulate UI styling behind a wall of least-common-denominator APIs, GWT provides very few methods directly related to style. Rather, developers are encouraged to define styles in stylesheets that are linked to application code using style names”.
The whole point of GWT is to shield the programmer from JavaScript and let him use the Java idiomatisms and tools he is used to. I’ve been working with GWT for almost 3 years now and I have never ever felt the need to learn JavaScript. And I thank GWT for that!

JavaScript is just a means to achieve the goal, which is: to build a rich web UI. Knowing JavaScript will not help you build a good client, instead you should concentrate on writing clean and robust client code using proven techniques such as MVC, which GWT makes really easy to use (unless you’re using GXT, but that’s another story…)

, ,

4 Comments