-
The Command Pattern with the Grails GWT Plugin
Posted on August 31st, 2009 37 commentsA talk by Ray Ryan of Google at the 2009 Google IO conference has caused a bit of a buzz in the GWT community. In that talk, Ray recommends several design patterns that will help make your projects more manageable as they grow in size. The particular suggestion I’ll be focusing on in this post concerns using the Command Pattern for server requests.
The idea is to encapsulate the stuff you want the server to do for your client in command or action objects instead of using standard service methods. For example, rather than calling a search() method on a remote service, you have a search object that gets sent to the server and the server returns the corresponding result or response object. By using this pattern, you can effectively implement caching, batching, undo/redo, etc. See Ray’s presentation for a bit more info on this.
One ready-made implementation of the pattern for GWT is the gwt-dispatch library. I considered integrating this into the Grails plugin, but its server-side components weren’t really suitable for a Grails project. Anyway, I wanted to write something myself so I could better understand what the implementation should do. The result is the plugin’s new action framework, which you can test out with an intermediate release of the plugin.
Getting started
Using the framework is simplicity itself. Let’s say you want to implement a search action. You first create the appropriate classes for it by running a new Grails command:
This will create the following files:
grails create-gwt-action org.example.myapp.Search
- src/java/org/example/myapp/client/SearchAction.java
- src/java/org/example/myapp/client/SearchResponse.java
- grails-app/actionHandlers/org/example/myapp/SearchActionHandler.groovy
The action and response classes represent the request and response data respectively. Both of them implement Serializable, so they have to have a default constructor (which can be private) and can only contain other serializable data. Note that they are added to the client sub-package of the package you specify, because they are used on the client was well as the server.
The action handler is an instance of a Grails artifact type added by the plugin. Its role is to process actions and return the appropriate responses. It would typically offload the majority of the work to a standard Grails service that could then be used by other code, such as a REST or web services interface.
The code
Update I have updated the plugin packages in the following examples, so “org.grails.” is now just “grails.” The change was made for the final release of version 0.5.
The action object should contain only the information necessary to complete the request. Remember, it’s a data object and typically won’t have any behaviour. In the case of our search action, we might need a query string and the maximum number of results the search should return:
package org.example.myapp.client; import grails.plugins.gwt.client.Action; public final class SearchAction implements Action<SearchResponse> { private static final long serialVersionUID = 1L; private String query; private SearchAction() {} public SearchAction(String query) { this.query = query; } public String getQuery() { return query; } }Likewise, the response should only contain the data required by the client:
package org.example.myapp.client; import java.util.ArrayList; import java.util.Collections; import java.util.List; import grails.plugins.gwt.client.Response; public class SearchResponse implements Response { private static final long serialVersionUID = 1L; private ArrayList<Long> ids = new ArrayList<Long>(); private SearchResponse() {} public SearchResponse(List<Long> ids) { this.ids.addAll(ids); } public List<Integer> getIds() { return Collections.unmodifiableList(this.ids); } }All very straightforward so far. The final step is to implement the action handler. As I said, this typically offloads the work to a service and in our example we will make use of a search service:
package org.example.myapp import org.example.myapp.client.SearchAction import org.example.myapp.client.SearchResults class SearchActionHandler { SearchService searchService SearchResponse execute(SearchAction action) { def results = searchService.executeSearch(action.query) return new SearchResponse(results) } }As you can see, all the action needs to do is unwrap the action and create the response. Everything else is handled by the search service. We haven’t even needed to expose a service via GWT! That’s all you need to do on the server side, which just leaves the question of how you execute an action from the client.
On the client
The plugin comes with a dedicated GWT RPC service that you can use to dispatch all your actions: GwtActionService. All you have to do in your GWT code is create the service, instantiate your action, and then call the execute() method:
... import grails.plugins.gwt.client.GwtActionService; import grails.plugins.gwt.client.GwtActionServiceAsync; ... protected void doSearch(String query) { GwtActionServiceAsync service = GWT.create(GwtActionService.class); ((ServiceDefTarget) service).setServiceEntryPoint(GWT.getModuleBaseURL() + "rpc"); service.execute(new SearchAction(query), new AsyncCallback<SearchResponse>() { public void onFailure (Throwable caught) { ... } public void onSuccess (GetRecentResponse result) { ... } }); }You could even wrap the action service with another implementation that does caching and/or batching of commands.
If you use Google Gin, you can simplify your code by having the action service injected into the classes that need it. Simply add something like this to your Gin module definition:
... import grails.plugins.gwt.client.GwtActionService; import grails.plugins.gwt.client.GwtActionServiceAsync; public class MainModule extends AbstractGinModule { protected void configure() { ... } @Provides @Singleton GwtActionServiceAsync provideGwtActionService() { GwtActionServiceAsync service = GWT.create(GwtActionService.class); ((ServiceDefTarget) service).setServiceEntryPoint(GWT.getModuleBaseURL() + "rpc"); return service; } }Since GwtActionService is provided by the plugin, you also need to configure your module to inherit from the plugin’s (new) module:
<module> ... <inherits name="grails.plugins.gwt.Grails"/> ... </module>I think this is a really clean approach to GWT RPC that reduces the burden on you as a developer. In particular, you no longer have to implement GWT services because you can create simple action handlers instead. Before I implemented this framework, I found that I was creating specific GWT versions of each service. So for example, I had a SearchService and a GwtSearchService, which was pretty inefficient.
I hope you like the new approach!
-
Internationalising your Grails + GWT applications
Posted on August 17th, 2009 2 commentsThe recent 0.4 release of the Grails GWT plugin includes some enhancements in the area of internationalisation (i18n), so now seems like a good time to have a look at how you can add i18n to a Grails/GWT app. This article focuses on the specifics of getting GWT’s i18n support working with Grails, but the GWT website has a useful tutorial if you want more information.
Localising text
Grails and GWT take different approaches to i18n. Both systems are based on properties files with names that follow the usual Java i18n convention for resource bundles, but that’s as far as the similarities go. Grails expects to find the bundles in the grails-app/i18n directory, but GWT looks for them in the module directory structure. With static internationalisation, GWT also requires each property file to have an associated Java interface.
Ideally, you would be able to use the same properties files for both standard GSP pages and GWT code, but the plugin doesn’t support this yet. I don’t even know if it’s possible. Despite that, the plugin does make it easy to get started. Let’s say you have a GWT module org.example.Main that you want to internationalise. The first step is to create the resource bundles that will contain the localised text:
This simple command will generate two files for you:
grails create-gwt-i18n org.example.Main
- src/gwt/org/example/client/MainConstants.properties
- src/gwt/org/example/client/MainMessages.properties
The MainConstants.properties file is for basic localised text, whereas MainMessages.properties contains parameterised messages like “Today is {0,date,medium}” (where {0…} is a message parameter). Other than that, both properties files can be treated as standard Java resource bundles.
So how do you access these messages from your GWT code? By creating Java interfaces based on the entries in the properties files and loading the appropriate implementations for those interfaces using GWT’s deferred binding mechanism. It sounds complicated, but in practice it’s pretty straightforward. The plugin provides a Grails command that will perform the first step of creating the appropriate Java interfaces:
Assuming that you have added some enties to the MainConstants.properties and MainMessages.properties files, this command will create
grails compile-i18n
- src/gwt/org/example/client/MainConstants.java
- src/gwt/org/example/client/MainMessages.java
In fact, you don’t even need to run this command explicitly because the plugin will run it automatically before compiling the GWT modules.
Both the *Constants and *Messages interfaces contain methods named after the keys in the corresponding properties files. For example, an entry cancelLabel will result in a method cancelLabel(). In the Java world, developers commonly use ‘.’ as a separator in resource bundle keys. You can do this with GWT too, but you end up with underscores in the method names. For example, cancel.label becomes cancel_label(). In other words, the generated methods don’t follow the Java convention. Whether that’s an issue is really down to you.
Now that you have the i18n interfaces, you can start replacing hard-coded text in your GWT UI with localised text. You first need to load the appropriate i18n classes:
public class Main implements EntryPoint { private MainConstants constants = GWT.create(MainConstants.class); private MainMessages messages = GWT.create(MainMessages.class); ...You can now call the methods on the constants and messages objects to get the localised text:
public class Main implements EntryPoint { ... Button saveButton = new Button(constants.save_label()); Button saveButton = new Button(constants.cancel_label()); ... // Report an error RootPanel.get("errorMessage").add(new HTML(messages.msg_upload_fail(filename))); }You can also see in the above example how you pass parameters to a message as simple method arguments.
Adding locales
That’s almost all there is to it. Your application will now work with the default locale. To add extra locales, though, requires a few more steps. First off, you need to create the language-specific resource bundles with the translated text. Say we want to display the application in French. We create the files
- src/gwt/org/example/client/MainConstants_fr.properties
- src/gwt/org/example/client/MainMessages_fr.properties
and add the French versions of all the messages there. Next, we need to inform GWT of the new locale by adding the following line to the module file:
<module> ... <!-- Supported languages --> <extend-property name="locale" values="fr"/> </module>That’s it! Your users can now view the application in French.
Setting the locale
The application is now localised, but how do you pick which locale to display? The simplest approach is to add a “locale=…” query parameter to the application’s URL. GWT picks up that parameter and loads the appropriate resource bundles. Unfortunately, this doesn’t work so well with Grails because it uses a different query parameter: “lang=…”.
Another issue is that you have to add the “locale” query parameter to any internal links so that the correct locale is propagated to the different pages. This is a pretty ugly and error-prone approach.
Have no fear! There is a simple solution. Simply add the following meta tag either to your GSP pages or, even better, your layouts:
<%@ page import="org.springframework.web.servlet.support.RequestContextUtils" %> <html> <head> ... <meta name="gwt:property" content="locale=${RequestContextUtils.getLocale(request)}"> </head> ... </html>Not only will this ensure that GWT uses the same locale as Grails, but the locale will also be retained between pages and modules. To change the locale to French, all you have to do is load the application with the query parameter “lang=fr”. Next time you reload the page without the query parameter, it will still be in French! The same when you navigate to a different URL with the application. Now that’s what I call a result.
Have fun internationalising your Grails/GWT apps!
-
Grails JSecurity Plugin version 0.4 released
Posted on August 6th, 2009 15 commentsI have finally released version 0.4 of the Grails JSecurity Plugin – see the release notes for more details.
This will be the last release under this name because JSecurity was renamed to Apache Shiro. All future work will now be done on the Shiro Plugin. You can already install a 1.0-SNAPSHOT version that is basically the JSecurity Plugin 0.4 rebadged.
Wildcard permissions
The most significant change in version 0.4 is native support for JSecurity’s WildcardPermission. “What’s that?” I hear you cry. A permission in JSecurity serves two purposes:
- it is a representation of a right or privilege that is required to access something, such as a document or a printer
- it represents one or more rights or privileges that a particular user has
So in order for a user to access a secured resource, his assigned rights must match (or “imply”) those required by the resource.
JSecurity implements permissions via an interface, called unsurprisingly Permission. You can create any type of permission you like, as long as it implements that interface. Objects get a bit clunky, though, when you start dealing with declarative access control. Consider this example access control filter:
import org.jsecurity.grails.JsecBasicPermission class SecurityFilters { def filters = { main(controller: "*", action: "*") { before = { accessControl { permission(new JsecBasicPermission(controllerName, actionName)) } } } } }This example ensures that each controller action requires the user to have a permission specific to the controller name and action name. As I said, it’s clunky.
WildcardPermission is an implementation of the Permission interface that uses a single string to describe an arbitrary permission. The string must follow a certain pattern in order for the permission to work properly, but this is best demonstrated by example. Let’s take the previous example and modify it to use a wildcard permission:
class SecurityFilters { def filters = { main(controller: "*", action: "*") { before = { accessControl { permission("$controllerName:$actionName") } } } } }We have managed to do away with the import and the permission requirement is now a simple string. The important thing to notice is that the controller and action names are separated by a colon, ‘:’. Each substring separated by a colon is called a part. As far as JSecurity and the WildcardPermission implementation are concerned, these parts have no inherent meaning. They don’t know that the first part is a controller name or that the second part is the name of an action. It’s up to the application to give the parts meaning and interpret them.
Of course, I’ve only shown you a permission requirement. How do you assign such a permission to a user? Well, assuming that you are using the default database realm that comes with the plugin, the code you need will look something like this:
class BootStrap { def init = { servletContext -> ... // Wildcard permissions. def wildcardPermission = new JsecPermission(type: "org.jsecurity.authz.permission.WildcardPermission", possibleActions: "*").save() new JsecUserPermissionRel(user: user1, permission: wildcardPermission, target: "book:list,show", actions: "*").save() new JsecUserPermissionRel(user: user2, permission: wildcardPermission, target: "book:*", actions: "*").save() ... } }As you can see, you must first create an instance of the JsecPermission domain class for WildcardPermission. You can then link this permission to users via the JsecUserPermissionRel domain class. The target contains the permission string, while the actions property is ignored.
If you take a look at the first permission assignment, you’ll see that it allows the first user to access the list and show actions on the book controller. Notice how the assignment includes the names of two actions? These are sub-parts and they are separated by commas. It’s very unusual to see sub-parts in a permission requirement, but they are common in permission assignments like this. The second user has access to all the actions courtesy of the wildcard ‘*’.
In fact, you can have as many parts and sub-parts as you need. For example, we could add an extra part to the above permissions that represented a domain instance ID.
If you want to learn more about the rules that determine whether one permission string implies another, then take a look at the Javadoc for WildcardPermission. That’s all for now folks!
-
GWT Plugin for Grails 0.4-SNAPSHOT
Posted on July 23rd, 2009 18 commentsI have just released a new interim version of the GWT plugin for Grails. The main changes are:
- it works with GWT 1.6 properly
- GWT client requests now go through a controller
- new command: clean-gwt-modules
Two of those are pretty self-explanatory, but the second one deserves a closer look.
In the beginning…
The traditional approach to GWT RPC involves creating a servlet that extends GWT’s RemoteServiceServlet class for each remote service in your application. Prior to version 0.4, the plugin used a technique based on that approach but geared towards Grails. Rather than requiring the user to create his own servlets and configure them in the web descriptor, the plugin set up a single servlet (extending RemoteServiceServlet) for each GWT module. The servlets simply forwarded requests to the appropriate Grails service.
This approach worked well, particularly as the user gained all the benefits of using proper Grails services, but it meant that neither URL mappings nor Grails filters took effect. Each module had to send requests to a hard-coded URL: /gwt/<moduleName>/rpc. With the introduction of version 0.4 of the plugin, this has all changed.
Enter GwtController
The custom GWT servlet has gone, disappeared, vanished. In its place you’ll find a new controller: GwtController. It works in a similar way to the old servlet, but because requests now go through the standard Grails dispatch logic, URL mappings and Grails filters can now be used on GWT requests.
You don’t have to do anything special to get the new version of the plugin working with your application because it comes with a URL mapping that matches the old hard-coded URL:
class GwtUrlMappings { static mappings = { "/gwt/$module/rpc"(controller: "gwt", action: "index") } }Note that the above mapping includes a module parameter, but the controller currently doesn’t use it any way. It’s only there so that the mapping behaves the same as the old servlet URLs.
If you want to send GWT requests to a different URL, simply add a new entry to your application’s URL mappings. You will need to map the URL to the same controller and action as shown in the code above.
That’s all there is to it! Please try it out and let me know of any problems.
-
Introducing SmartGWT to Grails
Posted on July 20th, 2009 40 commentsSmartGWT 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?):
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:
grails install-plugin gwt
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:
- grab the SmartGWT distribution from Google Code
- extract the zip file
- create the directory <project>/lib/gwt, for example smart-working/lib/gwt
- 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:
This will create two files under the src/gwt directory:
grails create-gwt-module org.example.SmartButton
- 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:
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.
grails create-gwt-page smart.gsp org.example.SmartButton
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
with
main.draw();
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:
RootPanel.get("main").add(main);
<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.





Social Media