December 20, 2014
Hot Topics:

Get RESTful with Spring 3.0

  • December 23, 2009
  • By Michael Pilone
  • Send Email »
  • More Articles »

The JSON Endpoint

While simpler than the full SOAP web service implementation, the simple XML endpoint still forces clients to produce and consume XML messages, which aren't always easy to processes in some web 2.0 languages like JavaScript. To make things even easier, you can introduce another endpoint that uses the REST-like HTTP POST pattern introduced with the simple XML endpoint, but have the endpoint consume and produce the JSON, making it very Ajax friendly. Keeping with the design goals for these new APIs, the JSON endpoint should use the same domain objects described in the web service XML schema, which requires the use of the Jackson JSON Processor (see Sidebar 2. What's the Jackson JSON Processor?).

The flexible Spring MVC design allows you to reuse the exact same WeatherRestEndpoint that you implemented to support the simple XML endpoint. If you think about the process described with the XML endpoint, you can see that the only part of the message flow that needs to change is the marshalling of JSON into the XML schema-defined domain objects and the marshalling of the response objects back into JSON. Therefore, you can reuse the implementation of the endpoint and configure it as another controller accessed by the DispatcherServlet defined in the web.xml servlet definition (see Listing 10).

Again, the Spring bean configuration file needs to link the request unmarshaller, the controller, and the view. The addition of JSON support comes mostly from the configuration of the new Spring 3.0 MappingJacksonHttpMessageConverter, as it is added to the AnnotationMethodHandlerAdapter to perform the Jackson unmarshalling of HTTP requests, as well as the MappingJacksonView to marshal the HTTP responses:

<!--
    Maps incoming requests to the appropriate controller based on the annotations on
    the controller methods.
  -->
  <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
  <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
      <list>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
          <property name="objectMapper" ref="jacksonObjectMapper"/>
        </bean>
      </list>
    </property>
  </bean>
  
  <!-- The Jackson view that uses the Jackson object mapper for serialization. -->
  <bean id="restJsonMarshalView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
    <property name="objectMapper" ref="jacksonObjectMapper"/>
    <property name="renderedAttributes">
      <list>
        <value>response</value>
      </list>
    </property>
  </bean>

You can see how similar the definition of the Jackson converter and view is to the XML converter and view, which brings a simple consistency to the implementation and deployment. However, unlike the XML endpoint, Spring's OXM functionality is replaced with Jackson's ObjectMapper and the built-in JaxBAnnotationIntrospector:

<!-- Jackson ObjectMapper that can serialize and deserialize to and from JSON.
     The ObjectMapper is similar to JAXB marshallers. -->
<bean class="org.mpilone.spring.web.rest.MapUnwrappingObjectMapper" id="jacksonObjectMapper"/>

Jackson uses the JAXB introspector, configured as part of the custom object mapper to be discussed later, to identify fields of JAXB-generated objects to be marshaled and unmarshalled, allowing Jackson to bridge from JSON- to JAXB-annotated Java objects. Listing 11 contains the full Spring configuration file for the Jackson endpoint.

You must handle two special cases explicitly with the Jackson endpoints:

  1. The MappingJacksonView allows you to specify which properties in Spring's model map to serialize (in this case, only the "response" object). However, Jackson serializes the map itself, which can introduce an undesirable top-level map object in the response. To avoid this, a custom implementation of the Jackson ObjectMapper was implemented to "unwrap" single item model maps and to configure the JAXB annotation introspector (see Listing 12).
  2. Jackson currently does not support serializing an empty object (i.e., an object with no properties) through the default BeanSerializer. Therefore, if your current XML response objects are empty (as is commonly the case with a "void" SOAP operation), you must implement a custom serializer to simply generate an empty JSON object (e.g., "{ }"). The Jackson developers have indicated that this feature may be supported natively in the future.

To test the new functionally, deploy the application and post an XML message to the configured endpoint using a testing tool such as SoapUI or through a test case using the new Spring 3.0 RestTemplate:

RestTemplate restOps = new RestTemplate();
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
List<MediaType> mediaTypes = new ArrayList<MediaType>();
mediaTypes.add(MediaType.parseMediaType("application/json"));
stringConverter.setSupportedMediaTypes(mediaTypes);
restOps
	.setMessageConverters(new HttpMessageConverter[] { stringConverter });

String jsonRequest = "{ \"temperature\": 38, \"targetScale\": \"celcius\" }";
String jsonResponse = restOps.postForObject(
	"http://localhost:8080/weather/json/convertTemperature", jsonRequest,
	String.class);
System.out.println(jsonResponse);

HTTP Client Example

The full source code for this article includes a simple HTTP and JavaScript example. The example simply uses the XmlHttpRequest object that is built into the browser to allow you to post a message payload to any of the endpoints implemented here. You can use the JavaScript as a launching pad to integrate real Ajax support into your web applications using the new REST-like APIs you just added. You also can deploy the services and client demos directly in the Tomcat container as a web application archive (WAR).

Quick REST Services Implementations

Spring 3.0 brings many new simple yet powerful features to the Spring MVC framework. These features allow for the quick implementation of REST services. In this article, you saw how to leverage your existing service API (defined with XML schema and WSDL) to expose a SOAP-based web service as a REST-like service. The REST-like service supports both XML and JSON, making it more flexible and easier for clients to use, while maintaining consistency across all three APIs. You also can use Spring's ContentNegotiatingViewResolver to select the appropriate response format based on the HTTP Accept header, which would allow a single endpoint to serve multiple formats—beyond just XML and JSON—to meet clients' needs.

Only time will tell which service approach wins out, but you can rest assured that with the proper tools, your application will be agile enough to meet the demands of client developers. At the same time, it will successfully reduce time and costs by reusing existing API definitions and infrastructure, as well as leveraging common backend business logic.

The Spring Framework suite, as well as great third-party libraries such as JAXB and Jackson, make Java all the more powerful in a fast moving Web 2.0 world.

Code Download

  • Spring-WS-Rest_src
  • For Further Reading

  • Apache CXF
  • Apache Axis2
  • Spring Web Services
  • Jackson JSON Processor
  • JAXB
  • Spring Framework
  • SoapUI
  • About the Author

    Michael Pilone is a senior software engineer for Vangent, Inc., where he is currently working on Java based web service technologies and large scale geographical data indexing and searching. Michael holds a master's degree in Information Technology Project Management.



    Page 3 of 3



    Comment and Contribute

     


    (Maximum characters: 1200). You have characters left.

     

     


    Enterprise Development Update

    Don't miss an article. Subscribe to our newsletter below.

    Sitemap | Contact Us

    Rocket Fuel