In the previous post, I’ve presented GWT RPC integration with Spring. In this post we’ll see how we can achieve JSON backend service integration between GWT and Spring MVC. We’ll re-use the same StockWatcher application and change the RPC communication into JSON requests.
I Implementation
The integration of JSON service in the backend with Spring MVC is quite similar to the integration of RPC services with Spring plain service beans. What’s new here is the introduction of Spring MVC to drive the JSON service.
Most of this integration is about smart configuration of the servlet mapping and the Spring MVC pipeline.
A Spring MVC configuration
Let’s see how we configure Spring MVC for this purpose:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" /> <bean id="jacksonMessageConverter" class="java.util.ArrayList"> <constructor-arg> <list> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /> </list> </constructor-arg> </bean> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" > <property name="messageConverters" ref="jacksonMessageConverter"/> </bean> <bean id="stockWatcherController" class="com.google.gwt.sample.stockwatcher_json.controller.StockWatcherController" > <property name="jsonStockDataService" ref="jsonStockDataService"/> <property name="jsonRandomizeService" ref="jsonRandomizeService"/> </bean>
Yes, that’s pretty few! Have you noticed that we did not define any viewResolver? It’s perfectly normal since we’re only using Spring MVC to produce JSON data back, there is no need for a view rendering technology.
Please notice that I prefer full XML declaration over <mvc> namespace because we have greater control with full XML config. With <mvc> namespace lots of things (message converters, exception handlers …) are injected by default (convention over configuration) and we do not need them for our usecase.
B web.xml configuration
The configuration for web.xml is very classical
<!-- Spring classical web application context declaration --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Spring MVC Servlet declaration --> <servlet> <servlet-name>springMVCServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:stockwatcher_json-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- Spring MVC Servlet mapping --> <servlet-mapping> <servlet-name>springMVCServlet</servlet-name> <url-pattern>*.json</url-pattern> </servlet-mapping>
First we declare the Spring applicationContext as usual.
Then we declare the Spring MVC servlet with its associated configuration file (line 16)
Finally we map the MVC servlet to the .json extension (line 24). All request finishing with .json will trigger the Spring MVC servlet. The dispatching to service bean is handled by Spring MVC controller @RequestMapping annotation.
C MVC Request mapping
@RequestMapping(value = "**/jsonStocPrices.json", method = RequestMethod.GET, produces = "application/json") @ResponseBody public List<StockDataDto> getStocks(@RequestParam("q") String rawSymbols) { return this.jsonStockDataService.getStockDataFromSymboles(rawSymbols); } @RequestMapping(value = "**/jsonRandomize.json", method = RequestMethod.GET, produces = "application/json") @ResponseBody public Integer randomize() { return this.jsonRandomizeService.getRandomNumber(); }
The request mapping in the MVC controller is quite straightforward. However you should pay attention to the request URL. Here we must use the **/ wildcard because we declared the servlet mapping as *.json.
Indeed if the absolute URL is /StockWatcherJSON/jsonStockPrices.json and the declared URL in @RequestMapping is just jsonStockPrices.json, it will not match beacause of the leading part (/StockWatcherJSON) of the URL.
II Demo
The demo of the above integration can be found on Github at StockWatcherJSON
All you need to do is to follow the instructions to make the Demo run.