Archive

Posts Tagged ‘AJAX’

Using GWT in an enterprise application

May 19th, 2010 10 comments

I started playing around with Google Web Toolkit (GWT) for building something beyond  the obligatory “Hello World”  and I found many challenges along the way. GWT docs talk a lot about the front-end design and layout. But when it comes to integrating with an enterprise java application, I did not find much by way of pointers or guides. So I took a look under the covers and here’s the gist of that experiment.

When  considering enterprise Java development, the  frameworks/technologies that spring to mind are: Spring (:) and Maven. So I decided to use both in my “Hello Enterprise” application. So in the end, we’ll have an application with the following features:

  • A front-end that is written in Java but runs in Javascript.
  • Makes asynchronous calls to the server and updates the front end.
  • Modular, in that clear separation between the presentation and service layers
  • A multi-module project built with Maven.
  • Can access existing (and new) Spring services.

Before we dive deep, let’s talk a bit about GWT at a high level:

  1. GWT is a Java library that produces Javascript when compiled. The Javascript is bundled in the webapp and invoked via an html page.
  2. The javascipt does the heavy lifting, and is typically used for:
    1. Layout of the page, although it can also be used to replace DOM objects (using id tags) in an “shell” HTML page also.
    2. Making asynch calls to the server
  3. GWT allows users to interact with back-end services in two modes, both asynchronous (doesn’t have to be async, but in todays world of RIA and AJAX, who cares about synchronous UIs!):
    1. Using RPC (Remote Procedure Calls) to access server-side Servlets necessarily served from the same server that is serving the HTML (where the GWT javascript is running).
    2. Using GWT classes in the HTTP package that access the server

So to really get to the bottom of what is GWT and what is not, it will help to build the application in the following stages:

  1. Set up the Eclipse environment
  2. GWT app that only draws out some HTML objects but uses Maven
  3. GWT app that makes a call to a GWT Servlet using RPC
  4. GWT app that makes a call to a plain Servlet using the HTTP package
  5. GWT app that makes a call to a Spring service using RPC
  6. GWT app that makes a call to a Spring service using the HTTP package

With each of these steps(steps 2 thru 6 actually), there’s  a download-able source and binary file that you can follow along with.

Set up the Eclipse environment

Eclipse is the IDE I chose to use for this project just as a convenience. If you prefer to use UltraEdit or Textpad or NotePad, that’s fine, just skip this step.

If you have decided to use Eclipse (and you are not the purist/bare-bones emacs kind of guy ;) , may as well get 2 eclipse plugins to make your life easier:

  • The m2Eclipse plugin – > Among other things, this will cause you to record your dependencies only in one place: the pom, instead of in your project and in Eclipse’s classpath.
  • The google-plugin-for-eclipse -> Although this has many uses including running a light-weight server, the only thing I will use it for is running my GWT code from within Eclipse.

Once you have these plugins, your .project file should look like the following:

<natures>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
</natures>

With the m2eclipse plugin you will see Maven dependencies pulled from the pom.xml instead of the Eclipse classpath like so:

The Google Plugin allows you to specify a Run Configuration for running the GWT application in Development Mode (fka Hosted Mode). The advantage of doing this is that you can debug your presentation layer in Java, and while Firebug is all great and dandy, I find it quite cumbersome compared to debugging in Java.

To configure this Run configuration, you must keep the following in mind:

  • Make sure that the main class is com.google.gwt.dev.DevMode
  • Make sure that the following arguments are specified in the arguments tab:
  • -war C:\<<pathToYourProject>>\target\<<yourProjectArtifactId>>-1.0.0 -remoteUI “${gwt_remote_ui_server_port}:${unique_id}” -logLevel INFO -port 8888  -startupUrl <<thHtmlFileThatMakesTheCallToNocache.js>.html com.acme.web.gwt.Hello

GWT app that only draws out some HTML objects but uses Maven

You can download the application source here and war file here.

As you can see, there’s not much going on here. But is serves as a good starting point to flesh out the pom and project structure. For some reason, the GWT folks place the “war” directory directly under root. The structure proposed by GWT is specified here. This flies in the face of the structure that Maven proposes, especially when building several modules in a multi-module project.

Let’s first check out the project structure of this project in Figure A.


Figure A

The GWT module is defined in Hello.gwt.xml. The GWT classes are all in Hello.java. Besides that, there’s just hello.html, the file where anchorPoints are defined and are referenced in Hello.java. web.xml has no significance besides defining a welcome file.

Note that the name of the javascript file (that is invoked in hello.html) below:

<script type=”text/javascript” language=”javascript” src=”GWTMvnNoRPC/GWTMvnNoRPC.nocache.js”></script>

is based on the name specified in the GWT module definition for rename-to:

<?xml version=”1.0″ encoding=”UTF-8″?>
<module rename-to=’GWTMvnNoRPC‘>
<!– Inherit the core Web Toolkit stuff.                        –>
<inherits name=’com.google.gwt.user.User’/>
–>
<inherits name=’com.google.gwt.user.theme.standard.Standard’/>
<entry-point class=’com.acme.firm.client.Hello’/>
<source path=’client’/>

</module>

And it corresponds to the directory structure that is produced by the build (actually by the gwt-maven-plugin: compile goal):


Figure B

The pom has packaging of type war with just the dependencies defined. Here is where the gwt-maven-plugin is declared. Since there are no interfaces to produce the Asynch version of, the plugin is configured as below:

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<!–  not needed because there is nothing to generate as there is no Service for RPC
<goal>generateAsync</goal>
–>
</goals>
</execution>
</executions>
</plugin>

And that’s about it. Run it by deploying the war file to your favorite app server  and you will see the buttons do nothing and the text goes nowhere!
Let’s make it do something more meaningful by adding some RPC calls.

GWT app that makes a call to a GWT Servlet using RPC

Download the source from here and the war from here.

The project structure is shown below. No surprises here except that we have added a service interface (HelloService.java) and a implementation (HelloServiceImpl.java).


Figure C

Here’s where this graphic come in handy. (Look at the section that says “RPC Plumbing Diagram”). Accordingly, HelloService extends RemoteService and HelloServiceImpl extends RemoteServiceServlet.

Also, the GWT module has included in it’s  <source />  element, the directory that contains both Hello.java and HelloService.java. That is what tells the generateAsync goal of the gwt-maven-plugin that it needs to produce a HelloServiceAsync.java interface. An instance of that interface is invoked by the Hello GWT class.


Figure D

If you look at the HelloServiceAsync.java, you will see that it uses the annotation that you have set in the corresponding interface (HelloService.java) to specify the url that is being sent to the server.

HelloService.java

@RemoteServiceRelativePath(“xyz“)
public interface HelloService extends RemoteService {
public double calculateTax(double income, int year) throws IllegalArgumentException;
}

produces

HelloServiceAsync.java
public static final HelloServiceAsync getInstance()
{
if ( instance == null )
{
instance = (HelloServiceAsync) GWT.create( HelloService.class );
ServiceDefTarget target = (ServiceDefTarget) instance;
target.setServiceEntryPoint( GWT.getModuleBaseURL() + “xyz” );
}
return instance;
}

In this manner you can have many services that can be called by your GWT module.

Note also that the gwt-maven-plugin is configured to drop the async class in the generated-sources directory (the generateSync goal  is bound to the generate-sources phase by default).

Although HelloServiceImpl extends RemoteServiceServlet, it is deployed as a regular servlet in the web.xml. There is nothing GWT-specific in the way it is deployed. However, the fact that it extends RemoteServiceServlet is what (IMO) is the downside of this approach. Either I have to write wrapper servlets that extend RemoteServiceServlet and call my business service layer or I make all my business service objects extend RemoteServiceServlet. Both these options are not very great, which is why you should continue reading to see the other ways we can skin the cat!

GWT app that makes a call to a plain Servlet using the HTTP package

Download the source from here and the war from here.

Let’s begin by looking at the project structure:


Figure E

GWT provides another way to access server side components by using classes in it’s HTTP package. The class RequesBuilder is where it all starts. This class has methods in it to make asynchronous calls. The URL is specified to this class that points to any arbitrary string that is mapped (in web.xml) to the servlet (in this case SimpleServlet). An HttpRequest carries (via a GET or POST) name value pairs from the client UI to the Servlet, where they are peeled off the request and passed on to a business service. The results from the business service are placed in the response object which is accessed via an asynchronous callback method defined in the HTTP API (RequestCallback).

The difference between this and the RPC call is that here, SimpleServlet does not extend RemoteServiceServlet. Also, note that there is no business interface. That, IMO is a bad thing. Not having a clear contract bewtween what the client can call slows down development and complicates testing. OTOH, our servlet is any servlet which is a good thing! Just goes to show, you can’t have your cake and eat it too!

Also, since there is no business interface, there is nothing to produce an Async interface for. So there is one less step in the build process. There is still javascript produced that is accessed by the shell html file as usual.

Moving on to the next level in our integration to back-end service, we’ll look at Spring-GWT integration.

GWT app that makes a call to a Spring service using RPC

Download the source from here and the war from here.

Lets first look at the project structure:

Figure F

I have tried to separate the presentation and service layers so that the service layer does not have any dependency on the presentation layer (only the presentation layer depends upon the service layer). This is a maven multi-module project. The presentation “module” (Called GWTMvnRPCWithSPring-Presentation) has in it’s pom all GWT dependencies and is built using Spring MVC. So the dispatcher-servlet.xml file has two URL mappings: a SimpleUrlHandlerMapping and a GWTHandler. Just for reference, I threw in a RegularController that is pointed to by the simpleUrlHandlerMapping. This (RegularController) controller is nothing special, but the GWTHandler is where all the magic happens. This class is a part of a GWT Widget Library.

Right from GWTHandler’s  javadoc:

The GWTHandler implements a Spring  HandlerMapping which maps RPC from
URLs to RemoteService implementations. It does so by wrapping service
beans with a GWTRPCServiceExporter dynamically proxying all
RemoteService interfaces implemented by the service and delegating
RPC to these interfaces to the service.

Therefore when I define a GwtBusinessService1, you will see that that interface extends RemoteService and defines one business method: caculateTax(…). The call to this business interface is dynamically proxied on the Spring service (businessService1) that is injected into the GWTHandler:

<bean id=”urlMapping1″ class=”org.gwtwidgets.server.spring.GWTHandler” >
<property name=”mappings”>
<map>
<entry key=”/hello/service1.htm” value-ref=”businessService1″ />
<entry key=”/hello/service2.htm” value-ref=”politicalService” />
</map>
</property>
<property name=”order” value=”2″ />
</bean>

The dispatcher-servlet.xml has only spring beans needed for SpringMVC and spring-services-core.xml is the application context that is defined in the services module (GWTMvnRPCWithSpring-services) and contains only services that are presentation-agnostic. Both the contexts are made available in the web.xml.

Other than that there is nothing else that is noteworthy. Let’s move on to accessing Spring services using the HTTP package.

GWT app that makes a call to a Spring service using the HTTP package

Download the source from here and the war from here.

Observe the project structure in Figure G:

Figure G

Comparing it to Figure F, the first thing to notice is the absence of the business interfaces. In it’s place is a SimpleServlet defined in the presentation package. The SimpleServlet is a vanilla implementation (in that it does not extend a specific interface or class except HttpServlet). Here is what this servlet does:

  • Accept requests (typically asynch) from the GWT module.
  • Peel of name/value pairs from the Request object.
  • Invoke Spring services using WebApplicationContextUtils
  • Make the service call passing in values
  • Process the return value(s) from the service
  • Place the value(s) in the response

Also, there is no Spring-MVC here(no dispatcher-servlet.xml), just plain Spring (only spring-service-core.xml). The GWThandler cannot be used here because for the GWTHandler to work we will need interfaces that implement RemoteService which we do not have here. And we do not have those interfaces because HTTP api calls can be used to make any call on the server via HttpRequest/Response unlike RPC where calls were made on an Asynch interface produced via a GWT supplied utility.

That’s it folks! I found this exercise rewarding in learning GWT technologies to build a real-world enterprise app that can scale. My next step is to use smartGWT and then the holy grail of AJAX frameworks: GWT-GoogleMaps! Maybe I’ll blog about it sometime… stay tuned!

  1. GWT allows users to interact with back-end services in two modes, both asynchronous (doesn’t have to be async, but in todays world of RIA and AJAX, who cares about synchronous UIs!):
    1. Using RPC (Remote Procedure Calls) to access server-side Servlets necessarily served from the same server that is serving the HTML (where the GWT javascript is running).
    2. Using GWT classes in the HTTP package that access the server
Get Adobe Flash playerPlugin by wpburn.com wordpress themes