Building a GWT RPC Service – Tutorial

Posted December 8th, 2007 by

Introduction

If you haven’t already please read our previous tutorials: Introduction to GWT, and Anatomy of a GWT Project.

As you already know, GWT is a Java framework that allows you to easily develop AJAX (Asynchronous JavaScript and XML) based web applications. The difference between GWT (AJAX based web) applications and traditional (non AJAX based) web applications is that GWT applications do not need to fetch new HTML pages from the server when they want to make User Interface (UI) changes. A GWT application behaves like a regular client/server application that happens to be running in a browser. The GWT application can fetch data from the server as it executes and update only the specific parts of the UI that need to be updated.

To learn more about GWT, I recommend reading these good books – GWT Solutions, GWT Applications, AJAX Security.

What is GWT RPC?

One of the most important pieces of the GWT framework is the GWT Remote Procedure Call (RPC) mechanism. This RPC mechanism makes it easy for a GWT application client to make a call to server-side code. GWT RPC makes it simple to get data between the client and the server.

What is a GWT service?

The server-side code that gets called from the client is referred to as a service (not to be confused with SOAP web-services). During a service call, the GWT RPC makes it easy for client and server to pass Java objects back and forth over HTTP.

GWT services can be used to accomplish tasks that are part of your application, but cannot be done on the client computer. Proper use of GWT services can allow you to develop an application where all the UI logic resides on the client, resulting in an application with greatly improved performance, reduced bandwidth, and reduced web server load. This will also result in a user experience that is similar to using a desktop application, and is far more compelling than the experience of visiting a simple web page.

GWT’s RPC mechanism hides all the plumbing necessary to create and consume services. All the proxy classes that handle RPC plumbing for making the server-side code invocation and for converting data back and forth between the client and server are all generated automagically. All you need to do is define your service’s interface and its server-side implementations.

Asynchronous – the A in AJAX

All network operations in GWT are asynchronous, or non-blocking, i.e. they return immediately after they are called, and require the user to use a callback method to handle the results when they are eventually returned from the server.

The reason for using asynchronous operation is that most browsers’ JavaScript engines are single-threaded. A blocking on a call to XMLHTTPRequest (a JavaScript Object defined by browsers to enable a web page to send HTTP requests) in a browser based application, would block the UI thread until a response was received from the server. This would make it appear as though the browser was frozen for the duration of the connection to the server. Some browsers provide a way around this, but there is no clean, universal solution. As a result, GWT does not implement any synchronous network connections.

Sending data back and forth between client and server

Because GWT RPC calls are between JavaScript (on the client) and Java code (on the browser), GWT provides object serialization as part of its RPC mechanism to help bridge the language divide. Please note that GWT serialization is not the same as Java serialization. You need to ensure that any object that needs to be sent between the client and server is of a GWT serializable type. A type is serializable and can be used in a service interface if the type:

  • is primitive, such as char, byte, short, int, long, boolean, float, or double;
  • is String, Date, or a primitive wrapper such as Character, Byte, Short, Integer, Long, Boolean, Float, or Double;
  • is an array of serializable types (including other serializable arrays);
  • is a serializable user-defined class; or
  • has at least one serializable subclass

This is only a brief overview of GWT serialization. To learn more about the details of GWT object serialization, and how to create complex serializable objects, check out this tutorial.

Need more help? developerlife.com offers training courses to empower you, and consulting services to enable you.

GWT service demo – The String Reverser Application

A simple GWT application that reverses the order of the characters in a string will be used to demonstrate how to build a GWT service. The String Reverser application consists of a simple form-like UI with a text box where the user can enter a string. Users can press a button to have the string reversed. When the button is pressed, the application will make an asynchronous call to a String Reverser Service. The client will send the user-entered string to the service and a callback as the service call parameters. Once the call is made, server-side code will reverse the order of the characters in the string and return the reversed string to the client via the callback. The rest of this tutorial will focus on the String Reverser Service.

Building and calling a GWT service

There are three steps involved in creating a GWT service:

  1. Defining the service’s synchronous and asynchronous interface
  2. Implementing the service
  3. Calling the service

1. Defining a GWT service

Synchronous Interface

The first step in creating the String Reverser Service is defining the service’s client-side interface. The interface must extend the GWT RemoteService interface and contain the signatures of the service methods that should be exposed to the client. Method parameters and return types must be serializable.

The code snippet below shows the client-side class (StringReverserService) which defines the synchronous interface for the String Reverser Service.

public interface StringReverserService extends RemoteService {
  public String reverseString(String stringToReverse);
}

Asynchronous Interface

A client-side asynchronous interface, based on the synchronous interface, must be built before a service call can be made. The nature of asynchronous method calls requires the caller to pass in a callback object (AsyncCallback). This callback object is used to notify the caller when an asynchronous call completes. Asynchronous methods cannot have return types, and so they must always return void. After an asynchronous call is made, all communication back to the caller is via the passed-in callback object.

A service’s asynchronous interface must be in the same package and have the same name, but with the suffix “Async”. E.g. if a service interface is called com.example.app.client.RandomService, the asynchronous interface must be called com.example.app.client.RandomServiceAsync.

An asynchronous “sibling” method should be defined for each method in your service’s synchronous interface. The method signature for these asynchronous sibling methods is the same as the synchronous methods signature, but with the addition of an asynchronous callback. If the synchronous interface method is:

public ReturnType methodName(ParamType1 one, ParamType2 two);

the asynchronous sibling method will be:

public void methodName(ParamType1 one, ParamType2 two, AsyncCallback callback);

The code snippet below shows the client-side class (StringReverserServiceAsync) which defines the asynchronous interface for the String Reverser Service.

public interface StringReverserServiceAsync {
  void reverseString(String stringToReverse, AsyncCallback async);
}

2. Implementing a GWT service

Now that the service interfaces have been defined, the next step is to implement the service methods. These methods are implemented in a class that extends GWT’s RemoteServiceServlet class. This service implementation can be hosted in any servlet container.

For the String Reverser Service, the service implementation will take the user-entered string that was passed to the service and reverse the order of the characters. Once reversed, the reversed string is returned.

The code snippet below shows the server-side class (StringReverserServiceImpl) which implements the String Reverser Service Interface.

public class StringReverserServiceImpl extends RemoteServiceServlet implements StringReverserService {
  /**
    * This method is used to reverse a string
    * @param stringToReverse The string that you want reversed
    * @return                The reversed string
    */
  public String reverseString(String stringToReverse) {
    StringBuffer reverse = new StringBuffer(stringToReverse.length());
    for (int i = (stringToReverse.length() - 1); i >= 0; i–)
      reverse.append(stringToReverse.charAt(i));
      return reverse.toString();
  }
}

3. Calling a GWT service

Once a service has been defined and implemented, it can be called from a client. The process of making a GWT RPC call from the client involves the following steps:

a. Instantiate the service interface using GWT.create().

Before we can use the service, we need to instantiate an instance of the service. The following listing demonstrates how to create an instance of StringReverserService. Note that although an instance of the synchronous service interface is being created and then cast to asynchronous version of the interface. The cast is always safe because the generated proxy implements the asynchronous interface automatically.

The code snippet below shows you how to instantiate the String Reverser Service.

1: StringReverserServiceAsync reverserService = (StringReverserServiceAsync) GWT.create(StringReverserService.class);

b.Specify a service entry point URL for the service using ServiceDefTarget.

Once an instance of the service is created, we need to specify the URL at which the service implementation is, or will be, running. The target URL for the service must reside on the same domain and port from which the host page was served. This is due to the fact that most modern browsers implement the “Single Origin Policy” (SOP) security model. The SOP policy makes it so that JavaScript code running in a currently loaded web-page can only interact with resources originating from sites with the same domain name and port as the currently loaded web-page.

The code snippet below shows you how to specify the URL for the String Reverser Service Implementation.

((ServiceDefTarget) reverserService).setServiceEntryPoint( GWT.getModuleBaseURL() +
                                                           "/StringReverser/StringReverserService");

c. Create an AsyncCallback object so that the client can be notified when the service call is completed.

The next step is to create an Asynchrounous Callback (AsyncCallback) object. This object will be passed as a parameter to the remote service when it is called. As was mentioned before, all network operation is GWT are asynchronous and non-blocking. When a call to the service is made, there is no immediate value returned. Since the service call is asynchronous and non-blocking, the GWT application will not wait for a response from the service. It will continue executing until it receives an asynchronous callback from the service. This callback informs the GWT application whether or not the service call has been executed successfully.

If the service call is unsuccessful, the onFailure method of the AsyncCallback object is called. If the service call is successful, the onSuccess method of the AsyncCallback object is called. The onSuccess method accepts a value of type java.lang.Object as a parameter. If your service returns data, this result object is it. It is always safe to downcast the parameter to the return type of the service method. Note that if the return type of the synchronous service interface method is a primitive (int, long, etc) then the parameter will be the boxed version of the primitive (for example, an int return type becomes an Integer).

The following code snippet shows you how to create an AsyncCallback object.

AsyncCallback callback = new AsyncCallback() {
    // This method will be called if the service call fails   
    public void onFailure(Throwable caught) {
      // Show a message informing the user why the call failed   
      Window.alert("Failed to get response from server" + caught.getMessage());
    }
    // This method will be called if the service call succeeds   
    public void onSuccess(Object result) {
      // Get the service call result and cast it to the desired type and display it
      String reverse = (String) result;
      Window.alert(reverse);
    }
};

d. Make the call :)

The final step is to make the service call. The following code snippet demonstrates how to make the call to the String Reverser Service.

1: reverserService.reverseString(stringToReverse, callback);

Putting it all together

The following code snippet shows the sections of the String Reverser widget (StringReverserWidget.java) where the call to the String Reverser Service is made. Note that AsyncCallback below is created as an Anonymous Inner Class when the String Reverser Service is called.

/**
  * Method used to get an instance of the String Reverser Service
  *
  * @return  Reversed String
  */
private StringReverserServiceAsync getReverserServiceInstance() {
  if (reverserService == null) {
    // Instantiate the service 
    reverserService = (StringReverserServiceAsync) GWT.create(StringReverserService.class);
    // Specify the URL at which the service implementation is running.
    // The target URL must reside on the same domain and port from
    // which the host page was served.
    ((ServiceDefTarget) reverserService).setServiceEntryPoint( GWT.getModuleBaseURL() +
                                                               "/StringReverser/StringReverserService");
   }
   return reverserService;
}
/**
  * Method used to call the String Reverser Service. The response from the service is displayed in a dialog box after
  * it is received.
  *
  * @param stringToReverse String that you want reversed
  */
public void callStringReverserService(final String stringToReverse) {
  // Show the loading message and animation
  showLoadingMessageAndAnimation();
  // Call the String Reverser Service
  // The asynchronous callback used to handle the service response is created inline.
  //    If the service call fails, a message will be displayed on the client
  //    If the service call is successful, the reversed string will be displayed
  getReverserServiceInstance().reverseString(stringToReverse, new AsyncCallback() {
    public void onFailure(Throwable caught) {
      // Reset the button text and remove the loading animation
      resetWiget();
      Window.alert("Failed to get response from server");
    }
  public void onSuccess(Object result) {
    // Reset the button text and remove the loading animation
    resetWiget();
    // Get the service call response and display it
    String reverse = (String) result;
    ReversedStringDisplayDialog dlg = new ReversedStringDisplayDialog(stringToReverse, reverse);
    dlg.show();
  }
});
}

Downloads

All the source code provided on this site is distributed under the Apache Open Source License v2.0.

  1. You can download the full source code used to build the String Reverser Application here.
  2. You can download the WAR file to deploy the String Reverser Application here.

What’s next?

To learn how to transport transport Objects over RPC using GWT Object Serialization, click here.

Coming Soon – Build simple and complex UIs using GWT.


Comments are closed.