| Developer: SOA
Introduction to the Google Web Toolkit
by Stéphanie Antoine,
Julien Dubois, and Jean-Philippe Retaillé
Learn how to use the Google Web Toolkit to do
everything from basic tasks to advanced ones such as RPC communication,
history management, and packaging a production-ready
application.
Published
October 2006
Web 2.0 and its technical counterpart, Asynchronous
JavaScript and XML (Ajax), are gaining momentum thanks to applications
such as Gmail and Google Maps. For Web applications, the main benefit
of Ajax is a greatly improved user experience. Although JavaScript and
DHTML—the technical foundations of Ajax—have been
available for years, most programmers ignored them because they were
difficult to master. Today, frameworks written in JavaScript, such as
Dojo, can help you build Ajax applications, but you still need a good
understanding of JavaScript in order to use them. Google offers another
way to help Java developers create Ajax applications more productively.
This new framework, called Google Web Toolkit (GWT), can be used
efficiently with Oracle JDeveloper. GWT is freely available under the
Apache License v. 2.0 at http://code.google.com/webtoolkit.
Main Features and Restrictions
One of the main problems with Ajax development is that you need to
master a large stack of heterogeneous technologies. Depending on the
nature of your project (for example, business applications), this can
be a great drawback.
In addition, different Web browsers don’t support JavaScript
and DHTML in the same way. For example, Microsoft Internet Explorer and
Mozilla Firefox handle these technologies slightly differently;
you’ll need to deal with this if you want your application to
run seamlessly on your users’ PCs.
Although most of the Ajax frameworks available today simplify
development work, you still need a good grasp of the technology stack.
So, if you’re planning to use Ajax to improve only your
application’s user experience—if you’re
not also using it as a strategic advantage for your
business—it may be unwise to spend a lot of money and time on
the technology.
GWT proposes a different way to create Ajax applications. It uses Java
as a single programming language for both the client and server sides.
Is it the return of Java applets? Not at all: GWT provides a compiler
that translates the Java code on the client side into JavaScript and
DTHML. This solution greatly simplifies the technology stack from the
programmer’s point of view: You have to master only Java. The
downside is that you have less control over the client-side code of
your application because it’s eventually generated by the GWT
compiler.
The Java code for the client side of your application is subject to
restrictions because JavaScript doesn’t implement the entire
object-oriented concepts and APIs available in Java. You can use only a
subset of Java keywords and APIs (java.lang and java.util):
- All the primitive types (such as byte, char, short,
and int) as well as their corresponding classes (such as Byte and Char)
are directly supported—except for long, which is translated
into the JavaScript equivalent of double. We recommend that you use int
instead of long.
- User-defined exceptions (checked or not) are possible
but the method Throwable.getStackTrace() is not available. Some JVM
exceptions are also available (such as IndexOutOfBoundException).
- The keyword synchronized has no effect because
JavaScript is mono-thread. The multithread API is not available.
- Reflection is not supported. However, you can get the
class name of an object by using the method GWT.getTypeName(Object).
- Finalization is not supported.
- Several objects containers from java.util can be
used, such as Stack, Vector, and HashMap. The Date class is also
available.
In addition, GWT provides specific APIs to manage the GUI,
internationalization, and XML parsing. It also provides a comprehensive
library to manage communication between the client and the server. It
uses well-known Remote Procedure Call (RPC) principles implemented by a
generic servlet (RemoteServiceServlet), which you can specialize for
your own needs. You also can use JavaScript Object Notation (JSON) as
the data interchange format for your HTTP messages sent with the GWT
HTTPRequest class.
GWT also offers an interface, called JavaScript Native
Interface (JSNI), which lets you mix your own hand-made JavaScript code
with the code generated by the GWT compiler. JSNI uses the keyword
native used by Java Native Interface (JNI) to define your own
JavaScript functions. The body of these functions is defined inside
specifically formatted comments.
Finally, you can unit-test your code inside JDeveloper
with GWTTestCase, a specialization of the class TestCase provided by
JUnit.
Focus on GUI Programming with GWT
Ajax dramatically changes the way you develop Web applications. Most of
the time, an Ajax application needs only a single Web page. Its content
is modified dynamically by JavaScript and DHTML to produce a user
experience similar to that provided by native applications.
Therefore, GWT provides a programming model whose
principles will sound familiar to Swing or AWT programmers. The GUI is
no longer specified by HTML tags as in classic Web applications.
It’s programmed directly with Java code in a way similar to
AWT or Swing. The well-known concepts of GUI programming are available
with GWT:
- Widgets, including the usual items (such as Button,
TextBox, and CheckBox) and more advanced items such as Tree and Menu Bar
- Panels, which contain widgets, with their own layout
(panels and layout aren’t separated as in Swing)
- Events generated by widgets. The listeners must
implement specific interfaces.
Loading the GWT JavaScript library and specifying the entry point of
your application is easy: all you have to do is create a simple HTML
page.
GWT uses Cascading Style Sheets (CSS). Every widget has
its own style, which you can change to meet your needs. You must create
your own CSS to overload the defaults defined by GWT.
If the standard widgets don’t suit your needs,
you can also define your own. (This topic, however, is beyond the scope
of this article.)
Project Structure
A GWT project must comply with a pre-defined structure
in order to be
accepted by the compiler. Thus, it’s mandatory that you
define a global package for your application. The last part of the
package name must be the name of the application (such as
global.package.yourApplicationName). The XML file describing your
application must be found at the root of this global package. The name
of this file must be the name of the application followed by the
.gwt.xml extension (for example, yourApplicationName.gwt.xml). In
addition, you must create three sub-packages:
- “client”, which contains the Java
code of the client side (this
code must comply with the restrictions mentioned earlier)
- “server”, which contains the Java
code of the server side (you can
use the full J2SE/J2EE API here)
- “public”, which contains the HTML
pages, CSS, and images of your
application
Your project must declare several jars:
- gwt-dev-windows.jar or gwt-dev-linux.jar: Programming
tools
including the compiler. The embedded Web browser provided by GWT is
platform-dependent.
- gwt-user.jar: The GWT runtime.
- gwt-servlet.jar: The jar to deploy on your
application server
with the code generated by the GWT compiler. It contains the
RemoteServiceServlet.
The result of the compilation is stored in a single directory whose
name is the name of the global package of your application. This
directory contains all the elements (such as HTML pages, CSS, and
JavaScript files) that comprise the client side of your application.
These elements must be deployed inside your Web application, as usual.
Hosted and Web Modes
Two execution modes are possible with GWT. The Hosted mode executes
your application code inside an embedded server and Web browser, so you
don’t have to deploy your code on an application server.
It’s useful during application testing because it makes
debugging simpler.
The Web mode is the deployment of your Ajax Web
application on a genuine application server such as OC4J. You typically
use this mode when the application runs in production.
Building Your First GWT Web App with Oracle JDeveloper
Thus far you've learned how GWT works; now,
let’s code a
sample Web application (download).
The sample application is a to-do list manager. Its
features are quite simple: creating, editing, deleting, and
prioritizing to-do lists. We chose this example because it’s
easy to understand, yet its implementation covers a lot of
GWT’s features.
Here’s a screen shot of the final application:

Step 1: Install GWT
Download GWT from Google’s Web site at
http://code.google.com/webtoolkit/. At the time of this writing, GWT
comes in Windows and Linux versions. GWT is platform-specific because
its Hosted mode works with a modified version of Firefox, which is
itself platform-dependent. (We were able to use the Linux version of
GWT successfully on an Apple computer, but the Hosted mode
didn’t work.)
GWT downloads as an archive file, which you must
uncompress either with the tar -xvf command on
Linux or with an unzip utility on Windows. That’s all you
need to do to install the toolkit.
Step 2: Run the applicationCreator Script
Open a command line and go to GWT’s
installation directory.
This directory contains the applicationCreator script, which
we’ll use to start up our application. Because we want our
application to be stored in the Oracle Technology Network directory, we
add “-out otn” as a parameter to the script. On
Linux, type:
./applicationCreator -out otn otn.todo.client.TodoApp

On Windows, use:
applicationCreator -out otn otn.todo.client.TodoApp
This script generates the basic project structure, a sample
“Hello word” code inside the requested application
class, as well as two scripts: TodoApp-shell, which is used to run the
application in Hosted mode; and TodoApp-compile, which is used to
package the application for use in Web mode.
Step 3: Open the Project in JDeveloper
Launch JDeveloper and create a new Web project:

Click on the Next
button. JDeveloper will ask for the new project’s location.
Use your application’s name as the Project Name, and
choose the application root directory, as defined in Step 2, as the Directory Name:

Click on the Next button and
validate that your application is
a J2EE 1.4 application:

Click on the Next
button and choose your project Web properties: the Document Root is the
current project’s www directory, and the J2EE Web Application
Name and J2EE Context Root are both the project name:

This will create the JDeveloper project, but some
compilation errors will occur because GWT’s library
isn’t included in the project classpath. In the project
properties, select the Libraries
node in the side tree on the left and add the gwt-user.jar library:
Your project should now compile and look like this:

Writing the Client-side Code
The applicationCreator script above created a basic
“Hello world” application, which is available in
the otn.todo.client package. Here's its main method:
public void onModuleLoad() { final Button button = new Button("Click me"); final Label label = new Label();
button.addClickListener(new ClickListener() { public void onClick(Widget sender) { if (label.getText().equals("")) label.setText("Hello World!"); else label.setText(""); } });
RootPanel.get("slot1").add(button); RootPanel.get("slot2").add(label); } }
This method creates a button that says “Click Me”.
When you click the button, the text “Hello World”
is displayed.
This method is divided into three parts:
- The creation of the Button and Label widgets
- The creation of a ClickListener object. This code is
very close to what you would have written in Swing; it’s
easier to understand if you have a desktop Java background.
- The display of the widgets on the HTML page: slot1
and slot2 are both HTML elements on the page
The HTML page that’s used as a skeleton is located in the
src/otn/todo/public directory. It defines the two HTML elements, slot1
and slot2, as table cells.
Running and Debugging in Hosted Mode
Now that you’ve created the application and have seen what it
generates, let’s execute it.
You can easily run the project by using the
TodoApp-shell script from the command line. Although this is a
perfectly correct way to launch the application, you might prefer to
launch it directly from within JDeveloper. To do so, click the Run menu
and select Choose Active Run Configuration > Manage Run
Configurations. Edit the default run configuration and use the
following:
- For the Default Run Target: Use the
com.google.gwt.dev.GWTShell that’s
inside your platform-specific GWT jar. On Linux it will look like this:
path.to.your.gwt.installation.directory/gwt-devlinux.jar!/com/google/gwt/dev/GWTShell.class
On Windows it will look like this:
path.to.your.gwt.installation.directory/gwt-dev-windows.jar!/com/google/gwt/dev/GWTShell.class
- For the Program Arguments, use:
-out path.to.your.gwt.installation.directory/otn/www otn.todo.TodoApp/TodoApp.html
- For the Run Directory, use
path.to.your.gwt.installation.directory/otn
The end result should look like this:

To run your application, you must add two more libraries to its
classpath: the GWT platform-specific jar and the
application’s src directory:

You should now be able to run the application from JDeveloper.
This was quite a complicated setup, but thankfully,
you can reuse it for debugging the application: just use the Debug
button instead of the Run button. You can then use the debugger as
usual—set breakpoints, execute the code step-by-step, and so
on:

What’s particularly impressive about this feature is that you
can debug the client-side code written in Java with the standard
JDeveloper debugger.
Extending Your GWT Web App
Now that you’ve created a simple GWT Web
application,
let’s extend it using two of the most commonly used GWT
features: the RPC mechanism, which allows the application to call
server-side code, and the History object, which allows the user's
precise handling of the browser’s Back button.
Data Exchange Between Client and Server Using RPC
Thus far, you’ve created only the
client-side code of our
application: using the GWT compiler, you’ve generated a
number of HTML and JavaScript files that will run in the
end-user’s browser. However, this application won’t
be of much use if it can’t communicate with the server.
With GWT, client/server communication is a matter of
coding a servlet and making it communicate with the application.
Here’s what you have to do.
Create
an interface that defines your service. This interface
must extend Google’s
com.google.gwt.user.client.rpc.RemoteService interface, and be placed
into the client package (otn.todo.client, in our example).
Next, code an interface that lets you read and write a
to-do list on the server:
package otn.todo.client; import java.util.List; import com.google.gwt.user.client.rpc.RemoteService; public interface TodoListBackupService extends RemoteService { /** * Save the to-do list on the server. */ void saveTodoList(List todoList); /** * Get the to-do list on the server. */ List getTodoList(); }
Code the Servlet. On the server side, you must code a class that:
- Extends Google’s
com.google.gwt.user.server.rpc.RemoteServiceServlet class (which, in
turn, extends Java’s javax.servlet.http.HttpServlet,
effectively making it a servlet)
- Implements the interface written in Step 1
- Is located in the server package (otn.todo.server,
in our example)
package otn.todo.server;
import java.util.ArrayList; import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession;
import otn.todo.client.Todo; import otn.todo.client.TodoListBackupService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
public class TodoListBackupServiceImpl extends RemoteServiceServlet implements TodoListBackupService {
private static final String TODOLIST_KEY = "TODOLIST_KEY"; public void saveTodoList(List todoList) { HttpServletRequest request = this.getThreadLocalRequest(); HttpSession session = request.getSession(); session.setAttribute(TODOLIST_KEY, todoList); }
public List getTodoList() { HttpServletRequest request = this.getThreadLocalRequest(); HttpSession session = request.getSession(); if (session.getAttribute(TODOLIST_KEY) == null) { List todoList = new ArrayList(); Todo todo = new Todo("Hello from the server"); todoList.add(todo); return todoList; } else { return (List) session.getAttribute(TODOLIST_KEY); } } }
This servlet stores only the to-do list in the user’s
HttpSession; this, of course, is a basic way of saving data. In a
normal application, you could use JNDI to access EJBs, or any of the
classic patterns used to access a business service from a servlet.
Finally, you must configure this servlet inside the
servlet container. If you’re using the GWT shell, you can
configure it inside the *.gwt.xml configuration file, which is
TodoApp.gwt.xml in our example:
<module> <!-- Inherit the core Web Toolkit stuff. --> <inherits name='com.google.gwt.user.User'/> <!-- Specify the app entry point class. --> <entry-point class='otn.todo.client.TodoApp'/> <servlet path="/todoListBackupService" class="otn.todo.server.TodoListBackupServiceImpl"/> </module>
If you want to configure it within another application server, such as
OC4J, just add the usual XML configuration into the WEB-INF/web.xml
file:
<servlet> <servlet-name>TodoListBackupService</servlet-name> <servlet-class>otn.todo.server.TodoListBackupServiceImpl</servlet-class> </servlet> <servlet-mapping> <servlet-name>TodoListBackupService</servlet-name> <url-pattern>/todoListBackupService</url-pattern> </servlet-mapping>
Add some glue. The glue we need is the Async class, which must follow
several rules:
- It’s located in the client package
(otn.todo.client).
- It has the same name as the interface described in
Step 1, with the addition of Async at the end.
- It has the same methods as the interface described
in
Step 1, but they all get an additional parameter,
com.google.gwt.user.client.rpc.AsyncCallback callback.
package otn.todo.client;
import java.util.List;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface TodoListBackupServiceAsync {
/** * Save the to-do list on the server. */ void saveTodoList(List todoList, AsyncCallback callback);
/** * Get the to-do list on the server. */ void getTodoList(AsyncCallback callback); }
Use it inside the application. To access the server-side code from
within the client application, use the com.google.gwt.core.client.GWT
class, which can create a very special object:
TodoListBackupServiceAsync todoListBackupService = (TodoListBackupServiceAsync) GWT.create(TodoListBackupService.class);
This creates at runtime a class implementing two interfaces:
- The Async interface we just coded in Step 3
- Google’s
com.google.gwt.user.client.rpc.ServiceDefTarget interface
The second interface is used to configure the class so that it can
point to the servlet defined in Step 2:
ServiceDefTarget endpoint = (ServiceDefTarget) todoListBackupService; endpoint.setServiceEntryPoint("/todoListBackupService");
Now that you’ve configured this object to access the
server-side service, let’s access the service. As
you’ve seen in Step 3, the Async interface lets you access
all the methods defined in the service, with the addition of the
AsyncCallback callback parameter. This parameter is used to define the
application’s behavior, depending on the success or failure
of the server-side call:
AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { printTodoList(); }
public void onFailure(Throwable caught) { Window.alert("Warning : the to-do list could not be saved on the server. Maybe the server is down."); } };
Let’s put it all together. Here’s the complete code
of the two client-side methods accessing the TodoListBackupService
business service: one for saving the to-do list on the server side, the
other for reading it:
/** * Update the to-do list with data from the server. */ private void updateTodoListFromServer() { TodoListBackupServiceAsync todoListBackupService = (TodoListBackupServiceAsync)GWT.create(TodoListBackupService.class);
ServiceDefTarget endpoint = (ServiceDefTarget)todoListBackupService; endpoint.setServiceEntryPoint("/todoListBackupService");
AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { todoList = (List)result; saveTodoListInHistory(); }
public void onFailure(Throwable caught) { Todo todo = new Todo("ERROR!! Server could not be reached."); todoList.add(todo); saveTodoListInHistory(); } };
todoListBackupService.getTodoList(callback); }
/** * Save the to-do list on the server. */ private void saveTodoListOnServer() { saveTodoListInHistory(); TodoListBackupServiceAsync todoListBackupService = (TodoListBackupServiceAsync)GWT.create(TodoListBackupService.class);
ServiceDefTarget endpoint = (ServiceDefTarget)todoListBackupService; endpoint.setServiceEntryPoint("/todoListBackupService");
AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { printTodoList(); }
public void onFailure(Throwable caught) { Window.alert("Warning : the to-do list could not be saved on the server. Maybe the server is down."); } };
todoListBackupService.saveTodoList(todoList, callback); }
The example application makes a server-side call at startup. This call
returns the latest to-do list saved in the user’s
HttpSession, or a new to-do list containing the “Hello from
the server” to-do:

Managing the Back Button
In high-end Web applications, the browser’s
Back button is
too often broken. Classic Ajax applications don’t support the
standard Web behavior of returning you to the previous Web page.
GWT, on the other hand, allows for programmatic
handling
of the Back button. This is a powerful yet tricky feature that
we’ll explore using our example application. The idea is to
use the Back button as an Undo button: clicking it will show you the
to-do list as it was before the latest event. Similarly, the Forward
button will work as a Redo button.
Implement the HistoryListener interface. In order to
manage the Back button programmatically, the GWT application must
implement the com.google.gwt.user.client.HistoryListener interface.
This forces the writing of the onHistoryChanged(String _historyToken)
method:
public class TodoApp implements EntryPoint, HistoryListener {
/** * This method is called whenever the application's history changes. */ public void onHistoryChanged(String _historyToken) { if (Integer.parseInt(_historyToken) + 1 != historyToken) { if (historyMap.get(_historyToken) != null) { historyToken = Integer.parseInt(_historyToken); todoList = (List) historyMap.get(_historyToken); } } printTodoList(); }
This method is meant to receive events when the browser’s
history is changed. You must add it as a listener to the
GWT’s History object. This is typically done in the
onModuleLoad() method, so that the History object is correctly
initialized at startup:
/** * This is the entry point method. */ public void onModuleLoad() {
History.addHistoryListener(this); }
Now, the onHistoryChanged(String _historyToken) method is called each
time the browser’s history is changed.
This method is able to recreate the
application’s state according to a token that’s
passed as a parameter. In our example, you'll use that token as a key
to find a to-do list stored inside a history map.
Add items to the history. In order for the
onHistoryChanged(String _historyToken) method to work, you must have
stored items in the history beforehand.
This is easily done with the History object, using its
static newItem(String historyToken) method:
private void saveTodoListInHistory() { List todoListClone = new ArrayList(); Iterator it = todoList.iterator(); while (it.hasNext()) { Todo todo = (Todo) it.next(); todoListClone.add(todo.clone()); } historyMap.put(String.valueOf(historyToken), todoListClone); History.newItem(String.valueOf(historyToken)); historyToken++; }
In our example, you stored the application state in a map so it can be
found using the history token. Note that you used a number as the
history token, but that any string could be used instead.
Deploying Your Web App
To deploy a Web application made with GWT, you compile
the client-side
code, package the result inside the .war file of your Web application,
and then deploy the .war file on your favorite application server,
OC4J.
Compiling the Client-side Code
There are several ways to compile your client-side
code.
When you used
the applicationCreator script, GWT creates a shell script named
TodoApp-compile. You can launch it from the command line. Like
TodoApp-shell, it’s a fine way to compile the application;
however, you may prefer to launch it directly from within JDeveloper.
Another way to compile your code is to execute your
application in Hosted mode so it can be done directly from JDeveloper.
The toolbar of your application’s window contains a
compile/browse button, like this:

At the end of the compilation process, your default Web browser will
open so you can test the result. The window of the GWT development
shell will show if the compilation was successful:
Regardless of how you compile your code, you’ll find the
generated files in the www/otn.todo.TodoApp of your project.
The last way to compile your code is to use Ant. GWT
doesn’t provide a specific Ant task, but you can launch any
Java class (such as GWTCompiler) with the standard Java Ant task.
First, define the path to include the GWT jars:
<path id="project.class.path"> <pathelement path="${java.class.path}/"/> <pathelement location="src"/> <pathelement path="/your/path/to/gwt-user.jar"/> <pathelement path="/your/path/to/gwt-dev-linux.jar"/> <!-- ... --> </path>
Now, define a task dedicated to the compilation of your client-side
code:
<target name="GWTcompile"> <java classpathref="project.class.class.path" classname="com.google.gwt.dev.GWTCompiler" fork="true"> <arg value="-out"/> <arg value="${gwt.output.dir}"/> <arg value="${entry.point.class}"/> </java> </target>
Set the gwt.output.dir and entry.point.class variables in a properties
file, like this:
gwt.output.dir=www entry.point.class=otn.todo.TodoApp
Finally, declare the properties file (here, build.properties) inside
your Ant script, like this:
<property file="build.properties"/>
You can directly launch this new target by selecting Run Target
GWTCompile in the Context menu of the task:
GWTcompile: [java] Output will be written into www\otn.todo.TodoApp [java] Compilation succeeded
BUILD SUCCESSFUL
Deployment in OC4J
Once you have compiled the application, deploying it
under OC4J is just
a matter of creating a correct deployment profile. If you followed the
steps described earlier, you should already have a default deployment
profile. Otherwise, just select File > New... >
Deployment Profiles > WAR File, and create a new profile.
Using your configuration, everything should work out
of
the box. However, if you encounter any problems, check for the
following common mistakes:
- In Project Properties, in Project Content >
Web Application, the HTML Root Directory should be your
application’s www directory (where GWT will compile the
application for running in Hosted mode).
- In the deployment profile, in File Groups >
WEB-INF/lib > Contributors, the gwt-user.jar should be added.
This jar file includes the javax.servlet package from the J2EE
specification. This didn’t cause any problems in our example;
however, you shouldn’t usually deploy those classes inside a
Web application, as they may cause some trouble. If this happens, GWT
also provides a gwt-servlet.jar file, which is the gwt-user.jar without
the javax.servlet package.
- The Web application’s context root
affects
GWT’s RPC mechanism. If your GWT client application is
talking to the server, as described in “Data Exchange between
client and server using RPC”, it must be able to find the
server. That’s the purpose of the
endpoint.setServiceEntryPoint("") method that we’ve
discussed. In our example, we deployed the application on the root of
the server, which is how the GWT shell works by default. But if you
deploy the application to the TodoApp Web context (in the deployment
profile’s general properties), set the endpoint to
/TodoApp/todoListBackupService, not to /todoListBackupService.
Don’t forget that this URL should also be correctly mapped in
the application’s web.xml file, as described earlier.
- Assuming that OC4J is correctly installed on your
system,
deploying the application to the server is simple: just right-click the
deployment profile and select Deploy to OC4J.
The deployed application has two parts:
- The client-side application is a set of HTML and
JavaScript files that were compiled previously. (See the section
“Compiling the Client-side Code.”) OC4J serves as a
classic Web server, which delivers those files to the user.
- The server-side application is basically a servlet
that handles the RPC communication. Once deployed in OC4J, this servlet
can access enterprise resources such as EJBs or JMS providers.
Performance-wise, serving static resources is very
efficient; the main performance bottleneck of our application should
come from client/server communication. But thanks to OC4J, we have
access to some interesting server-side performance graphs:
As this graph shows, under normal load (a few
requests per second) the server-side part of the application responds
in less than 4 ms on average—an excellent result.
Stéphanie
Antoine is a senior J2EE developer
working for a major French software consultancy firm. Julien Dubois and Jean-Philippe Retaillé
are both J2EE experts and authors; their latest book, Spring par la Pratique
(Eyrolles, 2006) is the first French book about the Spring J2EE
framework.
Send us your comments
|