The DevNexus website is based on Spring MVC 3.0 and provides RESTful Urls that render Html views of the data (Targeting traditional browser clients as well as mobile client using Spring Mobile and jQuery Mobile).
Thus, I configured Restful endpoints as described in my last blog post. The easiest way to marshal JSON in Spring MVC is via the Jackson Java JSON-processor. Spring has a few documentation pointers regarding that. Theoretically, the setup is fairly simple and in its simplest forms means to just put the Jackson jar file onto your class path and adding mvc:annotation-driven to your Spring Xml Context file (See Chapter 15.12.1 of the Spring documentation). No sweat.
To get started more specifically with Jackson, here are some blog entries that I came accross while diving deeper into it:
- http://java.dzone.com/articles/how-serialize-javautildate
- http://rwehner.wordpress.com/2010/06/09/2-ways-to-create-json-response-for-ajax-request-in-spring3/
- http://ondra.zizka.cz/stranky/programovani/java/jaxb-json-jackson-howto.texy
java.lang.StackOverflowError - org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError)
You can configure Jackson's marshalling behavior by annotating your domain model objects. However, those annotations are Jackson specific and I already was annotating my obejects with Jaxb annotations for the Xml marshalling of data.
Well - cool beans - , it turns out, Jackson can indeed use Jaxb annotations to renders Json data (added with version 1.1 of Jackson).
But how do I configure Jackson? How do I make it work in my Spring environment? I came across 2 blogs, that combined, provided the necessary solution.
The first example I found here, which provides a really nice example.
Furthermore, I not only wanted to configure Jackson to use Jaxb annotations, but I also needed to make it work for my Spring environment. For that Kyrill Alyoshin has some good information on his blog (
He also details how to make Jackson work better with Hibernate, which sounds interesting and I may return to his blog entry more specifically for that.).
Basically the best way to integrate Jackson and Spring is to create a custom ObjectMapper class that enables Jaxb support and which can then be injected into Spring's MappingJacksonJsonView.
Here are the things that were needed to get things going for my project -
First, add the following Maven Dependencies (jackson-xc provides the additional Jaxb support):
<!-- Jackson JSON Mapper --> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-core-lgpl</artifactId> <version>1.6.4</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-lgpl</artifactId> <version>1.6.4</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-xc</artifactId> <version>1.6.4</version> </dependency>
The custom ObjectMapper:
import org.codehaus.jackson.map.AnnotationIntrospector; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; public class JaxbJacksonObjectMapper extends ObjectMapper { public JaxbJacksonObjectMapper() { final AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(); super.getDeserializationConfig() .setAnnotationIntrospector(introspector); super.getSerializationConfig() .setAnnotationIntrospector(introspector); } }
The SpringContext configuration that wires everything together:
<bean class="org.springframework.web.servlet.view .ContentNegotiatingViewResolver"> <property name="order" value="1" /> <property name="ignoreAcceptHeader" value="true" /> <property name="mediaTypes"> <map> <entry key="xml" value="application/xml"/> <entry key="json" value="application/json"/> </map> </property> <property name="defaultViews"> <list> <bean class="org.springframework.web.servlet.view .xml.MarshallingView"> <property name="marshaller" ref="jaxbMarshaller"/> </bean> <bean class="org.springframework.web .servlet.view.json.MappingJacksonJsonView"> <property name="objectMapper" ref="jaxbJacksonObjectMapper"/> </bean>
</list> </property> </bean>
5 comments:
Hi Gunnar.
Was it really necessary to create that JaxbJacksonObjectMapper class?
Surely you could have had your Spring configuration instantiate the JaxbAnnotationIntrospector and an ObjectMapper and inject the JaxbAnnotationIntrospector in?
Thanks for your guidance on this post.
Did you ever solve the parent/child relationship (bi-direcitonal relationship) with Jackson mapping using JAXB annotations alone? Since Jackson doesn't support XmlID and XmlIDREF, what else do we do? Mix annotations (JAXB and JSON?)
Thanks Gunnar! This was extremely helpful!
For folks looking to accomplish this entirely through Spring configuration, here's one way of going about it:
You can also create the JaxbAnnotationIntrospector outside of the deserializationConfig and serializationConfig -- it's a matter of stylistic preference.
json is a very interesting language to be used. very good tutorial and can hopefully help me in building json in the application that I created for this lecture. thank you
Somehow Dan's configuration seems to have been lost, so I'll post what I did:
<bean id="jaxbAnnotationIntrospector" class="org.codehaus.jackson.xc.JaxbAnnotationIntrospector" />
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper">
<property name="serializationConfig.annotationIntrospector" ref="jaxbAnnotationIntrospector" />
<property name="deserializationConfig.annotationIntrospector" ref="jaxbAnnotationIntrospector" />
</bean>
Good luck.
Post a Comment