An easy-to-use RPC mechanism for passing Java objects to and from a server over standard HTTP.
When used properly, RPCs give you the opportunity to move all of your UI logic to the client, resulting in greatly improved performance, reduced bandwidth, reduced web server load, and a pleasantly fluid user experience.
The server-side code that gets invoked from the client is often referred to as a service, so the act of making a remote procedure call is sometimes referred to as invoking a service. To be clear, though, the term service in this context isn't the same as the more general "web service" concept. In particular, GWT services are not related to the Simple Object Access Protocol (SOAP).

public interface MyService extends RemoteService {
public String myMethod(String s);
}
This synchronous interface is the definitive version of your service's
specification. Any implementation of this service on the
server-side must extend
RemoteServiceServlet and 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;
}
}
interface MyServiceAsync {
public void myMethod(String s, AsyncCallback callback);
}
The nature of asynchronous method calls requires the caller to pass in a callback object that can be notified when an asynchronous call completes, since by definition the caller cannot be blocked until the call completes. For the same reason, asynchronous methods do not have return types; they must always return void. After an asynchronous call is made, all communication back to the caller is via the passed-in callback object.
The relationship between a service interface and its asynchronous counterpart is straightforward:com.example.cal.client.SpellingService, then the
asynchronous interface must be called
com.example.cal.client.SpellingServiceAsync. The
asynchronous interface must be in the same package and have the same
name, but with the suffix Async.public ReturnType methodName(ParamType1 param1, ParamType2 param2);an asynchronous sibling method should be defined that looks like this:
public void methodName(ParamType1 param1, ParamType2 param2,
AsyncCallback callback);
A service implementation must extend RemoteServiceServlet and must implement the associated service interface. Note that the service implementation does not implement the asynchronous version of the service interface.
Every service implementation is ultimately a servlet, but rather than
extending HttpServlet,
it extends RemoteServiceServlet instead.
RemoteServiceServlet automatically handles serialization
and invoking the intended method in your service implementation.
<servlet> tag within your
module XML. The
GWT development shell includes an embedded version of Tomcat which acts
as a development-time servlet container for testing.
web.xml configuration. See
ServiceDefTarget for more
information.GWT.create().public interface MyEmailService extends RemoteService {
void emptyMyInbox(String username, String password);
}
Its corresponding asynchronous interface will look like this:
public interface MyEmailServiceAsync {
void emptyMyInbox(String username, String password,
AsyncCallback callback);
}
The client-side call will look like this:
public void menuCommandEmptyInbox() {
// (1) Create the client proxy. Note that although you are creating the
// service interface proper, you cast the result to the asynchronous
// version of
// the interface. The cast is always safe because the generated proxy
// implements the asynchronous interface automatically.
//
MyEmailServiceAsync emailService = (MyEmailServiceAsync) GWT.create(MyEmailService.class);
// (2) Specify the URL at which our service implementation is running.
// Note that the target URL must reside on the same domain and port from
// which the host page was served.
//
ServiceDefTarget endpoint = (ServiceDefTarget) emailService;
String moduleRelativeURL = GWT.getModuleBaseURL() + "email";
endpoint.setServiceEntryPoint(moduleRelativeURL);
// (3) Create an asynchronous callback to handle the result.
//
AsyncCallback callback = new AsyncCallback() {
public void onSuccess(Object result) {
// do some UI stuff to show success
}
public void onFailure(Throwable caught) {
// do some UI stuff to show failure
}
};
// (4) Make the call. Control flow will continue immediately and later
// 'callback' will be invoked when the RPC completes.
//
emailService.emptyMyInbox(fUsername, fPassword, callback);
}
It is safe to cache the instantiated service proxy to avoid creating it
for subsequent calls.A type is serializable and can be used in a service interface if it
char, byte,
short, int, long,
boolean, float, or double;String, Date, or a primitive
wrapper such as Character, Byte,
Short, Integer, Long,
Boolean, Float, or Double;final, non-transient
instance fields are themselves serializable, andpublic default (zero argument) constructortransient keyword is honored, so values in transient
fields are not exchanged during RPCs. Fields that are declared
final are also not exchanged during RPCs, so they should
generally be marked transient as well.
java.util.Set and
java.util.List are tricky because they operate in terms of
Object instances. To make collections serializable, you
should specify the particular type of objects they are expected to
contain. This requires you to use the special Javadoc annotation
@gwt.typeArgs. Defining an item type for a
collection means that you will ensure that the collection only ever
contains objects of that item type or a subclass thereof. This hint is
necessary so that the GWT proxy generator can create efficient code.
Adding an object to a collection that violates its asserted item type
will lead to undefined behavior.
To annotate fields of collection type in a serializable user-defined class:
public class MyClass implements IsSerializable {
/**
* This field is a Set that must always contain Strings.
*
* @gwt.typeArgs <java.lang.String>
*/
public Set setOfStrings;
/**
* This field is a Map that must always contain Strings as its keys and
* values.
*
* @gwt.typeArgs <java.lang.String,java.lang.String>
*/
public Map mapOfStringToString;
/**
* Default Constructor. The Default Constructor's explicit declaration
* is required for a serializable class.
*/
public MyClass() {
}
}
Note that there is no need to specify the name of the field in the
@gwt.typeArgs declaration since it can be inferred.
Similarly, to annotate parameters and return types:
public interface MyService extends RemoteService {
/**
* The first annotation indicates that the parameter named 'c' is a List
* that will only contain Integer objects. The second annotation
* indicates that the returned List will only contain String objects
* (notice there is no need for a name, since it is a return value).
*
* @gwt.typeArgs c <java.lang.Integer>
* @gwt.typeArgs <java.lang.String>
*/
List reverseListAndConvertToStrings(List c);
}
Note that parameter annotations must include the name of the parameter
they are annotating in addition to the collection item type, while return
type annotations do not.
throws declarations to indicate which
exceptions may be thrown back to the client from a service
implementation. Callers should implement
AsyncCallback.onFailure(Throwable) to check for any exceptions
specified in the service interface.
InvocationException because the
problem was with the invocation attempt itself rather than with the
service implementation itself.
An RPC can also fail with an invocation exception if the call does reach
the server, but an undeclared exception occurs during normal processing
of the call. There are many reasons such a situation could arise: a
necessary server resource, such as a database, might be unavailable, a
NullPointerException could be thrown due to a bug in the
service implementation, and so on. In these cases, a
InvocationException is thrown in
application code.
Another type of failure can be caused by an incompatibility between the client and the server. This most commonly occurs when a change to a service implementation is deployed to a server but out-of-date clients are still active. For more details please see IncompatibleRemoteServiceException.
When the client code receives an IncompatibleRemoteServiceException, it should ultimately attempt to refresh the browser in order to pick up the latest client.
For example, suppose your application displays a large table containing many widgets. Constructing and laying out all those widgets can be time consuming. At the same time, you need to fetch data from the server to display inside the table. This is a perfect reason to use asynchronous calls. Initiate an asynchronous call to request the data immediately before you begin constructing your table and its widgets. While the server is fetching the required data, the browser is executing your user interface code. When the client finally receives the data from the server, the table has been constructed and laid out, and the data is ready to be displayed.
To give you an idea of how effective this technique can be, suppose that building the table takes 1 second and fetching the data takes 1 second. If you make the server call synchronously, the whole process will require at least 2 seconds. But if you fetch the data asynchronously, the whole process still takes just 1 second, even though you are doing 2 seconds' worth of work.
The hardest thing to get used to about asynchronous calls is that the calls are non-blocking. However, Java inner classes go a long way toward making this manageable.
Architecturally, you can make use of RPC two alternative ways. The difference is a matter of taste and of the architectural needs of your application.
The first and most straightforward way to think of service definitions is to treat them as your application's entire back end. From this perspective, client-side code is your "front end" and all service code that runs on the server is "back end." If you take this approach, your service implementations would tend to be more general-purpose APIs that are not tightly coupled to one specific application. Your service definitions would likely directly access databases through JDBC or Hibernate or even files in the server's file system. For many applications, this view is appropriate, and it can be very efficient because it reduces the number of tiers.
In more complex, multi-tiered architectures, your GWT service definitions could simply be lightweight gateways that call through to back-end server environments such as J2EE servers. From this perspective, your services can be viewed of as the "server half" of your application's user interface. Instead of being general-purpose, services are created for the specific needs of your user interface. Your services become the "front end" to the "back end" classes that are written by stitching together calls to a more general-purpose back-end layer of services, implemented, for example, as a cluster of J2EE servers. This kind of architecture is appropriate if you require your back-end services to run on a physically separate computer from your HTTP server.