Introduction to GWT Remote Procedure Calls (RPC) (with example application)
Services in GWT
Google Web Toolkit is a Web Application Framework dealing with Servers and Clients. When a Server is required to do some processing in a web-app Services must be used. A service is used to invoke server-side code from the client (and vice-versa occasionally).
In GWT the Client side code pages run more like an application within the Client (Browser), so requesting the HTML pages from the Server is not necessary. But in common with all Server-Client Architectures, even GWT needs to contact the Server as they execute, this is carried out by Remote Procedure Calls (RPC).
What is RPC?
RPC is a powerful technique for constructing distributed, client-server based applications. It is based on extending the notion of conventional or local procedure, so that the called procedure need not exist in the same address space as the calling procedure. GWT automatically generates most of the classes required for RPC.
Services: Creation and Implementation.
Before getting into RPC, we will have a look at relationships between various classes and interfaces that we are creating for a service. With GWT Framework classes we create certain classes and interfaces for THE RPC Service.
- Service: This is our service definition interface. This defines the methods in our service and extends the RemoteService marker interface that indicates that this is a GWT RPC service. This is the synchronous definition and the server-side implementation must implement this interface.
- ServiceAsync: The asynchronous definition of our interface. It must have the same methods as the synchronous interface, except for the requirement that all of its methods must have an AsyncCallback object as a parameter and the methods may not return anything. The naming convention recommended for this interface is to suffix the name of our synchronous interface with the word Async.
- Service Impl: This is the server-side implementation of our service. This must extend RemoteServiceServlet and implement our synchronous interface—Service.
Remote Procedure Call – In Detail
Client Creation:
To start with, we will create a client side code, by creating an Interface that extends the RemoteService Interface
public interface MyService extends RemoteService {
public String myMethod(String s);
}
Any implementation of this Service must extend the RemoteServiceServlet and should Implement this Service Interface:
public class MyServiceImpl extends RemoteServiceServlet implements MyService {
public String myMethod(String s) {
// Do something interesting with ’s’ here on the server.
return s;
}
}
Call Progress:
Now we need an Asynchronous Interface based on our Service Interface:
interface MyServiceAsync {
public void myMethod(String s, AsyncCallback callback);
}
If we are using Asynchronous method calls, then we have to have callback object that can serve as a messenger to indicate when the call is completed.
Asynchronous methods are always void, only the callback object is used for communication to the caller.
A service Interface and its Asynchronous counterpart have one simple relationship. The Asynchronous method must be in the same package as the Service Interface. If a service interface is called com.example.cal.client.AjaxMattersService, then the asynchronous interface must be called com.example.cal.client.AjaxMattersServiceAsync.
For each method in the Service Interface,
public ReturnType methodName(ParamType1 param1, ParamType2 param2);
the Asynchronous Interface must look something like this
public void methodName(ParamType1 param1, ParamType2 param2, AsyncCallback callback);
In order to respond to client requests, the service ultimately needs to perform some processing. Such server-side processing occurs in the service implementation. A service implementation must extend RemoteServiceServlet and must implement the associated service interface. One important thing that to be noted here is that, the service implementation does not implement the asynchronous version of the service interface. to simplify matters we can say that every service implementation is ultimately a servlet, but rather than extending HttpServlet, it extends RemoteServiceServlet instead.
//break//
How a Call is made?
The steps are pretty simple:
1. Instantiate the service interface using GWT.create().
2. Specify a service entry point URL for the service proxy using ServiceDefTarget.
3. Create an asynchronous callback object to be notified when the RPC has completed and make a call.
Serialization in GWT:
GWT tries really hard to make serialization as painless and as easy as possible, so while the rules regarding serialization are subtle, in practice the behavior becomes intuitive very quickly. That is the actually goal of GWT since it is involved in Web Applications. Serialization provides a simple and robust way to make object persistent and in case of RPCs, serialization plays a viral role. There are some conditions which GWT enforces for a type to be serializable and for it to be used in Service Interface.
Java objects and primitive types that can be serialized and transmitted via the GWT-RPC mechanism:
| Java primitive types | boolean, byte, char, double, float, int, long, short |
| Java primitive wrapper types | Boolean, Byte, Character, Double, Float, Integer, Long, Short |
| Subset Java objects | Only ArrayList, Date, HashMap, HashSet, String, Vector |
| User defined classes | Any class that implements IsSerializable |
| Arrays | An array of any of the serializable types |
Serializable User-defined Classes
A User Defined Class is said to be Serializable if it implements the IsSerializable interface. This is an interface that is part of the GWT library, and is used to signify that a class may be serialized via reflection techniques. This serves the same purpose as Java’s own java.io.Serializable interface, but is specific to GWT applications.
All non-transient fields in the class are serializable; by ‘
non-transient field’ we mean any field not using the transient modifier. GWT will also not serialize fields that have been marked as final, but don’t rely on this and be sure to mark all final fields as transient. The class has a zero argument constructor or no constructor at all.
Polymorphism
In terms of optimizations for the GWT compiler, it is good to be as specific as possible when specifying the types of your fields in the data object. For example it is common practice to specify java.util.List as a type instead of either ArrayList or Vector. The benefit of using a generalized type is that it allows you to change the underlying implementation without changing the type declaration. The problem is that when you generalize the type it is harder for the GWT compiler to optimize the code, and you often end up with larger JavaScript files. So the rule of thumb it to try to be as specific as possible in your typing.
Arguments
By Arguments, here we mean the Type Arguments. Suppose if we have a case where we use collections, we can’t be very specific, in that case the conflict arises. In order to solve this, GWT provides an annotation that allows us to let the compiler know what types of objects are being used in the collection. As this is not a Java 5 annotation, we have to provide an inside Java Comment.
/**
* @gwt.typeArgs <java.lang.String>
*/
private ArrayList listOfWords;
/**
* @gwt.typeArgs <java.util.Date>
*/
private Vector listOfDates;
We can also implement this for return types and parameters.
Exception Handling in GWT
Remote Procedure Calls open up the possibilities of errors and exceptions. Errors may be due to various issues such as Network error, Server related issues, Server-Client call transactions etc. GWT allows us to handle exceptions easily and efficiently. Any RPC related exception can be categorized into two types.
Checked Exceptions
Unexpected Exceptions
Common or Checked Exceptions
When a Service interface method is implemented there are many possibilities of exceptions being thrown and in order to handle that throw, declarations are added. The throw indicates that an exception may be thrown back during the implementation. AsyncCallback.onFailure(Throwable)is the primary interface a caller must implement to receive a response from a remote procedure call. If an RPC is successful, then onSuccess(Object) is called, otherwise onFailure(Throwable) is called. The asynchronous method always takes an AsyncCallback as its last parameter.
e.g.: Animal[] getAnimals(String databaseName) throws AnimalException, DbException;
Its asynchronous counterpart method is declared as:
void getAnimals(String databaseName, AsyncCallback callback);
Note that the throws declaration is not repeated in the Async version.
A typical AsyncCallback call might look like this:
service.getAnimals(dbName, new AsyncCallback() {
public void onSuccess(Object result) {
// Downcasting to the known return type.
Animal[] animals = (Animal[]) result;
controller.processAnimals(animals);
}
public void onFailure(Throwable caught) {
try {
throw caught;
} catch (InvocationException e) {
// Call terminated in a adhoc way
} catch (AnimalException e) {
// one of the ‘throws’ from the original method
} catch (DbException e) {
// one of the ‘throws’ from the original method
} catch (Throwable e) {
// last resort — a very unexpected exception
}
}
});
Ad-hoc Exceptions
If an Exception occurs ‘ad-hoc’ then it is termed an Unchecked Exception. There are many reasons why such exceptions might occur, they will be mainly due to machine and server related issues. Network breakdown, DNS error, HTTP process error etc.
An InvocationException is passed to the implementation of AsyncCallback.onFailure (Throwable). This class is called InvocationException because the problem was with the invocation attempt itself rather than with the service implementation. A NullPointerException might also lead to this, since that is ad-hoc.
There are two types of InvocationException:
| InvocationException(String) | Constructs an exception with the given description. |
| InvocationException(String, Throwable) | Constructs an exception with the given description and cause. |
GWT also allows us to implement almost all types of exceptions that are in Java.
Asynchronous Calls
An asynchronous call comes into play when we need parallelism in our applications.
For example if we have a page which contains a huge table containing many widgets and we need to fetch data from the Server for the table and at the same time as we need to construct all the widgets that are required building the table itself is time consuming and fetching the data adds to the load. If we implement Asynchronous calls by the time the table is constructed with widgets, the data can be fetched from the Server Asynchronously, this will reduce the load time and at the same time double the efficiency.
In case of Asynchronous calls, a common problem is blocking, but this can be managed with the concept of Inner classes.
RPC Example:
1. Create a new Eclipse GWT project named MyFirstRPC using the projectCreator and applicationCreator. Set the name of the application class to com.test.MyFirstRPC.client.MyFirstRPC.
2. If you are comfortable you can build the Project as it is or you can use any standard IDE like Eclipse.
3. Create a Java file and name it as NumsService.java in the com.test.MyFirstRPC.client package.
Define a NumsService interface with one method that verifies if a number is an even. It takes an integer as a parameter and returns a Boolean value upon verification:
public interface NumsService extends RemoteService
{
public boolean isEven(int numberToVerify);
}
4.Create a new Java file named NumsServiceAsync.java in the com.test.MyFirstRPC.client package. Define a NumsServiceAsync interface:
public interface NumsServiceAsync
{
public void isEven(inr numberToVerify, AsyncCallbackcallback);
}
5.Create a new Java file, named NumsServiceImpl.java in the com.test.MyFirstRPC.
server package. Define a NumsServiceImpl class that extends RemoteServiceServlet and implements the previously created NumsService interface. Add functionality to this class to verify if the provided number is an even number.
public class NumsServiceImpl extends RemoteServiceServlet
implements NumsService
{
private static final long serialVersionUID = -8620968747002510678L;
public boolean isEven(int numberToVerify)
{
boolean numIs = false;
if ( (numberToVerify%2)==0)
{
numIs = true;
break;
}
return numIs;
}
}
//break//
6. Create the client in a new file named NumsClient.java in the com.test.MyFirstRPC.client package that extends the EntryPoint class.
public class NumsClient implements EntryPoint
{
}
7. Add an onModuleLoad() method to this new class, and create a text box.
public void onModuleLoad()
{
final TextBox IsEvenTxt = new TextBox();
}
8. Instantiate the NumsService and store it in a variable in the onModuleLoad()method.
final NumsServiceAsync NumsService = (NumsServiceAsync) GWT
GWT.create(NumsService.class);
ServiceDefTarget endpoint = (ServiceDefTarget) NumsService;
endpoint.setServiceEntryPoint(GWT.getModuleBaseURL()+”Nums”);
9. Create a new button, and add an event handler to listen for clicks on the button. In the handler, invoke the NumsService using the text typed into the text box as the input parameter to the service. Display the result in an alert dialog.
final Button checkNum=new Button(“Is this an Even number?”,
new ClickListener())
{
public void onClick(Widget sender)
{
AsyncCallback callback = new AsyncCallback()
{
public void onSuccess(Object result)
{
if(((Boolean) result).booleanValue())
{
Window.alert(“Yes, “+ IsEvenTxt.getText()
+ “‘ is a Even number.”);
}
else
{
Window.alert(“No, “+ IsEvenTxt.getText()
+ “‘ is not a Even number.”);
}
}
public void onFailure(Throwable caught)
{
Window.alert(“Error while calling the Nums
Service.”);
}
};
NumsService.isIsEvenTxt(Integer
parseInt(IsEvenTxt.getText()), callback);
}
});
10. Add the following entry to the application’s module.xml file in order for the client to find this service.
<servlet path=”/Nums” class=
“com.test.MyFirstRPC.server.NumsServiceImpl”/>
When you execute the app, you will get the result like this
Conclusion:
Google Web Toolkit has made RPC really simple and at the same time with the implementation of Asynchronous Calls the transactions occurs parallely and dynamically giving the User a complete AJAX experience and the developer a easy life to architect the application.

15. May, 2006 







Comments are closed.