Well it’s been nearly a month since I first wrote about project freedom (as in financial) and I thought it might be time give a brief update on where I’m at. Given that we’ve just had Christmas and I’m currently on holidays progress hasn’t been all that dazzling. That said, I’m still pretty happy with what has been done all things considered. So what have I been doing? Well so far I’ve mainly been looking at different approaches to building the application.

The Java Way

Naturally I immediately jumped to looking at a Java based solution – after all it is what I’d call my “home” language. Anyone who’s been around a while and has had the opportunity to program in Java as well as a variety of other programming languages/paradigms would undoubtedly agree that it is a beautiful language. I for one really appreciate the consistency of the syntax, the uncompromising enforcement of the OOP paradigm, and most of all the rich standard library with its accompanying documentation.

Being that I work with this stuff quite a bit my head was filled with all sorts of ideas about how we could achieve our goals using Java as the weapon of choice. The first thing that came to mind was that I could utilize the Eclipse RCP and JFace to get some quick wins getting a basic application framework up and running. This approach has the following distinct advantages:

  1. Eclipse RCP contains an OSGi container built in (Equinox to be exact) which is a very powerful plugin framework in a manner of speaking. Potentially it means that each discrete piece of functionality can be build as a separate plugin (or bundle in OSGi-speak).
  2. SWT/JFace contain a rich component set which would do about 95% of what I require and look/behave just like native components on Mac, Windows and Linux.
  3. RCP comes with a tool that allows to generate an executable and budle a JRE with the application so you can avoid “but my system doesn’t have Java (or version required) installed” type support headaches. It just runs.
  4. It’ll run on Mac, Windows, and Linux with no issues whatsoever.

So why wouldn’t I take that approach?

  1. Personally I’ve found RCP very hard to come to grips with. Documentation is scarce and outdated from what I can determine.
  2. OSGi adds a large amount of overhead in terms of complexity. Now I’m not exactly the smartest guy going round, but I’m not a moron either. I’ve spent hours frigging around with manifests, configurations, interfaces, dodgy docos and classpath hassles getting very little done. It all feels like a tremendous waste of time at this stage.
  3. Need to learn and ORM mapping tool like Hibernate or similar to overcome the OO to Relational mapping mismatch. I’m predominantly a user interface specialist so I usually leave this kinda stuff to someone else. Alternatively I can just battle on through with JDBC (*shudder).

As far as abstractions go Donald Knuth is reputed to have once said:

“There is no complexity problem in programming that cannot be eased by adding a layer of indirection. And there is no performance problem in programming that cannot be eased by removing a layer of indirection.”

Ordinarily I’d agree with this statement. You only have to look as far as something like an ORM to see this principle at work. What could be simpler than just working with your domain objects and letting something else worry about the whole persistence issue? On the contrary though I’m inclined to say that the sheer number of abstractions present in the aforementioned solution actually add to its complexity – not reduce it as promised. As always in Java I seem to be forced to spend a lot of time thinking about the correct way to do something as opposed to just doing it and refactoring later.

So there it is, I’ve spent a whole lot of time without a great deal of success. About the best thing it’s got going for it so far is that I’ve managed to do some modelling of the domain level objects. So where do we go from here?

Back to the Future

Some might consider this a backward step from comfortable walled garden that is Java but I’ve been experimenting a bit lately with C and GTK+. Yes you read right C, not C++, just pure unadulterated structured programming. Why not C++ indeed.

I’ll probably get flamed for saying this, but I just don’t like it. With great power comes great responsibility, and it’s like a wild beast that can take on any form it likes depending on the wild mood swings of your average programmer. Every time I read C++ I get the impression that whoever’s driving the evolution of the language can’t quite decide what they want it to be. If Java is a well manicured, if somewhat anal, golfing green then C++ resembles a hoarders front yard. You know the ones, full of old car bodies and useless junk left over after you take all the useful stuff out. Don’t take my word for it though, ask Linus. That said you can always pick and choose the bits you like and leave out the bits you don’t.

Anyway, so far I’m really impressed. Previously I’d thought that leaving OO behind would just be too painful however I was pleasantly surprised. To demonstrate a few concepts to myself I briefly knocked up this little demo which consists of a simple GTK+ interface sitting atop an SQLite database. As far as I’m concerned this a great “thin line” of technology from top to bottom which could conceivably be employed to write the app.

db_test.c

#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <sqlite3.h>

/* Database file name. */
const gchar *DB_FILENAME = "test.db";

/* A simple SQL query to select all rows from the person table. */
const gchar *DB_QUERY = "SELECT * FROM person;";

/* Index of the name column in the list view */
const gint LIST_COL_NAME = 0;

/* Index of the age column in the list view */
const gint LIST_COL_AGE = 1;

/* The total number of columns in the list view */
const gint LIST_NUM_COLS = 2;

/* Global reference to DB handle. */
static sqlite3 *db;

/* Callback that processes a single row returned from the database. The first
 * parameter is expected to be a pointer to a GtkTreeView. */
static int
process_db_results( gpointer  data,
                    gint      ncols,
                    gchar    *col_values[],
                    gchar    *col_names[] )
{
    GtkTreeView    *view;
    GtkListStore   *store;
    GtkTreeIter     iter;

    /* Get reference to underlying GtkListStore so we can add to it. */
    view = GTK_TREE_VIEW (data);
    store = GTK_LIST_STORE (gtk_tree_view_get_model (view));

    /* Append a row and populate it using the row data provided */
    gtk_list_store_append (store, &iter);
    gtk_list_store_set (store, &iter,
            LIST_COL_NAME, col_values[0],
            LIST_COL_AGE, col_values[1],
            -1);

    /* Auto-adjust columns to fit data. */
    gtk_tree_view_columns_autosize (view);

    /* Return a zero to let SQLite know it's okay to continue processing */
    return 0;
}

/* User clicked the "Load List" button. */
static void
button_load_clicked( gpointer data )
{
    gint rc;
    gchar *err_msg = 0;

    /* Populate the list component with data from the DB. */
    rc = sqlite3_exec (db, DB_QUERY, process_db_results, data, &err_msg);
    if (rc != SQLITE_OK)
      {
        fprintf (stderr, "SQL error: %s\n", err_msg);
        sqlite3_free (err_msg);
      }

    return;
}

/* User clicked the "Clear List" button. */
static void
button_clear_clicked( gpointer data )
{
    GtkTreeModel  *model; 

    /* Get reference to underlying GtkTreeModel so we can clear it. */
    model = gtk_tree_view_get_model (GTK_TREE_VIEW (data));

    /* Clear the list using gtk_list_store_clear. This is much faster than
     * calling gtk_list_store_remove once for each row. */
    gtk_list_store_clear( GTK_LIST_STORE (model));

    return;
}

/* This callback quits the program */
static gboolean
delete_event( GtkWidget *widget,
              GdkEvent  *event,
              gpointer   data )
{
    /* Close the database connection. */
    sqlite3_close (db);

    /* Terminate the main program loop. */
    gtk_main_quit ();

    return FALSE;
}

/* Creates a list view component consisting of two columns. The first column
 * is for a persons name, the second for their age. */
static GtkWidget *
create_list_view( void )
{
    GtkCellRenderer        *renderer;
    GtkTreeViewColumn	 *column;
    GtkListStore             *store;
    GtkTreeView             *view;

    view = GTK_TREE_VIEW (gtk_tree_view_new ());

    /* --- Column #1 --- */
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes ("Name", renderer,
            "text", LIST_COL_NAME,
			NULL);
    gtk_tree_view_column_set_resizable (column, TRUE);
    gtk_tree_view_insert_column (view, column, -1);

    /* --- Column #2 --- */
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes ("Age", renderer,
            "text", LIST_COL_AGE,
            NULL);
    gtk_tree_view_insert_column (view, column, -1);

    store = gtk_list_store_new (LIST_NUM_COLS, G_TYPE_STRING, G_TYPE_STRING);
    gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));

    return GTK_WIDGET (view);
}

/* Initialises the application's database connection. */
static void
init_db( void )
{
    gint rc;

    /* Open the database to initialise the connection object. */
    rc = sqlite3_open (DB_FILENAME, &db);
    if (rc)
      {
        fprintf (stderr, "Can't open database: %s\n", sqlite3_errmsg (db));
        sqlite3_close (db);
        exit(1);
      }
}

/* Initialises the application's user interface. */
static void
init_ui( void )
{
    GtkWidget *window;
    GtkWidget *vbox, *hbox;
    GtkWidget *scrolled_window;
    GtkWidget *list_view;
    GtkWidget *button_load, *button_clear;

    /* Create the main application window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_widget_set_size_request (GTK_WIDGET (window), 300, 150);
    gtk_window_set_title (GTK_WINDOW (window), "GTK/SQLite DB Example");

    /* Configure app to terminate when closed */
    g_signal_connect (G_OBJECT (window), "delete_event",
			G_CALLBACK (delete_event), NULL);

    vbox = gtk_vbox_new (FALSE, 5);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
    gtk_container_add (GTK_CONTAINER (window), vbox);
    gtk_widget_show (vbox);

    /* Create a scrolled window to pack the CList widget into */
    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
    		GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);

    gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
    gtk_widget_show (scrolled_window);

    /* Create the list view which will display the data. */
    list_view = create_list_view ();

    /* Add the list view widget to the vertical box and show it. */
    gtk_container_add (GTK_CONTAINER (scrolled_window), list_view);
    gtk_widget_show (list_view);

    /* Create a horizontal box to hold our buttons */
    hbox = gtk_hbox_new (FALSE, 0);
    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
    gtk_widget_show (hbox);

    /* Create the buttons and add them to the window. */
    button_load = gtk_button_new_with_label ("Load List");
    button_clear = gtk_button_new_with_label ("Clear List");

    gtk_box_pack_start (GTK_BOX (hbox), button_load, TRUE, TRUE, 0);
    gtk_box_pack_start (GTK_BOX (hbox), button_clear, TRUE, TRUE, 0);

    /* Connect our callbacks to the three buttons */
    g_signal_connect_swapped (G_OBJECT (button_load), "clicked",
    		G_CALLBACK (button_load_clicked), list_view);
    g_signal_connect_swapped (G_OBJECT (button_clear), "clicked",
            G_CALLBACK (button_clear_clicked), list_view);

    gtk_widget_show (button_load);
    gtk_widget_show (button_clear);

	/* The interface is completely set up so we show the window. */
    gtk_widget_show (window);

    return;
}

int
main( gint   argc,
      gchar *argv[] )
{
    /* Before we even think about doing anything we must initialise GTK */
    gtk_init (&argc, &argv);

    /* Initialise the database connection */
    init_db ();

    /* Initialise the user interface */
    init_ui ();

    /* Now that everything's ready, start the main program loop. */
    gtk_main ();

    return 0;
}

Not bad for 236 lines of code huh? Feel free to use the code in any way you like. You’ll have to create a new database using the sqlite command-line utility first before running it though:

$ sqlite3 temp.db
SQLite version 3.5.9
Enter ".help" for instructions
sqlite> create table person (name varchar(30), age smallint);
sqlite> insert into person values ("Phillip J. Fry", 33);
sqlite> insert into person values ("Hubert J. Farnsworth", 167);
sqlite> insert into person values ("Zapp Brannigan", 45);
then type CTRL-D to exit

As far as I’m concerned writing this thing in C has a few compelling advantages:

  1. It’s portable. C is arguably the most portable (not to mention widely used) language in the world. If binaries aren’t available for your processor architecture, you can always compile it especially to suit that Z80 you’ve had sitting in your basement – just because you can.
  2. No special libraries or runtimes required here. Just run it baby.
  3. Glib, GTK+ again provide 95% of what I need for the app out of the box. Not to mention that the documentation is awesome and free. They’re cross-platform too!
  4. Working with relational databases is a snack. No OO/RDBMS disparity here, it’s all smooth sailing.
  5. It’s really, really fast. There’s no VM here, just bare-metal machine code.
  6. Like Java, there’s heaps of free libraries and tools out there to take advantage of.

Of course using something as raw as C/GTK+ isn’t without its hangups:

  1. Memory management and pointers frighten the bejesus out of many programmers. I don’t mind them so much, but I do understand that some have a pathological aversion to them.
  2. Cross-compilation isn’t exactly what I’d call straight forward.
  3. If you’ve been spoilt, like I have, working in 4th gen languages with awesome support for strings  NULL terminated character arrays are a rude shock. Don’t get me wrong, it’s not difficult, it’s just one extra thing to keep in mind.
  4. Very little in the way of syntactic sugar.
  5. GTK is still yet to be ported to Mac OSX. This is potentially a dealbreaker.

One thing in particular that I found was very nice was the GTK+ “Object Oriented” style interfaces which allow for a form of inheritance within a standard C program. This is a massive benefit because UI programming can get quite repetitive if you’re unable to extend and modify components simply by subclassing them.

Well that’s about all I’ve got for now. I’d be really interested in hearing what you think on the matter of technology choice, especially if you’re looking to contribute in future.

It seems like every time I turn around I run in to class loading issues when working with Java. Trying to get something as simple as logging working for an application can turn in to a real chore. This is especially true of getting Apache Commons Logging (aka. clogging) to work on WebSphere Application Servier (WAS). Since I haven’t yet found that there was a single, straight forward, step-by-step guide to doing this I decided to write this article.

The Issue

The basic problem with clogging under WAS is that WAS in fact uses clogging for its own purposes under the covers. In doing so they’ve configured it to use their own logging class (the WsJDK14Logger I believe). By default this will dump any clogging activity out to the console and be recorded in the stdout log file. This is far from ideal if you wish to isolate the logging activity for a single application in its own log file.

The Bitter Taste of Defeat

Regarding myself as somewhat of a class loading expert (in a novice kind of way), I somewhat foolishly thought “I know I’ll just dump the log4j.jar file and the commons-logging.jar file into my WEB-INF/lib folder and put a log4j.properties file in my src folder. Then I’ll install the application on the application server and set the module class loader to application first”. Simplicity itself I thought! What could be easier? Bah-bow – WRONG! It crashed and burned in the worst way possible: it gave me nothing. Absolutely bloody nothing. The application just merrily went on its way happily dumping its logging information straight into stdout.

Feeling rather bitter about the resounding defeat I’d just been handed I resolved to see what was out there on the web – which led to even greater despair. This issue is the subject of much confusion and misunderstanding with very few good answers. Luckily I happend to stumble upon this forum thread and an IBM presentation which combined told me approximately what I needed to know.

Seven Steps to Success

In a nutshell this is what you need to do to get this working inside a web project.

1. Import your commons-logging.jar and log4j.jar files into the EAR project in which the module will be bundled. You can do this by right-clicking on the EAR project and selecting Import > J2EE Utility Jar if you’re using RAD or Eclipse. Otherwise you can just copy these JARs directly into your EAR project and it should have the same effect.

2. Create a folder called services inside the META-INF directory of your web project. Inside this folder create a file called org.apache.commons.logging.LogFactory and copy and past the following into the file:

org.apache.commons.logging.impl.Log4jFactory

3. Add both the commons-logging and log4j JAR file to the MANIFEST.MF file located in the META-INF folder of your web project. For example:

Manifest-Version: 1.0
Class-Path: commons-logging.jar
  log4j-1.2.15.jar

4. Next if you’re using RAD open the EAR deployment descriptor and click on the deployment tab at the bottom. Then scroll down to the Applications section at the bottom of the page and change the classloader mode from PARENT_FIRST to PARENT_LAST. Save the file and close it. Note: if you can also do this once the application is installed from the WAS admin console.

5. Now make sure that you have your log4j.properties file configured and available somewhere on the class path inside your web app. Putting it at the root of the src directory is usually your best bet.

6. Install the application and restart the application server.

7. Profit.

Sorry, that last point was a complete waste of time but I needed another one to round out the seven. Anyway there you have it! Commons Logging running blissfully inside a WebSphere web container.

Creating and running GWT projects from the command line isn’t all that hard, but it isn’t all that convenient either if you’re an Eclipse user. If you’ve read my previous post on Integrating Spring with GWT you would have seen that we still had to manually package and deploy the application to the app server before running up the hosted mode browser. This is quite different to a regular Eclipse Dynamic Web Project (part of the Eclipse Web Tools Platform) which allows you to automatically publish your project to the app server.

Creating a GWT module with Cypal Studio

Creating a GWT module with Cypal Studio

Thankfully there is a way to add a GWT facet to Dynamic Web Projects in Eclipse. It comes in the form of a third party plugin from development shop Cypal. Cypal Studio for GWT allows you to hook into your existing GWT SDK and add the GWT facet to your new/existing WTP project. From there you can go on developing your GWT application as you would a regular Dynamic Web Project in Eclipse and add the GWT stuff as you go. IMO this is a fantastic piece of work and really lowers the barrier to entry for developers new to GWT scene but who are already familiar with Eclipse.

To get started download Cypal Studio for GWT here, and then follow the instructions here.

Some might claim that I’m rehashing a topic that has already been solved however I’m compelled to write this article as I personally struggled to connect all the disparate dots in order to make Google Web Toolkit (GWT) integrate with the Spring Framework. This is intended to be the article that I wished I’d stumbled upon in the first 10 minutes of looking for a solution to the problem. Before we start I’d also like to acknowledge that I’ve borrowed heavily from the concepts that people like George Georgovassilis pioneered. There’s nothing really new or groundbreaking here, I’ve simply combined all the knowledge that I’ve gained from all over the place into one convenient guide.

Update: Since publishing this article I’ve been contacted by Richard Bondi with regard to some great work that he’s also done on the matter of which I wish to also acknowledge his fantastic work. If you want to know more on this subject then I heartily recommend you check out his article on how to Integrate Spring with GWT and once you’ve done that, stubbing in hosted mode. Thanks again Richard.

Why would anyone want to integrate Spring and GWT?

If you’re familar with GWT (and I’m assuming you are) you may have marvelled, as I did, with how seamless and uncomplicated client-server interaction is. You are also probably aware that GWT RPC services are not web services. In fact they’re just plain old servlets that are endowed with an ability to serialize and deserialize information across the wire using a rather compact encoding developed by Google.

The RemoteServiceServlet class is great insofar as it handles all the grunt work of the RPC side of things whilst letting you get down to the business of writing your business logic for your services. The fact that you have to extend RemoteServiceServlet raises a few gnarly questions however:

1. What happens if I’ve already got my business logic implemented as an existing Java class with it’s own inheritance heirarchy?

2. What if you want to reuse that same class to implement a SOAP web service or any other RESTful interface for that matter?

3. What if I want to use the service class internally and don’t need all the RPC stuff?

4. What if something better than GWT comes out and I just want to replace the presentation layer technology?

Ouch! Suddenly extending RemoteServiceServlet starts to look a bit painful and far less useful than it did before. Now we could either try to imitate the ostrich and pretend that this isn’t an issue, or we could address the problem head on. We’re going to take the latter option.

Enter Spring

One answer to the above questions is to use a technique called Dependency Injection (DI). The Spring Framework happens to come with quite a good IoC container implementation and has become an industry standard. Without getting into the details about what DI is and how it works, Spring was designed with the intent of making your code as loosely coupled to its dependencies as possible and promoting POJO based development for enterprise applications.

So what does this look like in practice? Well currently out RPC model looks like this:

Standard GWT RPC plumbing

Standard GWT RPC plumbing (image courtesy of Google)

Ideally we want to look more like this:

New and improved GWT RPC plumbing with Spring integration

New and improved GWT RPC plumbing with Spring integration

Not too different really. With the exception of two new classes and two new interfaces you could be forgiven for thinking that I’d hardly done a thing, not to mention that three of them are Spring MVC classes! Well that’s actually the truth of it, I’ve done bugger all. It’s also worth noting that all the work is on the server-side with nothing new for the client.

Going back to our sample code, essentially all we need to do now is wire up our DispatcherServlet (a front-controller) and point it to our new GwtRpcController class for all RPC requests. We’ll also need to break the inheritance chain on the YourServiceImpl (a.k.a. QuoteServiceImpl) class to prove a point.

Getting down to business

In order to illustrate the point, I’m going to walk you through an adaptation of a random quote program from another GWT tutorial originally found on netbeans.org. I’ve adapted the original example to Eclipse as it’s my IDE of choice and I’m using Tomcat 6 as my test server.

For this tutorial you’ll require the following

If you’re impatient like me you might also want access to the project source code which can be found here. Please note that you’ll have to download the dependencies separately as I don’t want to inadvertently infringe on any copyright restrictions.

Okay so maybe I lied a little beforehand, there’s a bit more that we have to do in the way of re-jigging our project structure to make it all hang together and work. Anyway, time to cut some code!

Creating the project

Open the terminal/command line and go to the folder where you’ve unzipped the GWT SDK. And run the following command to create your eclipse project:

./projectCreator -ant gwt-wisdom -eclipse gwt-wisdom -out /home/dave/eclipse/workspace/gwt-wisdom

Note: replace the -out parameter argument with your own project destination. Also I’m using Linux, Windows users should just get rid of the preceeding “./” and change all forward slashes to back slashes and the commands will work just fine.

Now run this command to create your GWT project structure:

./applicationCreator -eclipse gwt-wisdom -out ~/eclipse/workspace/gwt-wisdom org.example.gwtwisdom.client.GwtWisdom

Again replace the -out parameter with the same location you used for the command above

Next import the new application into Eclipse using the File > Import menu option. Choose the Existing Projects option from under the General category and then browse to where ever you output the project files to.At this stage you should be able to hit run and test that the application skeleton is working.

Additional project setup

So that your application will compile once we start adding Spring into the mix add the the Spring framework and Spring Web MVC jars (spring.jar, spring-webmvc.jar) to your applications build path.

Now we need somewhere to put all our configuration files and deployment time dependencies. Create the following directory structure at the base of your project WebContent/WEB-INF/lib. This is almost identical to the Eclipse WTP project structure and will become useful later when we automate the project build with an Ant script.

In the WebContent/WEB-INF folder create a web.xml file an copy and paste the text below into it:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <display-name>GWT Wisdom</display-name>

    <!-- Initialise the Spring MVC DispatcherServlet -->
    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Map the DispatcherServlet to only intercept RPC requests -->
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>*.rpc</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>GwtWisdom.html</welcome-file>
    </welcome-file-list>

</web-app>

Now I’m aware that the integrated Tomcat instance that comes with GWT has a web.xml file but we can’t actually modify the Tomcat web.xml file as it is dynamically regenerated by the compiler every time we start hosted mode. Hence why we’re creating our own.

If you were paying attention in the last step you would have seen that we defined a servlet in the web.xml file. This is the Spring Web MVC DispatcherServlet which will intercept our RPC requests and route them to the correct service. Each DispatcherServlet instance requires a bean definition file of the same with a “-servlet.xml” suffix. So in the same folder create a file called spring-servlet.xml and copy and paste the following into it:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <!-- The application context definition for the DispatcherServlet -->

    <!-- Maps the request through to a concrete controller instance -->
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <value>
            /**/quote.rpc=quoteController
            </value>
        </property>
    </bean>

    <!-- GwtRpcController wraps our service in order to decode the incoming -->
    <!-- request then delegates processing of the call to the POJO service -->
    <!-- and then encodes the return value forwarding the response. -->
    <bean id="quoteController" class="org.example.gwtwisdom.server.GwtRpcController">
        <property name="remoteService">
            <bean class="org.example.gwtwisdom.server.QuoteServiceImpl" />
        </property>
    </bean>

</beans>

This will be used to configure the DispatcherServlet to route calls to our services. It does so via the SimpleUrlHandlerMapper which uses regular expression syntax to match the request url to a controller bean ID.

Now you’ll need to add the following jars to the WebContent\WEB-INF\lib folder: commons-logging.jar, gwt-servlet.jar, gwt-user.jar, spring.jar, spring-webmvc.jar. This is necessary for when it comes time to deploy the app.

Creating the RPC quote service

Next we’re going to create our RPC service. Start by creating a subpackage of the *.client package and call it “service”.

Create a new interface called QuoteService and make it look like the code below:

package org.example.gwtwisdom.client.service;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

@RemoteServiceRelativePath("quote.rpc")
public interface QuoteService extends RemoteService {
    public String getQuote();
}

Those already familiar with GWT will know that the next step is to create an async service interface to pair with the QuoteService interface we just created. Create a new interface again in the *.client.service package called QuoteServiceAsync and modify it so it looks like the following:

package org.example.gwtwisdom.client.service;

import com.google.gwt.user.client.rpc.AsyncCallback;

public interface QuoteServiceAsync {
    public void getQuote(AsyncCallback<String> callback);
}

Enough of interfaces. Now it’s time to code up the actual service itself. Create a new package under the org.example.gwtwisdom package called server. Once that’s done create a new class and call it QuoteServiceImpl.

package org.example.gwtwisdom.server;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.example.gwtwisdom.client.service.QuoteService;

public class QuoteServiceImpl implements QuoteService {

    private Random randomizer = new Random();
    private static List<String> quotes = new ArrayList<String>();

    static {
        quotes.add("No great thing is created suddenly - Epictetus");
        quotes.add("Well done is better than well said - Ben Franklin");
        quotes.add("No wind favors he who has no destined port - Montaigne");
        quotes.add("Sometimes even to live is an act of courage - Seneca");
        quotes.add("Know thyself - Socrates");
    }

    public String getQuote()
    {
        return quotes.get(randomizer.nextInt(quotes.size()));
    }

}

Now some of you might be saying to yourselves “hey wait a minute, don’t we have to extend RemoteServiceServlet?”. Well read on. I’m about to show you a magic trick straight out of the Gang of Four (GoF) playbook.

To cap it all off before we continue, we should probably update our module configuration file to include our new service mapping. Copy and paste the following into your GwtWisdom.gwt.xml file:

<!-- RPC service servlet declarations                             -->
<servlet path="/quote.rpc"
    class="org.example.gwtwisdom.server.QuoteServiceImpl"/>

All rise for the GwtRpcController

Here’s the fun part, now we’re going to create the GwtRpcController. In the org.example.gwtwisdom.server package create a class called, you guessed it GwtRpcController. Then copy and paste the following code into it:

package org.example.gwtwisdom.server;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.context.ServletContextAware;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RPC;
import com.google.gwt.user.server.rpc.RPCRequest;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class GwtRpcController extends RemoteServiceServlet implements
        Controller, ServletContextAware {

    private ServletContext servletContext;

    private RemoteService remoteService;

    private Class remoteServiceClass;

    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        super.doPost(request, response);
        return null;
    }

    @Override
    public String processCall(String payload) throws SerializationException {
        try {

            RPCRequest rpcRequest = RPC.decodeRequest(payload,
                    this.remoteServiceClass);

            // delegate work to the spring injected service
            return RPC.invokeAndEncodeResponse(this.remoteService, rpcRequest
                    .getMethod(), rpcRequest.getParameters());
        } catch (IncompatibleRemoteServiceException ex) {
            getServletContext()
                    .log(
                            "An IncompatibleRemoteServiceException was thrown while processing this call.",
                            ex);
            return RPC.encodeResponseForFailure(null, ex);
        }
    }

    @Override
    public ServletContext getServletContext() {
        return servletContext;
    }

    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    public void setRemoteService(RemoteService remoteService) {
        this.remoteService = remoteService;
        this.remoteServiceClass = this.remoteService.getClass();
    }

}

This class works on the principle that it is both a RemoteServiceServlet AND a Spring MVC Controller (don’t you just love polymorphism?) meaning that it can not only be used as a target by the DispatcherServlet for handling incoming RPC requests, but also to decode the incoming RPC requests. Remember I previously mentioned the Gang of Four? Well you’re looking right at the strategy pattern baby. Pretty cool huh?

Upon receiving a request we delegate handling of this to the Controller’s superclass (the RemoteServiceServlet) to handle the unmarshalling of the request. We then intercept the processing of the message by overriding RemoteServiceServlet.processCall method and delegate the processing to the RemoteService POJO.

Where did we get this magical POJO from you ask? Well we injected it into the class via the setRemoteService setter back in the spring-servlet.xml bean definition file earlier.

Okay one last thing before we continue on to preparing the app for deployment. We need to tie all of this together by doing some work to display our quotes in the GWT entry point class and fixing up some of the HTML.

In the GwtWisdom.html file copy and paste the following in below the body tag:

<p>
This is an AJAX application that retrieves a random quote from
the Random Quote service every three seconds. The data is retrieved
and the quote updated without refreshing the page!
</p>

Once you’ve done that, replace the method body of the GwtWisdom classes onModuleLoad method with the following:

    public void onModuleLoad() {
        final Label quoteText = new Label();

        Timer timer = new Timer() {

            public void run() {
                // create an async callback to handle the result:
                AsyncCallback<String> callback = new AsyncCallback<String>() {

                    public void onFailure(Throwable t) {
                        // display error text if we can't get the quote:
                        quoteText.setText("Failed to get a quote");
                    }

                    public void onSuccess(String result) {
                        // display the retrieved quote in the label:
                        quoteText.setText(result);
                    }
                };
                QuoteServiceAsync service = (QuoteServiceAsync) GWT
                        .create(QuoteService.class);
                service.getQuote(callback);
            }
        };

        timer.scheduleRepeating(3000);
        RootPanel.get().add(quoteText);
    }

Note: since this is client-side code be careful that you use the google timer implementation as opposed to the stock Java one otherwise it won’t work like you expect.

That should take care of the display side of things. If you want you can also jazz it up a bit by putting some styles in the GwtWisdom.css file.

Ditching the GWT tomcat server

Remember that earlier on we created our own custom web.xml to initialise the Spring context via a DispatcherServler? Well because of this we can no longer rely upon the integrated tomcat server that comes with GWT to run our app. Fortunately the hosted mode browser comes with a -noserver switch which allows us to configure it to use the server of our choice during development.

There’s a bit of a knack to getting this running all running nice and seamlessly within Eclipse. First we’re going to have to compile the application then package it up and deploy it to the server just this once just so the server has knowledge of your app. Don’t worry, once it’s running in hosted mode the app will use your workspace code, but trust me we need to do this just once.

I’m actually going to use Ant to build and package the app. Conveniently, this is going to work out great in future when I need to bundle the app up into a war file and deploy it elsewhere.

First create a file called build.xml in the root of your project and copy and paste the script below into the build file.

<?xml version="1.0" encoding="utf-8"?>
<project name="gwt-wisdom" default="compile" basedir=".">
    <description>
        Build file. This is used to package up your project as a war, if you
        want to distribute/deploy it. This isn't needed for normal operation.
    </description>

    <property file="build.number"/>

    <!-- GWT properties - change these to suit your distribution (i.e. windows, mac or linux) -->
    <property name="platform" value="linux"/>
    <property name="gwt.home" value="/home/dave/eclipse/lib/gwt/linux/1.5.1"/>

    <!-- Build properties - shouldn't need changing -->
    <property name="name" value="GwtWisdom"/>
    <property name="module" value="org.example.gwtwisdom.GwtWisdom"/>
    <property name="src.dir" value="src"/>
    <property name="web.dir" value="WebContent"/>
    <property name="lib.dir" value="${web.dir}/WEB-INF/lib"/>
    <property name="bin.dir" value="${web.dir}/WEB-INF/classes"/>
    <property name="test.dir" value="test"/>
    <property name="out.dir" value="build"/>
    <property name="dist.dir" value="dist"/>

    <!-- set classpath -->
    <path id="project.class.path">
        <pathelement path="${java.class.path}/"/>
        <pathelement path="${lib.dir}/gwt-user.jar"/>

        <!-- Additional dependencies go here -->
        <pathelement path="${lib.dir}/spring.jar"/>
        <pathelement path="${lib.dir}/spring-webmvc.jar"/>
        <pathelement path="${lib.dir}/commons-logging.jar"/>
    </path>

    <target name="clean">
        <delete file="${dist.dir}/${name}.war"/>
        <!-- Delete the bin directory tree -->
        <delete>
            <fileset dir="${bin.dir}" includes="**/*.class"/>
        </delete>
    </target>

    <target name="compile" description="Compile both client &amp; server code">
        <!-- cross-compile client-side java classes -->
        <mkdir dir="${out.dir}"/>
        <java classname="com.google.gwt.dev.GWTCompiler" dir="${basedir}" fork="true">
            <jvmarg value="-Xmx256M"/>
            <classpath>
                <pathelement path="${java.class.path}"/>
                <pathelement location="${src.dir}"/>
                <pathelement location="${bin.dir}"/>
                <pathelement path="${gwt.home}/gwt-user.jar"/>
                <pathelement path="${gwt.home}/gwt-dev-${platform}.jar"/>
            </classpath>
            <arg line="-out ${basedir}/${out.dir}"/>
            <arg value="%*"/>
            <arg value="${module}"/>
        </java>
        <copy todir="${web.dir}">
            <fileset dir="${out.dir}/${module}"/>
        </copy>

        <!-- compile server-side java classes -->
        <mkdir dir="${web.dir}/WEB-INF/classes"/>
        <javac srcdir="${src.dir}:${test.dir}" destdir="${bin.dir}" includes="**" debug="on" debuglevel="lines,vars,source" source="1.5">
            <classpath refid="project.class.path"/>
        </javac>
    </target>

    <target name="package" depends="compile" description="Package up the project as a war">
        <mkdir dir="${dist.dir}"/>
        <war destfile="${dist.dir}/${name}.war" webxml="${web.dir}/WEB-INF/web.xml">
            <fileset dir="${out.dir}/${module}">
                <include name="**/*.*"/>
            </fileset>
            <fileset dir="${web.dir}">
                <include name="**/*.*"/>
                <exclude name="WEB-INF/web.xml"/>
            </fileset>
        </war>
    </target>

    <target name="all" depends="package"/>

</project>

Run the build script using the package target (Alt+Shift+X then Q). Alternatively if you’re using Ant from the command line then running “ant package” from the project directory should do the trick. This should compile and package the app automatically for you into a war file.

If the build fails for any reason you might have to edit some of the property elements listed at the top of the file depending on your platform (windows, mac or linux) and where you unzipped your GWT libs. Just change these as appropriate and everything should work fine.

From here you can just go ahead and fire up Tomcat and deploy the war file onto the app server either via the admin console or the autodeploy directory. At this point you should be able to test your application by opening your web browser and navigating to http://localhost:8080/GwtWisdom/GwtWisdom.html. If this works then we’re all good to proceed to the next stage.

Getting hosted mode to run with -noserver

Okay we’re getting close now. This step isn’t essential really, what I’ve shown you so far should be more than enough to demonstrate the application in action. If however you want to continue debugging and testing your app in hosted mode for development like I do then read on.

We’re going to need to edit the launch configuration in order to run the app in hosted mode using our own Tomcat instance as opposed to the integrated Tomcat server. You can do this one of two ways, either edit the GwtWisdom.launch file directly or you edit them via the Eclipse run configuration manager. We’re going to do it via the run configuration manager.

You can open the manager by right-clicking on the project Run As > Run Configurations. Once there, you should see in the left-hand tree view under Java Applications the GwtWisdom launch configuration. Select it and then click the Arguments tab over on the right hand side. Check that the program arguments resemble those below. Your configuration may differ slightly as far as the port is concerned but should read something like:

-out www GwtWisdom/GwtWisdom.html
-noserver
-port 8080

This configuration tells the hosted mode browser to use an external server on the given port and where it should find your applications home page on the server.

You might also have to add the contents of your WebContent/WEB-INF/lib folder to the classpath tab in order to get it working but try it first by clicking apply and then run.

Sweet sweet success!

All that’s left to do is run the project. If you’ve configured it correctly it should fire up the app in all its hosted glory. Your services are now free from the tyranny of RemoteServiceServlet!

Now if only we could figure out a way to remove the dependency on the QuoteService interface from the service. Then it really would be a bona-fide POJO…another day, another challenge.

Follow

Get every new post delivered to your Inbox.