Category Archives: GWT

Introducing SmartGWT to Grails

SmartGWT is a custom library for GWT that wraps the SmartClient AJAX toolkit. It looks impressively comprehensive and the show case is pretty slick. As with ExtJS though, SmartClient (and by extension SmartGWT) is quite large, and so it will take some time to learn how to use it. That’s my disclaimer, or more accurately an excuse for using such a pitiful example in this post. My aim here is just to show you how to get started with Grails and SmartGWT.

Prerequisites

You need Grails installed, unless you’re using Ant or Maven (in which case you need those installed 😉 ). I’ll assume in this article that you’re using the Grails command line, and therefore have a Grails installation.

Working smart

In order to use SmartGWT you need a Grails project, so create one now. I called mine “smart-working” – feel free to ditch that and use another name. Once Grails has worked its magic and created the project, you need to install the marvellous, wonderful, and downright cool GWT plugin (can you tell I wrote it?):

grails install-plugin gwt
At the time of writing, this command will install version 0.3.2 and present you with a list of GWT-related commands added by the plugin:

Plugin gwt-0.3.2 installed
Plug-in provides the following new scripts:
------------------------------------------
grails compile-i18n
grails create-gwt-page
grails run-gwt-client
grails create-gwt-module
grails compile-gwt-modules
grails generate-gwt-rpc

It’s looking good so far, but there’s no reference to SmartGWT in any of those commands. The sad truth is, you have to install it yourself at the moment. Fortunately, that’s pretty easy:

  1. grab the SmartGWT distribution from Google Code
  2. extract the zip file
  3. create the directory <project>/lib/gwt, for example smart-working/lib/gwt
  4. copy the smartgwt.jar file (in the root of the unpacked zip) to the directory you just created.

Any GWT libraries that you want to use should go into <project>/lib/gwt.

Your first SmartGWT page

SmartGWT is now ready for action. All we have to do is harness its power in our application’s UI. As with normal GWT, the starting point is a module. Let’s create one now:

grails create-gwt-module org.example.SmartButton
This will create two files under the src/gwt directory:

  • org/example/SmartButton.gwt.xml
  • org/example/client/SmartButton.java

At the moment, these files are only configured for bog-standard GWT, but adding SmartGWT is pretty straightforward. First off, we need to add a line to the XML module file:

<module>
    <!-- Inherit the core Web Toolkit stuff.                  -->
    <inherits name="com.google.gwt.user.User"/>

    <!-- Add SmartGWT -->
    <inherits name="com.smartgwt.SmartGwt"/>

    <!-- Specify the module entry point class.                   -->
    <entry-point class="org.example.client.SmartButton"/>
</module>

The second step is to use the SmartGWT elements in SmartButton.java:

package org.example.client;

import com.google.gwt.core.client.EntryPoint;

import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Button;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.layout.VLayout;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class SmartButton implements EntryPoint {
    /**
     * This is the entry point method.
     */
    public void onModuleLoad() {
        VLayout main = new VLayout();
        main.setWidth100();
        main.setHeight100();
        main.setLayoutMargin(5);

        Button button = new Button("Jump!");
        button.setAutoFit(true);
        button.setPadding(5);
        button.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent evt) {
                SC.say("You first");
            }
        });
        main.addMember(button);

        main.draw();
    }
}

The above code will create a simple button with the text “Jump!” on it that, when clicked, will display a modal dialog saying “You first”. We still don’t have a page on which to display this button, though, so we’ll have to create one:

grails create-gwt-page smart.gsp org.example.SmartButton
This will create a new GSP view that uses our SmartButton module. The Grails GWT plugin currently puts the GSP page, smart.gsp, in the project’s web-app directory, but that’s no longer the appropriate location (since Grails 1.1 I believe). So, you should move the smart.gsp file to the grails-app/views directory.

As an aside, you can also create GWT views backed by controllers. If you pass a string of the form <controllerName>/<page>.gsp as the first argument, the command will add the <page> view to the named controller, although you will have to manually add the corresponding action. The command will even offer to create the controller if it doesn’t already exist.

Right, the view has been created and it’s even displaying the button, but it’s a bit like a wireframe view of the button. That doesn’t look good. The problem is that the page can’t find the SmartClient skin files because the CSS link is wrong. You’ll probably also notice that the (wireframe) button is overlaying the Grails logo. Argh!

Let’s address the first problem. SmartGWT assumes that your project follows the standard GWT 1.5 layout. This assumption falls flat on its face with a Grails project, though, hence the incorrect CSS link. To fix the issue, we need to tell SmartGWT where the CSS files can be found. How do we do that? Add the following line to your smart.gsp file:

<head>
  <!-- Integrate with Sitemesh layouts           -->
  <meta name="layout" content="main" />

  <!--                                           -->
  <!-- Any title is fine                         -->
  <!--                                           -->
  <title>Example title (change this!)</title>

  <script>var isomorphicDir = "gwt/org.example.SmartButton/sc/"</script>

  <!--                                           -->
  <!-- This script loads your compiled module.   -->
  <!-- If you add any GWT meta tags, they must   -->
  <!-- be added before this line.                -->
  <!--                                           -->
  <script type="text/javascript" src="${createLinkTo(dir: 'gwt/org.example.SmartButton', file: 'org.example.SmartButton.nocache.js')}"></script>
</head>
...

Interestingly (or simply annoyingly depending on your take), you need to remove the leading gwt/ from the isomorphicDir value if you’re using GWT 1.6. I don’t know why, but that’s what you have to do.

Update I have discovered that the standard main.css file used by the default Grails layout doesn’t play nicely with SmartGWT. The best option is probably to modify grails-app/views/layouts/main.gsp by removing the link to main.css. Your SmartGWT application will then look as it should!

The second problem relates the the SmartGWT layout that we use in the example. If you create a VLayout, set it’s height to 100% (via the setHeight100() method, and then call the draw() method, the layout takes up the whole page, even if a Grails layout is applied to the view. The solution involves three steps. First, remove the call to setHeight100() in SmartButton.java. Second, replace the line

main.draw();
with

RootPanel.get("main").add(main);
Don’t forget to import the RootPanel class! The final step is to add a div to the body of the host page, smart.gsp:

<body>  
  <!-- OPTIONAL: include this if you want history support -->
  <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe>
        
  <div id="main"></div> 
                
  <!-- Add the rest of the page here, or leave it -->
  <!-- blank for a completely dynamic interface.  -->
</body> 

If you’re using hosted mode, just refresh the page to see the final product in action! The modal dialog looks a bit off for some reason, but that can probably be fixed by a SmartGWT aficionado.

Update The modal dialog looks off because of the main.css problem mentioned in the previous update. It also seems that you don’t need to remove the call to setHeight100() – that was probably down to main.css as well.

An idiosyncrasy in the GWT plugin

If you use a normal browser to view the SmartGWT page in all its glory, rather than hosted mode, then you may soon notice that the GWT modules are not recompiled by grails run-app when they are modified. This behaviour is intentional: hosted mode reads the module files directly, so there is no reason to incur the extra time penalty involved with compiling the modules on startup. However, for some reason (that I genuinely can’t remember) the compiled JS files have to at least exist, even if they aren’t the latest ones. That’s why the modules are compiled the first time you run the application.

You might think this leaves you in a bit of a pickle if you use a normal browser instead of hosted mode, but you can easily recompile the modules with the grails compile-gwt-modules command.

Variations on the theme

When you inherit the SmartGwt module, your host page is automatically populated with all the required JS and CSS links for the default skin. You can gain a bit more control by inheriting SmartGwtNoTheme, which allows you to specify a different theme in the host page, or SmartGwtNoScript, which allows you full control over the JS files that are included as well as the theme. The showcase example for SmartGWT demonstrates the use of SmartGwtNoScript – note how much more you have to add to the host page!

That’s it for now. I may do more work with SmartGWT in the future. If so, I’ll post anything I find useful.