Last week I introduced the gwtrpc-spring project with an example application. Even though it was simple enough I wanted to reduce the configuration to a bare minimum. So this is example app number 2. By using auto configuration of annotated beans in spring and a naming convention for our services we can reduce the setup for a new rpc service.
To begin with when creating a new service we want to append an extension to our RemoteServiceRelativePath. So now instead of “greet” we want “greet.rpc”.
Here is our new GreetingService interface:
package org.gwtrpcspring.example.client;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
/**
* The client side stub for the RPC service.
*/
@RemoteServiceRelativePath("greet.rpc")
public interface GreetingService extends RemoteService {
String greetServer(String name);
}
Now we can change the servlet mapping in our web.xml to redirect all requests ending in .rpc to our dispatcher servlet. This means when we add a new service we don’t have to add a new mapping.
Here is our new web.xml:
<web-app>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>GwtRpcSpringExample.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.gwtrpcspring.RemoteServiceDispatcher
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.rpc</url-pattern>
</servlet-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
We need to add annotation scanning to our spring application context. This involves adding the context: name space and adding a component-scan configuration. Here we tell spring to look in the org.gwtrpcspring.example.server package for classes that have a spring annotation. The annotation is one of the types that extend @Component, we used @Service. What this does is tell spring to automatically wire up and instantiate any classes with the annotation. In a production application I would use a package where I want all of the services i.e. org.gwtrpcspring.example.server.services so that I can be more choosy about which classes get automatically instantiated.
Here is our new applicationContext.xml notice how we no longer have to define our service bean:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemalocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config>
<!-- Auto Config annotated classes in these directories -->
<context:component-scan base-package="org.gwtrpcspring.example.server">
</context:component-scan>
</context:annotation-config></beans>
Finally, we add the annotation to the service implementation:
package org.gwtrpcspring.example.server;
import org.gwtrpcspring.RemoteServiceUtil;
import org.gwtrpcspring.example.client.GreetingService;
import org.springframework.stereotype.Service;
/**
* The server side implementation of the RPC service.
*/
@Service
public class GreetingServiceImpl implements GreetingService {
public String greetServer(String input) {
String serverInfo = RemoteServiceUtil
.getThreadLocalContext().getServerInfo();
String userAgent = RemoteServiceUtil
.getThreadLocalRequest().getHeader(
"User-Agent");
return "Hello, "
+ input
+ "!<br><br>I am running "
+ serverInfo
+ ".<br><br>It looks like you are using:<br>"
+ userAgent;
}
}
That’s all there is to it. Annotation driven configuration is not for everyone, some like to have all the wiring explicitly defined. But if you want simplicity then this is the simplest Spring/GWT configuration can get. You can get the source at: SimpleGwtRpcSpringExample.zip
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=95b54f9a-a547-4d0d-ba9f-f6a4757db7bb)
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=31785fe9-9611-4ea9-b82c-2e0c16e78c88)

![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=dcc04f7a-b416-4a4f-8f6b-7a7359218114)