The following example shows a simple GWT RPC greeting service, which is generated automatically when you create a GWT project.
We create an interface that implements RemoteService
and define our remote methods in it. We annotate the service with the @RemoteServiceRelativePath
annotation, which specifies the path to the service implementation servlet on the server.
import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; @RemoteServiceRelativePath("greet") public interface GreetingService extends RemoteService { String greetServer(String name) throws IllegalArgumentException; }
We define the asynchronous version of our interface, by adding our remote methods with the same parameters as they were defined in the service interface, but without a return value. Instead, we add another parameter which is the AsyncCallback
class parameterized by our object return type.
In this example, we return String
from the greetServer()
method so we pass AsyncCallback<String>
as the callback class.
import com.google.gwt.user.client.rpc.AsyncCallback; public interface GreetingServiceAsync { void greetServer(String input, AsyncCallback<String> callback) throws IllegalArgumentException; }
Now, we create implementation of our service interface. This is the actual service that will be invoked on the server side. Our service implementation needs to extend the RemoteServiceServlet
and implement our service method.
import com.bitrunk.gwtrpc.client.GreetingService; import com.google.gwt.user.server.rpc.RemoteServiceServlet; public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService { public String greetServer(String input) throws IllegalArgumentException { return "Hello, " + input; } }
Our service implementation is actually a servlet. It needs to be defined in the web application deployment descriptor web.xml
. Note that the URL mapping of the servlet is composed of <web application root>/<service-path>
. The <service-path>
is the same URL path defined in our service interface using the @RemoteServiceRelativePath
annotation.
// web.xml <web-app> <!-- Servlets --> <servlet> <servlet-name>greetServlet</servlet-name> <servlet-class>com.bitrunk.gwtrpc.server.GreetingServiceImpl</servlet-class> </servlet> <servlet-mapping> <servlet-name>greetServlet</servlet-name> <url-pattern>/gwtrpc/greet</url-pattern> </servlet-mapping> <!-- Default page to serve --> <welcome-file-list> <welcome-file>GwtRPC.html</welcome-file> </welcome-file-list> </web-app>
To invoke our RPC service on the client side, we create an instance of our GreetingServiceAsync
interface using a call to GWT.create()
, passing the service
interface. We can now call the asynchronous
method and pass it to our callback
class.
The callback
class contains the onFailure
method, which is called in case of an exception and the onSuccess
method which is called if the remote call succeeds.
private GreetingServiceAsync greetingService = GWT.create(GreetingService.class); ... greetingService.greetServer(textToServer, new AsyncCallback<String>() { public void onFailure(Throwable caught) { // Show the RPC error message to the user // if the called service method throws an exception // defined in a throws clause then handle it here. } public void onSuccess(String result) { // Show success message to the user or update some UI } });
The GWT RPC service knows the URL of the service by the value of the RemoteServiceRelativePath
annotation defined in the service interface. That value is appended to a URL which includes the GWT module name. In case we want to invoke a service that belongs to a different GWT module, we will need to explicitly specify the service URL. This can be done using the ServiceDefTarget
interface:
ServiceDefTarget endPoint = (ServiceDefTarget) greetService; endPoint.setServiceEntryPoint(GWT.getHostPageBaseURL() + "/gxtcookbk/greet");