Using the GWTSpringController
 

This section describes the GWTSpringController which is now replaced by the GWTHandler and the GWTController

Depending on your background and expertise in GWT and Spring the post may still be worth reading since it shares a few thoughts on why and how to integrate GWT with Spring, the benefits of doing so and it describes the Demo application that comes with GWT-SL.

Why Spring?

    The Spring Framework is an established component framework for web applications that span authentication, database access and complex page flow. Through its aspect oriented approach it is unobtrusive and cleanly separates the presentation layer  from the business logic and the data model, allowing for back end services which have nothing to do with the way the presentation is rendered.

    This is the ideal base for a GWT application, which also separates the presentation (your widgets that run in the browser) from the business logic (your RPC services running on the webserver) from the data model (the objects serialised over RPC).

    By default, GWT binds java methods to RPC calls and uses the Servlet API for this, so that each service you write is a servlet.  The Servlet API however is rather crude and the servlet container (like Tomcat) is a gross environment providing little assistance to elaborate tasks like transaction management, AOP tasks (authentication, logging, per-task caching) etc. Also the notoriously scarce configuration abilities are by far inferior to Spring's XML configuration and bean injection which allows even the most complex configurations by plugging objects together in XML. 

 Using the demo 

    Following popular demand, I wrote a small calculator, covering basic arithmetic operations as a demo web application  which demonstrates the deployment of a GWT application that talks to a Spring service via RPC.

    In order to run the demo, all you will need a Tomcat installation (see the side bar) and the GWT 1.1.0. The archive contains the ready-to-run calculator.war file.

    After deploying it (you should not see any exceptions) navigate to http://localhost:8080/calculator/static/springtest.Calculator/Calculator.html

    The demo starts with two popups informing about whether the RPC service was found - it normally should. After that, you can play around with the calculator. A brief glance at the CalculatorWidget class reveals that nothing fancy is going on: it just invokes the corresponding service and displays the calculation result.

 How does it work?

    The GWT Widget Library contains the GWTSpringController, an abstract Spring Controller which assumes the entire GWT-RPC functionality from within the Spring environment,  allowing you to harness the full range of Spring services available to its controllers, such as proxying certain method invocations with database transactions or providing context beans to your service.

    This does not affect in any way the code you run on the client i.e. the browser. Conceptually and technically, a GWTSpringController is a fully capable GWT RPC service and there is no way the client could even know you are using Spring (remember I said it's unobtrusive?).

    On the server side however, nothing is the same anymore: the RPC service is demoted from a full Servlet to a Spring managed Controller. Thus in web.xml you don't anymore declare your service (which used to extend the RemoteServiceServlet) anymore, but Spring's DispatcherServlet like this:

    <servlet>
        <servlet-name>calculator</servlet-name>
        <servlet-class>

org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>calculator</servlet-name>
        <url-pattern>
/calculator.srv</url-pattern>
    </servlet-mapping>

  Supposed the application is deployed under http://localhost:8080/calculator the service is herewith declared to run under http://localhost:8080/calculator/calculator.srv 

The RPC service itself (the CalculatorController implementing the CalculatorService) is instantiated  in calculator-servlet.xml and bound to the URL as in:

    <bean id="urlMapping"
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
              <prop key="/calculator.srv">CalculatorController</prop>
            </props>
        </property>
    </bean>

<bean id="CalculatorController" class="springtest.impl.CalculatorController"
/>

 

Obviously it is possible to create more services, instantiate them as controllers and map them to different URLs. All you would do is add more

<bean id="idOfOtherController" class="my.other.Controller"/>

and then a mapping :

<property name="mappings">
    <props>
        <prop key="/someOtherURL">idOfOtherController</prop>
    </props>
</property>

Otherwise nothing interesting is going on, just a reminder because it is easy to forget: the service lookup in the entry point must of course point to the right URL, in the demo's ApplicationEntryPoint this is:

    CalculatorServiceAsync service = (CalculatorServiceAsync) GWT
        .create(CalculatorService.class);

    ServiceDefTarget target = (ServiceDefTarget) service;

    target.setServiceEntryPoint("../../calculator.srv");



 Appendix: Building the Demo

    If you want to build the calculator web application yourself, you can use the Ant build. This requires you to copy the GWT compiler JARs and DLLs to the dependencies folder, which is not included due to subtleties in the GWT licence.

 Appendix: Debugging hosted mode 

    A sticky topic is debugging the client code in hosted mode, since now the client connects not to the internal Tomcat server which by the hosted browser launchs, but to an external Tomcat running in a different JVM. The Ant build includes a proof-of-concept on how to run the hosted browser in debug mode... just that it does not prove anything, since even if you run the Ant task in debugging mode, it spawns a new JVM which does not run in the debugger. It is just there to show you which arguments you should use.

    But no worries, there is a solution and it's included in the archive you downloaded in the form of an Eclipse launch configuration in the file hostedmode.launch. For this to work, you must copy the GWT compiler dependencies (namely gwt-dev-xxx.jar, gwt-user.jar and the DLLs) to the dependencies folder under the project folder (which is by default empty). Then you can run the hosted mode browser from inside Eclipse and even debug it.