GWTSpringRPC
  http://gwtspringrpc.sf.net
 

Quick Start

 

MyEmailService example

 

Consider the example provided by Google in their Remote Procedure Calls documentation.  The service interface is MyEmailService, and is defined as follows:

 

public interface MyEmailService extends RemoteService

{

 

    void emptyMyInbox( String username, String password );

 

}

 

The corresponding asynchronous service looks like this:

 

public interface MyEmailServiceAsync

{

 

    void emptyMyInbox( String username, String password, AsyncCallback callback );

 

}

 

And the client-side call is similar to the following:

 

    public void menuCommandEmptyInbox()

    {

        MyEmailServiceAsync emailService =

            ( MyEmailServiceAsync ) GWT.create( MyEmailService.class );

       

        ServiceDefTarget endpoint = ( ServiceDefTarget ) emailService;

        String moduleRelativeURL = GWT.getModuleBaseURL() + "email";

        endpoint.setServiceEntryPoint( moduleRelativeURL );

       

        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

            }

        };

       

        emailService.emptyMyInbox( username, password, callback );

    }

 

To implement the server-side service, you would create a class that extends RemoteServiceServlet and implements MyEmailService.  The problem with this approach is that you cannot create the service as a POJO, which means you cannot create your own inheritance structure, and you cannot take advantage of dependency injection using the Spring application context.

 

Step 1:  Create your remote service implementation class

 

GWTSpringRPC allows you to define your remote services as POJO’s created and managed by the Spring application context.  The client-side code remains identical to the example provided by Google.  The server-side code only needs to implement the service interface.  In the below example, the MyEmailService implementation is created and has a reference to the MyEmailSession EJB injected into it:

 

public class MyEmailServiceImpl implements MyEmailService

{

 

    private MyEmailSession myEmailSession;

   

    public void emptyMyInbox( String username, String password )

    {

        myEmailSession.emptyMyInbox( username, password );

    }

   

    public void setMyEmailSession( MyEmailSession myEmailSession )

    {

        this.myEmailSession = myEmailSession;

    }

 

}

 

Note that the remote service implementation class implements your remote service interface, but does not extend RemoteServiceServlet.

 

Step 2:  Add your remote service to your GWT module XML

 

To define your remote service to GWT, you add your servlet definition to your GWT module XML.  However, rather than specifying your remote service implementation class, you use the DelegatingRemoteServiceServlet from GWTSpringRPC:

 

<module>

    . . .

   

    <servlet path="/email"

        class="net.sf.gwtspringrpc.servlet.DelegatingRemoteServiceServlet"/>

   

    . . .

</module>

 

This servlet will accept requests from many remote services and delegate the requests to your POJO remote services.

 

Step 3:  Define your remote service in the Spring bean configuration

 

The final step is to define your bean that the DelegatingRemoteServiceServlet will delegate requests to.  An example bean configuration is as follows:

 

    . . .

   

    <bean id="email" class="com.example.MyEmailServiceImpl">

        <property name="myEmailSession" ref="myEmailSession"/>

    </bean>

   

    . . .

 

Accessing servlet API objects

 

Because your remote service implementations are now detached from the servlet API, you will not be able to access HttpServletRequest and HttpServletRespone from GWT’s ThreadLocal objects or ServletContext and ServletConfig from the servlet API.  In order to access these objects from your remote service POJO, a set of dynamic proxies has been provided that allow you to treat them as singleton objects.

 

For example, if our MyEmailService requires the use of the HttpServletRequest for accessing session attributes, it can be injected using the Spring application context.  First, we need to declare the variable in the MyEmailServiceImpl class and write a setter:

 

public class MyEmailServiceImpl implements MyEmailService

{

 

    private MyEmailSession myEmailSession;

    private HttpServletRequest request;

   

    public void emptyMyInbox( String username, String password )

    {

        request.getSession().setAttribute( "emptied", Boolean.TRUE );

        myEmailSession.emptyMyInbox( username, password );

    }

   

    public void setMyEmailSession( MyEmailSession myEmailSession )

    {

        this.myEmailSession = myEmailSession;

    }

   

    public void setRequest( HttpServletRequest request )

    {

        this.request = request;

    }

 

}

 

Then we need to declare the HttpServletRequest dynamic proxy and inject it into the email bean:

 

    . . .

   

    <bean id="request"

        class="net.sf.gwtspringrpc.http.SingletonHttpServletRequestFactoryBean"/>

   

    <bean id="email" class="com.example.MyEmailServiceImpl">

        <property name="myEmailSession" ref="myEmailSession"/>

        <property name="request" ref="request"/>

    </bean>

   

    . . .

 

There are dynamic proxies available for accessing the following servlet classes:

 

Servlet Class

Dynamic Proxy

javax.servlet.ServletContext

net.sf.gwtspringrpc.http.SingletonServletContextFactoryBean

javax.servlet.ServletConfig

net.sf.gwtspringrpc.http.SingletonServletConfigFactoryBean

javax.servlet.http.HttpServletRequest

net.sf.gwtspringrpc.http.SingletonHttpServletRequestFactoryBean

javax.servlet.http.HttpServletResponse

net.sf.gwtspringrpc.http.SingletonHttpServletResponseFactoryBean

 

How it works

 

When the DelegatingRemoteServiceServlet receives the request to process the remote procedure call, it does the following:

 

  1. Stores the servlet API objects in ThreadLocal objects so that they are accessible by the dynamic proxies.

 

  1. Resolves the bean name using a BeanNameResolver instance.  The default instance will use the servlet path as the bean name; in our above example, the servlet path is “/email”, so the bean name is “email”.  The BeanNameResolver can be overridden to determine the bean name in a different fashion.

 

  1. Retrieves a web application context using a WebApplicationContextRetriever instance, and retrieves the bean from the web application context.  The default WebApplicationContextRetriever instance retrieves a servlet context attribute named “org.springframework.web.context.WebApplicationContext.ROOT”, but can be overridden to retrieve the application context in a different fashion.

 

  1. Decodes the RPC request and invokes the method on the delegated bean.