GWT Plugin for Grails 0.4-SNAPSHOT

I 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.

18 thoughts on “GWT Plugin for Grails 0.4-SNAPSHOT

  1. John Rellis

    Sweet! Great work if this doesn’t break applications running with the previous plugin, thats always nice, and we can now use GWT 1.6, sounds like Christmas? 🙂 GWT is a great client platform for Groovy/Java people struggling with Ajax/Javascript, and the fact that Grails is embracing it so strongly is only a good thing, especially since I work almost 100% in Grails and GWT these days! Keep it up!

  2. Peter Post author

    @Dirnov London

    @Sakuraba It depends what feature you mean. The RPC interface generation is now manual only – you have to run the generate-gwt-rpc command.

  3. errormsg

    grails run-gwt-client
    Found events script in plugin gwt
    java.lang.NullPointerException
    at java.io.File.(File.java:222)
    at InstallPlugin.run(InstallPlugin:43)
    at InstallPlugin$run.call(Unknown Source)
    at _PackagePlugins_groovy$run.call(Unknown Source)
    at _Events.run(_Events.groovy:1)
    at _PluginDependencies_groovy$_run_closure26.doCall(_PluginDependencies_groovy:964)
    at _PluginDependencies_groovy$_run_closure26.call(_PluginDependencies_groovy)
    at _GrailsPlugins_groovy.completePluginInstall(_GrailsPlugins_groovy:80)
    at _GrailsPlugins_groovy.this$4$completePluginInstall(_GrailsPlugins_groovy)
    at _GrailsPlugins_groovy$this$4$completePluginInstall.callCurrent(Unknown Source)
    at _GrailsPlugins_groovy.withPluginInstall(_GrailsPlugins_groovy:68)
    at _GrailsPlugins_groovy.this$4$withPluginInstall(_GrailsPlugins_groovy)
    at _GrailsPlugins_groovy$_run_closure4.doCall(_GrailsPlugins_groovy:60)
    at _GrailsPlugins_groovy$_run_closure4.call(_GrailsPlugins_groovy)
    at _GrailsPlugins_groovy$_run_closure5.doCall(_GrailsPlugins_groovy:110)
    at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:324)
    at gant.Gant$_dispatch_closure6.doCall(Gant.groovy:334)
    at gant.Gant$_dispatch_closure6.doCall(Gant.groovy)
    at gant.Gant.withBuildListeners(Gant.groovy:344)
    at gant.Gant.this$2$withBuildListeners(Gant.groovy)
    at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
    at gant.Gant.dispatch(Gant.groovy:334)
    at gant.Gant.this$2$dispatch(Gant.groovy)
    at gant.Gant.invokeMethod(Gant.groovy)
    at gant.Gant.processTargets(Gant.groovy:495)
    at gant.Gant.processTargets(Gant.groovy:480)

  4. Sakuraba

    >> The RPC interface generation is now manual only

    Great!

    Why is it better to use a GwtController then a plain old service?

  5. Alexander

    If you get that null pointer exception, make sure you have a GWT_HOME variable set. I was getting that until I set the variable.

  6. John Rellis

    Hi Peter,
    I was upgrading a Grails App that uses GWT from grails 1.0.5 to grails 1.1.1 today and noticed that running “grails upgrade” from the command line just deleted my src/gwt folder… have you ever come across this??? Pretty serious if you are happy go lucky and don’t backup before upgrading…
    Let me know if i should open a Jira???
    Thanks,
    John

  7. Peter Post author

    I’m not quite sure I understand your last comment – does it invalidate the previous one? I haven’t been able to reproduce grails upgrade deleting the src/gwt directory myself.

  8. John Rellis

    sorry peter, yes consider the last comment invalidated. I copied the project to a new location to perform the upgrade and for some reason windows did not copy the gwt folder, my mistake. Thanks for getting back to me, and sorry for the confusion!

  9. Do

    Hi Peter,
    I’m new to Grails. I don’t understand the advantage of having url mapping even though the rpc will continue to execute the Service. Basically, how does going through the “grails dispatch logic” make any difference in the result that the Service will send back?
    Thanks!

  10. Peter Post author

    There are a couple of significant advantages. The first one is that a Hibernate session is opened up for you for the duration of the request. That means you don’t have to use a transactional service. In other words, you’ll get the behaviour you’re used to from controllers.

    The second advantage is that you can map your RPC requests to any URL you like. Unfortunately, GWT.getModuleUrl() is the only GWT method that will return the servlet context, but it also returns the module part. That makes it more difficult to use an alternative URL for RPC. I haven’t come up with a solution to this problem yet, so I’m open to suggestions.

    All that said, using the Grails dispatch logic has no effect on the result returned by the service.

  11. Do

    Interesting! Thanks for the quick response. I’ve been trying out Acegi plugin along with the GWT plugin. The Acegi plugin generates login/registration/security code in the controller. Unfortunately, I read that the Service shouldn’t call the controller. To work with the GWT plugin, should I port the controller codes to the Service? From an architectural view, should these code be separated from the regular Service code that are not tied in with GWT (i.e. gsp pages that go through the controller rather than GWT RPC calls).

  12. Peter Post author

    @Do You can use the login and registration views with your GWT application. You don’t have to turn them into GWT UIs. Also remember that the Acegi/Spring Security plugin applies the access control via a servlet filter (if I remember correctly), which is active for your GWT-RPC calls. That said, you might want to use Spring Security annotations to protect the services directly.

Leave a Reply

Your email address will not be published. Required fields are marked *