Google Web Toolkit (GWT) + OpenJPA + Tomcat + MySQL
IMOs as Introduction
Google Web Toolkit is going to change the way web clients are developed. At least for those developers who love their Java. In its early days, Java grabbed the developers' mindshare with applets (remember them?), but soon it was JavaScript that reigned the browser runtime as Java spread its wing in the unexpected territory of server side infrastructure middleware and services. Naturally, a large segment of multi-tier web applications adopted a structural layering where the client (web browser) and the server (the application running in a container) spoke two different languages -- JavaScript and Java respectively. A bunch of smart techniques grew organically to bridge the interoperability of two languages. These collective knowledge of the community was waiting for a moniker -- and thanks to Jesse James Garrett -- it got one - it was called AJAX (Asynchronous JavaScript and XML). It was a powerful moniker that could pack a room with audience in any JavaOne 2005 session by the sheer virtue of AJAX appearing somewhere in its presentation title. The term AJAX came to represent a set of programming model and (often asynchronous) communication techniques between a JavaScript based client running in a browser and a remote server written mostly in Java or C#. Google Web Toolkit adopted this core paradigm of AJAX -- but introduced a radical and perhaps far-reaching element. The client is no more written in JavaScript but in plain old Java (albeit a shortened version of it). Though the client was written in Java -- the code ran as a JavaScript code in the browser. The unique contribution of GWT is to introduce a cross-compiler that compiled Java source code into a JavaScript executable. The cross-compilation process not only expanded the server-side Java developers' comfort zone but also solved one of the hardest problems of web client development -- namely the cross-browser compatibility.
As part of our ongoing exercise to bring OpenJPA to an wider audience and focus on its feature-rich, highly customizable aspects -- we are always looking for interesting techno-ecosystems where OpenJPA can operate. From that standpoint, we decided to build a multi-tier web application using GWT in client, OpenJPA in server running inside a Tomcat servlet container. In this blog, I will retrace the steps of building this
sample application. But let me be clear upfront. I had hardly ever programmed an web client. So this is not an expert's commentary -- but more of a tyro's journal -- at least as far as GWT is concerned.
Though I had hardly ever programmed an web client -- I remember writing (sheer by chance, way back in 2005) a JavaScript based AJAX application to demonstrate usage of freshly minted JPA 1.0 version of Kodo running in BEA Weblogic Server. For that exercise, Direct Web Remoting (DWR) -- I found it clean and simple -- helped to convert the server side Java objects and client-side JavaScript and vice versa. I must admit my discomfort with JavaScript during that brief encounter -- it was powerful language but made me - a lover of strong typing and verbosity of Java -- uncomfortable with its loose typing and cryptic syntax -- as if a sharp sword in the hand of an unsure novice who may just cut himself.
Five years later -- as I revisited the current state of client side web technologies to look for an ecosystem suitable for OpenJPA -- Google Web Toolkit did attract my attention. The website came with clear, concise description of the framework and usage to get me started quickly. But the major point of my attraction was something else. I am a strong believer of unified representation. I believe the business domain objects should be expressed once and used uniformly across the application tiers. That was one of the original promises of Object Oriented Analysis and Design to a Fortran-4 programmer. You can imagine my horror when I saw that promise broken and proliferation of "patterns" such as Data Access Object, Data Transfer Object etc. to express the same notion at multiple tiers and endless and useless complexity of copying from one representation to other. Frameworks such as DWR did ease the pain of fractured representation but still it maintained at least a pair of representations for the same notion -- once in Java and other in JavaScript. Looking at GWT, I hoped that it will restore that sanity -- I can define a plain old Java type such as Customer and use the same representation across tiers -- in the server, in the browser, in the communication channel, towards the persistent storage. Of course a set of frameworks will assist to interpret/serialize/marshal/map the state of Customer object between these different operating environments -- and as a developer I do rely and expect them to provide me such conversion without having to resort to multiple representations to express the same notion of a Customer.
Start Cooking
Enough generalities. Let us get our hands dirty. These are the few ingredients you will need to start cooking (but you do not need all of them at once):
- 1 tablespoon of GWT SDK available from the download site. I used the latest version of 2.0.4. Around the next aisle, you will also find an Eclipse Plugin for GWT. I deliberately avoided the temptation of using the plugin for this recipe. I wanted to understand how different pieces of GWT hold together -- and was sure that a plugin will smooth out many of those steps so that I can happily click this button or that on my Eclipse IDE without having any clue of what is happening beneath the surface. Simply, a plugin often makes a cooking experience too sugary.
- 1 packet of OpenJPA available from the download site. I used the cutting edge (SNAPSHOT) version of 2.1.0. OpenJPA comes in a ready-to-cook package with all its dependencies (such as Java Persistence API definition, Apache Commons utilities etc). Because of the experimental nature of this exercise I was not too concerned about using a nightly snapshot version over a released version such 2.0. Actually OpenJPA nightly snapshots built from the trunk are as stable as its released version. Because any change injected in OpenJPA trunk is highly monitored both manually and automatically (thanks to JetBrains and TeamCity and some of the excellent people who manages OpenJPA integration test infrastructure)
- 1 can of true and trusted Tomcat. Tomcat 7.0 is available but I decided to stick to earlier version of 6.0.29.
- Java SDK version 1.6.
- Ant build environment. Again I prefer Ant for such demonstration examples because it not makes each step of compilation, packaging, deployment explicit.
Architecture on a napkin
It always make sense to begin with interfaces. Let us say, ExampleService is the interface to the service. GWT requires that ExampleService to extend from RemoteService - an interface defined by GWT framework incom.google.gwt.user.client.rpc package. Moreover, GWT requires that an asynchronous counterpart of ExampleService interface must be defined. This asynchronous interface must be named ExampleServiceAsync. The naming is important because, at Java language level, ExampleService and ExampleServiceAsync do not know of each other. The GWT framework ensures that the pair of interface exists (by their naming convention) and also confirms that their signature is compatible. The compatibility means that every method of ExampleService has an asynchronous version on ExampleServiceAsync interface. The asynchronous version of an original method always returns void and the return type T of the original method becomes the last argument of generic type AsyncCallback<T> in the asynchronous method. For example, the following method in ExampleService
import com.google.gwt.user.client.rpc.RemoteService;
public interface ExampleService extends RemoteService {
Stock findStock(String symbol);
}
will appear in the asynchronous interface as
import com.google.gwt.user.client.rpc.RemoteService;
/**
* Asynchronous counterpart to the original service interface.
*/
public interface ExampleServiceAsync {
void findStock(String symbol, AsyncCallbackcallback);
}
The GWT client will actually call the asynchronous interface. The diagram below puts all the above together:

1 Comments:
Hello,
Any chance to see it continued - esp the way of using openJPA enhanced beans with GWT?
Post a Comment
Subscribe to Post Comments [Atom]
<< Home