(Quick Reference)

The RAP Widget Toolkit (RWT) for Grails - Reference Documentation

Authors: Benjamin Wolff

Version: 1.0.1

1 Introduction

This plugin integrates the RAP Widget Toolkit (RWT) - a web-based Ajax/JavaScript widget library similar to SWT - into your Grails application.

RWT is the web UI part of the Remote Application Platform (RAP) - an application framework based on the Eclipse platform. RWT is provided in standalone mode by this plugin, without the full RAP workbench or OSGi. Besides the SWT API, you can use the JFace API to build your user interfaces.

RWT enables you to create highly interactive, desktop-like Ajax interfaces by only writing Java/Groovy code. In contrast to the popular Google Web Toolkit (Grails plugin), RWT is not compiled to JavaScript, but provides its own set of JavaScript widget that communicate transparently with your server-side code. Since basically everything happens on the server-side (besides the rendering in the browser), it is not necessary to use DTOs or other transfer objects to display the data on the client. The domain objects can be seamlessly used in the UI logic (e.g. via DataBinding).

For more information please refer to the documentation of the particular technology.

The following pages will provide you with the necessary information to get started with Grails and RWT. Have fun!

Grails & RWT Version

The plugin requires at least Grails 2.0 and was currently build using Grails 2.2.3. The current version of this plugin ships with RWT 2.1 by default, but later RWT versions can be configured instead.

License

This plugin and its sources are made available under the terms of the Apache License, Version 2.0.

The packaged RWT and JFace binary libraries in this plugin are made available under the terms of the Eclipse Public License, Version 1.0.

Acknowledgments

I'd like to give big thanks to the developers and the community of Grails and RAP/RWT for making these wonderful technologies possible and for providing it for free! Keep up the excellent work!

1.1 Known/Open Issues

Please file any issues/requests/ideas in the GitHub issue tracker.

1.2 Release Notes

  • November 27, 2013
  • June 26, 2013
    • 1.0 release
    • Added support for configuring more RWT application aspects (e.g. themes).
    • Updated to use the RWT 2.1 final release.
    • RWT dependencies are now resolved from the Maven central repository.
    • Improved developer's guide.
  • November 18, 2012
    • First 0.1 release

2 Getting Started

This short guide will get you started with all you need to know to create your first Grails-RWT application. You should be familiar with how to create a Grails application and artifacts like domain classes and services.

The RWT setup process is based on the standalone guide. However, the Grails-RWT plugin does most of the setup for you, as you will see in this guide.

Start with creating an example Grails application and then follow the instructions below. The next sections assume that the applications is called grails-rwt-example. Replace the occurences in the example URLs with the actual name of your example application.

Example Code

There is an example project available on GitHub that can be used as a kickstart. It contains the example code shown in this guide and is properly configured to get started immediately.

git clone https://github.com/bwolff/grails-rwt-example

After you checked out the project you can inspect the code and start the application as described in the Running the Application section below.

2.1 Installation

The plugin is installed using the default Grails plugin installation mechanism. Simply add/modify the following lines to the plugin dependency section in the grails-app/conf/BuildConfig.groovy file:

grails.project.dependency.resolution = {

plugins { // Other plugin dependencies

compile ':rwt:1.0' } }

The plugin will be installed automatically on the next invocation of a Grails command. Your IDE (e.g. STS/GGTS) should also pick up the new installed plugin and should make the contained jar libraries available in your Grails project.

2.2 Creating the Entry Point Bean

The first step is to create a so called RWT entry point class. An instance of this class needs to be registered as a Spring bean to be picked up by the RWT configuration. The suggested approach is to use a Grails service for that. Being a Grails artifact, a service is registered as a Spring bean by default and other dependencies and functionalities are added/injected out of the box.

The following code snippet shows an example entry point service implementation (in the grails-app/services sub-folder). To demonstrate the usage, another service (FooService) and a domain class (Foo) are used. They don't do anything useful and their code can be obtained from the example application, as described above. The comments in the code snippet highlight interesting points.

package grails.rwt.example

import org.eclipse.jface.layout.GridDataFactory import org.eclipse.jface.layout.GridLayoutFactory import org.eclipse.jface.viewers.ArrayContentProvider import org.eclipse.jface.viewers.LabelProvider import org.eclipse.jface.viewers.ListViewer import org.eclipse.rap.rwt.application.EntryPoint import org.eclipse.swt.SWT import org.eclipse.swt.events.SelectionAdapter import org.eclipse.swt.events.SelectionEvent import org.eclipse.swt.widgets.Button import org.eclipse.swt.widgets.Composite import org.eclipse.swt.widgets.Display import org.eclipse.swt.widgets.Label import org.eclipse.swt.widgets.Shell

// "Note the use of the Groovy syntax"

class HelloEntryPointService implements EntryPoint { // "The service needs to implement EntryPoint"

def fooService // "Other services will get injected by Grails"

@Override public int createUI() { log.info("Creating RWT UI ...") // "Implicit logger object"

Display display = new Display() Shell shell = new Shell(display) shell.setText("Hello RWT!") GridLayoutFactory.swtDefaults().applyTo(shell)

final Label label = new Label(shell, SWT.NONE) GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(label)

// "JFace is available" ListViewer viewer = new ListViewer(shell, SWT.V_SCROLL | SWT.H_SCROLL) GridDataFactory.swtDefaults().hint(500, 300).applyTo(viewer.list) viewer.contentProvider = ArrayContentProvider.instance viewer.labelProvider = new LabelProvider() viewer.input = Foo.list() // "Use domain objects and GORM, no DTOs required!"

Button button = new Button(shell, SWT.PUSH) GridDataFactory.swtDefaults().align(SWT.BEGINNING, SWT.CENTER).applyTo(button) button.text = "Click me!" button.addSelectionListener(new SelectionAdapter() { Integer num = 0

@Override public void widgetSelected(SelectionEvent e) { label.text = fooService.serviceMethod(num++) // "Call methods of other services" } })

// "Open the shell and start the UI event handling queue" shell.pack() shell.open()

while(!shell.isDisposed()) { if(!display.readAndDispatch()) { display.sleep() } } display.dispose()

return 0; } }

According to the Grails conventions, a Spring bean called helloEntryPointService will be registered automatically on application start. The next step is to configure our newly created entry point.

The given code snippet is just a very simple example to demonstrate the usage. You should develop your application using a cleaner separation of concerns, i.e. by employing the MVC or MVP pattern.

2.3 Configuring the Entry Point

The only thing that is missing now is the configuration of our new RWT entry point. This is done in a configuration block in the grails-app/conf/Config.groovy file.

// RWT configuration
rwt {

// Entry points configuration entrypoints {

// Configuration of an entry point named 'hello', the relative URL path will be '/hello'. hello { bean = 'helloEntryPointService' // The name of the entry point bean (required) pageTitle = 'Hello RWT!' // The browser title that will be displayed (optional) } } }

Here we simply specify our entry point as a block under entrypoints and provide the name of the entry point bean, which is described above. We can also specify a string that will be displayed as the browser's page title.

More information about the configuration of the RWT application and the entry points is available here.

2.4 Running the Application

The application can be started in a local development setup using the default run-app Grails command from the command line in the project root folder:

grails run-app

After the application has been started you should be able to access your first Grails-RWT example under the following URL: http://localhost:8080/grails-rwt-example/hello

2.5 Deploying the Application

You can now package your application into a WAR file and deploy it to the servlet container of your choice. The deployment procedure is the same as for a default Grails application, by simply issuing the following command in the command line:

grails war

The resulting WAR file is created in the target/ sub-folder and can now be deployed to e.g. a Tomcat container. All necessary jar files for RWT/JFace will be packaged and the web.xml will also be properly set up.

Congratulations! You should now be able to create a more sophisticated Grails-RWT applications and explore the features that RWT provides.

3 Configuration

The RWT configuration goes into a special block in the grails-app/conf/Config.groovy file.

rwt {
    // RWT configuration goes here.
}

There are different aspects that can be configured, the global RWT application settings, the entry point settings, and the theme settings.

For more information about RWT in general please have a look at the RAP/RWT 2.1 developer's guide.

Classpath Resources

Some configuration settings (e.g. theme CSS files) expect a relative path to a file that is visible on the classpath. The easiest way is to put your static file resources in a sub-folder of src/java or src/groovy of your Grails application. This way the files are available in the classpath without any additional configuration.

This also enables you to reference files that are provided in the classpath by other plugins or libraries.

3.1 Application Configuration

There are a few configuration settings available that configure global aspects of a RWT application. Currently, all the documented settings here are optional. Therefore, you don't have to specify any of them if you don't have any special requirements.

The global RWT configuration go directly into the rwt configuration block in the Config.groovy:

rwt {
    // Global RWT application configuration goes here.
}

The currently supported settings are:

  • operationMode - The RWT operation mode as a string (optional) . Currently supported values are 'JEE_COMPATIBILITY' (default) , 'SWT_COMPATIBILITY', and 'SESSION_FAILOVER'.
  • phaseListeners - A list of either Class instances or the names (string) of a registered Spring bean that implement the PhaseListener interface (optional) . In case a Class instance is used the class needs to have a public default constructor without arguments. The list can also contain Class instances and bean names at the same time.
  • themableWidgets - A list of Class instances of themable custom widgets (optional) . For more information about custom widgets please see the RWT documentation and the RWT JavaDocs.

The following snippet shows an example configuration of all currently available RWT application configuration values:

rwt {
    operationMode = 'SWT_COMPATIBILITY' // "Required to use blocking SWT/JFace APIs like Display#sleep()"
    phaseListeners = [org.example.MyPhaseListener, 'myPhaseListenerBean'] // "Class instances and bean names can be mixed."
    themableWidgets = [org.example.MyThemableWidget1, org.exampleMyThemableWidget2]
}

3.2 Entry Point Configuration

An RWT application can consist of one or more entry points. Each entry point is configured as a configuration block within the rwt section.

rwt {
    entrypoints {
        hello {
            bean = 'entryPointBean'
            …
        }
    }
}

The given example configures an entry point with the name hello. By default, this entry point will be mapped to the relative URL path '/hello'. The following settings need to be provided for an entry point configuration:

  • bean - The name (string) of the registered Spring bean that implements the EntryPoint interface (required) .
  • pageTitle - The title (string) that will be displayed as the browser's title (optional) .
  • favicon - Relative path to an .ico image that will be used as the favicon for the entry point (optional) .
  • themeId - The ID of the registered theme (optional) . Please see the theme configuration section in this guide.
  • headHtml - Relative path to a file containing HTML (optional) . The content of the file will be added to the <head> element of the host page. Please see the RWT JavaDocs for more information.
  • bodyHtml - Relative path to a file containing HTML (optional) . The content of the file will be added to the <body> element of the host page. Please see the RWT JavaDocs for more information.

A Grails-RWT application can contain an arbitrary number of entry points, which usually refer to different entry point beans.

rwt {
    entrypoints {
        hello {
            bean = 'helloEntryPoint'
            …
        }

helloAgain { bean = 'helloAgainEntryPoint' … } } }

In this example there will be two entry points accessible under '/hello' and '/helloAgain'. For customizing the default URL mapping behaviour please see the Advanced Topics chapter.

Shown below is an example with all currently available entry point configuration values:

rwt {
    entrypoints {
        hello {
            bean = 'helloEntryPointService'
            pageTitle = 'Hello RWT World!'
            favicon = 'icons/favicon.ico'
            themeId = 'mytheme'
            headHtml = 'html/head.html'
            bodyHtml = 'html/body.html'
        }
    }
}

3.3 Theme Configuration

The plugin supports a simply configuration of RWT themes and theme contributions that can be used in the entry point configuration. The themes are provided via CSS files and configured via relative paths in the application's classpath. Shown below is an example theme configuration:

rwt {
    themes {
        rwtdefault = 'themes/default.css'
        mytheme = 'themes/mytheme.css'
        mytheme2 = ['themes/mytheme2.css', 'themes/mytheme3.css']
    }
}

Themes are configured in the themes block, each entry in this block represents a different theme, the name of the entry is the theme ID that is used to reference it in the entry point configuration. A special theme name is rwtdefault. This name references the default RWT theme and the CSS files provided for this name are treated as contributions and will be merged into the RWT default theme. Additions to this theme are automatically applied to your widgets without the need to add a theme configuration to your entry point. The example shown above also creates the two custom themes with the ID mytheme and mytheme2.

As mentioned before, the values of the themes are paths denoting a CSS file on the classpath. The value can be a single path string or a list of path strings. In case a list of paths is provided, the first file will be used as the main theme file and the subsequent files are treated as contributions to this theme file. The order in which they are specified determine the order in which the contributions are applied. This mechanism allows it to enhance your own themes with theme additions coming from other plugins or libraries, as long as the CSS files are accessible via the classpath.

For more information about theming in RWT and what widgets and properties are supported in the CSS please refer to the RWT theming reference.

3.4 Logging Configuration

The plugin logs some information in the INFO and DEBUG levels. To increase the verbosity of the log messages you can enable the debug level for some plugin artifacts. Add the following lines to the log4j section of your Config.groovy file:

log4j = {
    // Other logging configurations

debug 'grails.app.conf.RwtPluginBootStrap' debug 'grails.plugins.rwt' debug 'grails.rwt' debug 'RwtGrailsPlugin' }

3.5 RWT Version Configuration

The current version of the plugin is based on RWT version 2.1. The required libraries are resolved from the Maven central repository using the default Grails dependency mechanism (Ivy). An application can override these dependencies manually to use a more recent version of RWT. This can be useful to test new milestone releases or use new service releases without having to wait for a new release of the Grails-RWT plugin.

The internal mechanisms of the Grails RWT plugin are currently based on the API of version 2.1. If you use a new RWT version that comes with breaking API changes the plugin won't work anymore. In order to use the latest RWT version in this case a new release of the Grails RWT plugin is necessary.

Here is an example configuration in the BuildConfig.groovy to use the RWT 2.2 milestone release:

grails.project.dependency.resolution = {

dependencies { compile('org.eclipse.rap:org.eclipse.rap.rwt:2.2.0-M1') compile('org.eclipse.rap:org.eclipse.rap.jface:2.2.0-M1') compile('org.eclipse.rap:org.eclipse.rap.jface.databinding:2.2.0-M1') } }

The RWT JFace libs require three additional dependencies which are currently not present in the Maven central in the required version. Therefore, these dependencies are bundled in the lib folder of the RWT plugin. If you manually configure a newer RWT JFace version, you should make sure that the provided dependencies still satisfy the required version range of the RWT JFace libs. If they require new versions of the dependency you could grab the libs i.e. from the RAP target platform and put those in the lib folder of the project, so that they override the outdated versions provided by the RWT plugin.

4 Advanced Topics

Custom URL Mapping of Entry Points

By default RWT entry points are mapped to their name under the applications base URL. If the application name would be 'foo' and the entry point name 'hello', the URL would look like this: http://server/foo/hello

Sometimes it may be desired to reach the entry point under the base URL or a different URL. This can easily be achieved by using the Grails URL Mappings. To map the entry point to the base URL, the following needs to be configured in the grails-app/conf/UrlMappings.groovy file:

class UrlMappings {

static mappings = { // Other mapping configurations

"/"(uri: "/hello") } }

Now the RWT application is reachable via: http://server/foo