Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Build an Ajax application using Google Web Toolkit, Apache Derby, and Eclipse, Part 3: Communication

Remote Procedure Calls (RPCs) and Google Web Toolkit

Noel Rappin, Senior Software Engineer, Motorola, Inc.
Noel Rappin, a Ph.D. from the Graphics, Visualization, and Usability Center at the Georgia Institute of Technology, is a senior software engineer at Motorola. He is also the coauthor of wxPython in Action and Jython Essentials. You can check out Noel's blog at 10printhello.blogspot.com.

Summary:  In the last two articles in this series, you've discovered how to create a simple Web application using the Google Web Toolkit (GWT) and the Apache Derby relational database. Part 1 focused on using GWT to build the front end for a pizza delivery system called Slicr. In Part 2, you got a demonstration of the creation of a relational database using Derby, and a bare-bones demonstration of a mechanism for converting the database rows to Java™ objects. Now it gets interesting! In this third article, find out how to get the client and server talking to each other. You'll use the Remote Procedure Call (RPC) framework within GWT to make getting data off the server almost as simple as making a Java method call.

View more content in this series

Date:  13 Feb 2007
Level:  Intermediate
Also available in:   Chinese  Korean  Russian  Japanese

Activity:  17382 views
Comments:  

The A in Ajax

The key difference between an Asynchronous JavaScript + XML (Ajax)-enabled Web application and a traditional Web application is the A in Ajax: asynchronous. An Ajax application allows the browser to update a specific part of the page without having to completely refresh the entire page. This simple trick enables a much more interactive user experience, as a simple Web page now behaves much more like a desktop application.

From the developer's point of view, this asynchronous behavior has two key components:

  • The XMLHttpRequest object is a JavaScript object defined by the browser that enables a Web page to send HTTP requests and receive a response in a background thread. Unlike a typical page request, the call doesn't interrupt the user experience, and the browser doesn't pause while waiting for the response.
  • Some kind of callback is executed after the response is complete. That callback usually uses the JavaScript Document Object Model (DOM) to manipulate the elements of the page based on the new data. Something cool happens on screen, and the user is happy.
Check out the Ajax Resource Center, your one-stop shop for information on the Ajax programming model, including articles and tutorials, discussion forums, blogs, wikis, events, and news. If it's happening, it's covered here.

So that's the basic flow: a call to the server, a response back, and actions taken to the page based on the response. Again, the important thing to remember is that all of this takes place behind the scenes without the busy waiting and refreshing associated with a typical change of page in a browser.

There's only one problem with the whole XMLHttpRequest/DOM method: It's kind of a pain in the neck. Each browser implements the relevant JavaScript objects differently, for one thing. For another, getting data to the server can be awkward, and so can converting the response into useful data. As a result, every Ajax framework worthy of the name has some kind of simplification wrapper around the creation, calling, and management of RPCs. GWT is no exception.

GWT manages RPCs with a multiple-interface infrastructure somewhat reminiscent of Enterprise JavaBeans (EJB) technology, but -- thankfully -- a lot simpler. The deal is that you define the list of remote calls that your system makes. GWT implements the behind-the-scenes plumbing for converting data to go back to the server, making the server call, and converting the returned data back to client data. You then define what to do after the remote call has completely returned. It's not quite as easy as making a normal Java method call, but it's not difficult.

The change you're going to make to the Slicr application is to retrieve the initial list of toppings from the server database rather than hardcoding them into the client code. This admittedly simplistic example walks you through all the steps needed to make an RPC call. To run this example easily, run in hosted mode. In hosted mode, GWT automatically simulates your remote calls. You'll get some support for working in hosted mode if you use an integrated development environment (IDE), such as Eclipse or IntelliJ IDEA.

Note: In the final article in this series, I'll show you how to run your server side in a normal servlet environment.

Define services

The bulk of the work in your GWT procedure call happens in two classes. On the server side, you define a subclass of RemoteServiceServlet. In this class, you manipulate the server data and return a value to the client (or throw an exception, but let's stay optimistic for the moment). On the client side, you define a class that implements the interface AsyncCallback. In this class, you define what the client page does with the data (or the exception) when the server is done. In addition to these two classes, you must write some glue code that allows GWT to bind the client-side class and the server-side class together. OK, there's rather a lot of glue code. The glue code consists of two different interfaces plus some client-side code and a setting or two. But don't worry; most of the code is boilerplate, and if you just take it step by step you'll be fine.

Start on the server side. Your goal here is merely to generate a list of all the toppings you placed in the database at the end of the previous article. The server uses the simple ObjectFactory from that article (see Listing 1) to help you out.


Listing 1. Topping service implementation
	
public class ToppingServiceImpl extends RemoteServiceServlet 
		implements ToppingService {

	public static final String DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";

	public static final String PROTOCOL = "jdbc:derby:slicr;";

	public List getAllToppings() {
		try {
			Class.forName(DRIVER).newInstance();
			Connection con = DriverManager.getConnection(PROTOCOL);
			Statement s = con.createStatement();
			ResultSet rs = s.executeQuery(
			        "SELECT * FROM toppings order by name");
			return ObjectFactory.convertToObjects(rs, Topping.class);
		} catch (Exception e) {
			e.printStackTrace();
			return new ArrayList();
		} finally {
			try {
				DriverManager.getConnection("jdbc:derby:;shutdown=true");
			} catch (SQLException ignore) {}
		}
	}

}

The first thing to notice about this code is that there really isn't anything all that fancy about it. The requirements for a GWT remote service are simply that it must extend RemoteServiceServlet and implement an interface that you'll create in about two paragraphs from here.

Note: It seems as though most GWT documentation has you create the interfaces first. That's fine, it really doesn't matter. I just thought it would be clearer with the concrete code first.

Other than that, this code has much the same functionality as the ToppingTestr example from the previous article, repackaged for use within GWT. You make a call to the Derby database, use the object factory to create topping objects, and return them.

Glue code

To make your new service available to your client-side application, you must define two related interfaces. The first is the ToppingService interface used, but not described, in Listing 1. It's really simple, shown here in Listing 2.


Listing 2. Defining the first related interface, ToppingService
public interface ToppingService extends RemoteService {
	public List getAllToppings();
}

All you've done here is take the same signature you used for the method in the actual concrete class. The main constraint here is that your interface must extend com.google.gwt.user.client.rpc.RemoteService;. Also, your parameters and return value must be of types that GWT can serialize. A list of those types is provided in Part 2. However, it's not enough to have only one version of your service interface. You must also define an asynchronous version of the interface, as shown in Listing 3.


Listing 3. Defining an asynchronous version of the interface
public interface ToppingServiceAsync {
	public void getAllToppings(AsyncCallback callback);
}

The asynchronous version of the service interface is derived from the primary version described above. The two versions must be in the same package, and that package must be visible to your GWT client code. (I used com.ibm.examples.client ). The class name in the asynchronous version must be the name of your original interface with the string Async added to the end. For each method in your original interface, the asynchronous version must have a matching method with the return type changed to void and an additional parameter of type AsyncCallback. The client-side code uses AsyncCallback to act on the server response.

You are perfectly free to have as many methods in a single service interface as you like, as long as they all have siblings in the asynchronous version and are all implemented in the same remote service class. How you organize the services is largely an aesthetic decision, although I suppose there might be practical value in having service methods able to share common data on the server side.

One more thing, and then your server code will be registered. Add the following line to the Slicr.gwt.xml file:

<servlet path="/toppings" class="com.ibm.examples.server.ToppingServiceImpl"/>



The above line pairs the fully qualified class name of the concrete remote service class with a path name that is essentially the URL for this service. You can use any name you want as long as you remember it and are consistent later. Technically, you need to include only this line in the .xml file if you are going to run your application in hosted mode. As you'll see next time, in a Web deployment, you need something similar in your web.xml file.

That's a lot of things to keep consistent for a single call -- the interface, the asynchronous interface, the actual implementation, and the module file. Missing one or getting the match incorrect leads to errors when you try to actually invoke the service. As of this writing, at least one IDE (IntelliJ IDEA) provides support in the editor for keeping all these items in a consistent state. If you're using Eclipse, the Googlipse plug-in also provides similar support.

Make the client-side call

With the server side taken care of, it's now time for the client to make the procedure call. The basic idea here is that you carefully tell the GWT system which remote service you're calling. You then send an AsyncCallback object out into the ether; eventually, GWT sends it back to you, and you can act on the result. Listing 2 shows the code for the setup and call. This method is in the Slicr class from Part 1. Specifically, the call to this method replaces the line in Slicr.onModuleLoad() that added the topping panel.


Listing 4. Setup and call
	
public void callForToppings() {
	ToppingServiceAsync toppingService = 
		(ToppingServiceAsync) GWT.create(ToppingService.class);
	ServiceDefTarget target = (ServiceDefTarget) toppingService;
	String relativeUrl = GWT.getModuleBaseURL() + "toppings";
	target.setServiceEntryPoint(relativeUrl);
	toppingService.getAllToppings(new ToppingCallback());
}

Each line is a critical step in your GWT call. Here's the checklist:

  1. Create an instance of the asynchronous interface. Typically, of course, you can't create an instance of an interface, which is where the GWT.create() call comes in. The GWT class is a catch-all for several utilities. In this case, it allows you to create a proxy object that implements a given interface. Note that in deployment, the argument to this method must be a literal rather than a variable. Variables work in hosted mode, though, so be careful.
  2. The proxy object that GWT.create() returns also implements another interface, ServiceDefTarget. In a line or two, you're going to need a method in that interface.
  3. Calculate the URL that you need to send the message to. The URL has two components:
    • The base URL for the system, which you get by calling GWT.getModuleBaseURL()
    • The same string you used as the path back when you added the servlet to the .xml file
  4. Armed with the full URL, you can inform GWT that this particular URL is the place to go for this particular service by calling the setServiceEntryPoint() method. The interface also contains the related getter method. At this point, the service is fully initialized for use in this client page.
  5. And finally -- drum roll, please -- you can make the actual call to the service, just as the service defines it (except for that ToppingCallback object, which is the subject of the next section).

You need to initialize only the service (the first four lines of the example) once in your client page. After the service is created and associated with its entry point, you can reuse the same service object to make multiple calls back to the server. You can also create some helper methods to simplify the boilerplate initialization of the server object.

The joy of asynchrony

As I alluded to before, a big difference between a GWT RPC and a regular method call is that you don't know when or if the remote call is going to be completed. Because Web users don't normally take kindly to having entire pages freeze up while you refresh the select box in the corner, your GWT program makes its remote call and continues on its merry way. Eventually, the server will eke out a response, and only at that point does your GWT code do the wonderful thing you have planned.

Often, keeping track of the background threads in this kind of environment can be a challenge. However, in your case, GWT does most of the work with the mechanism described above and the AsyncCallback interface that you've already seen. GWT effectively simplifies the overhead of dealing with multiple threads.

The AsyncCallback interface defines two methods: OnSuccess(Object obj) and OnFailure(Throwable t). You must define a class that implements both. You create an instance of the class and pass it to your asynchronous service method when you make your remote call, as seen in Listing 4. Eventually, the server-side resource is complete, and one of the two methods in the code is called. The argument to the success method is the return value of the call in the interface and implementation. In your case, that's the list of toppings. You'd cast it to the expected type, and then do something useful with the new data. Hopefully, GWT will support Java 1.5 generics sometime soon, which would reduce the need for a lot of casting. If the server-side code fails, the failure method is called with the thrown exception as its argument. Again, you're free to do what you want to respond to the exception.

The code shown in Listing 5 shows the ToppingCallback class referred to in Listing 4. As I probably mentioned before, you'll frequently see AsyncCallback classes defined as anonymous inner classes. I'd recommend avoiding that. Your code will be much easier to read and test if the class has a name attached and isn't placed right in the middle of an entirely different block of code.


Listing 5. The ToppingCallback class
	
public class ToppingCallback implements AsyncCallback {

	public void onFailure(Throwable caught) {
	    GWT.log("Error ", caught);
		caught.printStackTrace();
	}

	public void onSuccess(Object result) {
		List allToppings = (List) result;
		VerticalPanel toppings = new VerticalPanel();
		toppings.add(new HTML("<h2>Toppings</h2>"));
		Grid topGrid = new Grid(allToppings.size() + 1, 3);
		topGrid.setText(0, 0, "Topping");
		topGrid.setText(0, 1, "Left");
		topGrid.setText(0, 2, "Right");
		for (int i = 0; i < allToppings.size(); i++) {
			Topping t = (Topping) allToppings.get(i);
			Button button = new Button(t.getName() );
			CheckBox leftCheckBox = new CheckBox();
			CheckBox rightCheckBox = new CheckBox();
			clearables.add(leftCheckBox);
			clearables.add(rightCheckBox);
			button.addClickListener(new ToppingButtonListener(leftCheckBox,
					rightCheckBox));
			topGrid.setWidget(i + 1, 0, button);	
			topGrid.setWidget(i + 1, 1, leftCheckBox);
			topGrid.setWidget(i + 1, 2, rightCheckBox);
		}
		toppings.add(topGrid);
		panel.add(toppings, DockPanel.EAST);
	}
	
}

An instance of the ToppingCallback class is sent by means of the asynchronous interface. GWT manages things behind the scenes so that first, the proper call is made to the server, then that the result of the server call is given to the callback object, and finally that the appropriate response method is invoked.

In this case, the failure option is easier to describe. If the server-side method throws an exception for any reason, control in the callback passes to the onFailure() method. The argument to this method is the exception or other throwable object that the server side has returned. This argument gives you a chance to respond gracefully to the failure, if possible. I use the method GWT.log(), which takes a string and a Throwable as arguments. This method prints a log message to the shell window for GWT hosted mode. As such, it only works in hosted mode; in Web mode, the method is ignored. The GWT.log() method is really meant for tracking during development. You'll probably want to use this method to put a nice default or error message in the part of the screen you were about to refresh, or perhaps redirect the entire browser to an error screen.

If you've read the first article in this series, you should notice almost immediately that the onSuccess() code is nearly identical to the buildToppingTypePanel() method in the original version. One of the differences is trivial: You're now looping over a list rather than an array, which causes minor changes in the loop control. I've also added the price of the topping to the display, because that information is also available in the database.

More profoundly, the previous version of the code was able to return the toppings panel back to the calling code, and the calling code was then able to add the toppings panel to the parent panel. In this code, you can't return a value, so you must add the newly created toppings panel to the parent as part of this method. When you run it, you'll see the Pizza panel show up first; then, after a small delay for GWT to simulate the server call, the Toppings panel will appear, as shown in Figure 1.


Figure 1. The New Topping panel
The New Topping panel

Even in this small example, moving to an asynchronous structure starts to have serious effects on the structure of the code. Just to start, the order in which the subpanels are added to the main panel was important in determining the final shape of each subpanel within the parent. As you move more of the initialization to RPC calls, you can no longer depend on the subpanels being created in order. You must separate the initial creation of the panels away from inserting the widgets inside them. (This should have the added benefit of reducing flickering when the new data is added.) The general goal is to keep the code inside the asynchronous callbacks as simple as possible and as disconnected from each other as possible. Having threads that depend on one another dramatically increases the complexity of your code.

What's next?

In this article, you worked through the process of creating a single RPC using GWT. At this point, you now have a legitimate GWT application. However, as of yet, that application runs only in hosted mode on your development machine. To show it to the great wide world, you must move over to Web mode and deploy your Web application within a servlet environment. Stay tuned for the final installment of this series, which will cover deployment.


Resources

Learn

Get products and technologies

  • Download the Google Web Toolkit.

  • Download Eclipse, the open source, freely available, and extensible IDE.

  • Innovate your next open source development project with IBM trial software, available for download or on DVD.

Discuss

About the author

Noel Rappin, a Ph.D. from the Graphics, Visualization, and Usability Center at the Georgia Institute of Technology, is a senior software engineer at Motorola. He is also the coauthor of wxPython in Action and Jython Essentials. You can check out Noel's blog at 10printhello.blogspot.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source, Information Management, Java technology, Web development
ArticleID=195838
ArticleTitle=Build an Ajax application using Google Web Toolkit, Apache Derby, and Eclipse, Part 3: Communication
publish-date=02132007
author1-email=noelrappin@gmail.com
author1-email-cc=ruterbo@us.ibm.com