Spring Finance > Part 7: Adding support for JSON and XML views

It has been a while since I have updated the Spring Finance Manager sample application so I thought it’s time to do it now. Since my last article a few of the dependencies have cut new milestone releases. This includes Spring Framework (3.0.0.M4), Spring Security (3.0.0.M2), Spring JS (2.0.8) and the bean validation API and its implementation (Hibernate Validator) have also released updates.

Aside from just updating the dependencies I also added a new feature the Spring Finance Manager application: content negotiation for XML and json. With the release of Spring 3.0.0.M4 you can configure a ContentNegotiatingViewResolver which allows you to expose your data in other formats than just HTML. Most notably, XML support has been moved from the Spring Web Services project to the Spring Framework (OXM package) and json support has been moved from the Spring JS project to Spring Framework (web.servlet package). Aside from json and XML Spring MVC also supports ATOM, RSS, Excel, PDF and JasperReport view rendering. More about these features can be found in the reference documentation. Alef Arendsen has posted a blog showing the integration of an ATOM view into a Spring MVC application.

So in order to configure XML and json view rendering (based on http headers or URL extensions) all you have to do is add some configuration to the Spring MVC application context:

	<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver" p:order="1">
		<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">
						<bean class="org.springframework.oxm.xstream.XStreamMarshaller"  p:autodetectAnnotations="true" />
					</property>
				</bean>
				<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
			</list>
		</property>
	</bean>

You can see I have chosen to use XStream in the marshalling view as it does not require any additional mapping or configuration. There is, however, also support for Castor, JiBX and XmlBeans should you require more control over the object to XML marshalling. The mediaTypes property on the ContentNegotiatingViewResolver allows you define default URL to http message header configurations. In this case a URL ending with .xml is mapped to a content type of application/xml and .json is mapped to application/json.

To try it out fire up the Spring finance manager application (ie mvn tomcat:run), populate it with some data (use the included selenium script if you are lazy) and try out: http://localhost:8080/FinanceManager/person.xml. This will render your person objects as XML:

<list>
   <person>
      <id>2</id>
      <version>0</version>
      <lastName>Burns</lastName>
      <firstName>Montgomery</firstName>
      <email>monty@nuclear.com</email>
      <password>Smithers</password>
      <address>
         <streetName>Powerstation</streetName>
         <streetNumber>1</streetNumber>
         <city>Springfield</city>
         <zipCode>99999</zipCode>
         <state>Ohio</state>
         <country>USA</country>
      </address>
   </person>
[...]
</list>

If you are familiar with XStream you might have noticed that the XML element for the Person domain object is mapped to a much better looking element compared to the standard . This (non-default) mapping can be achieved in several ways. One of them is to make use of the @XStreamAlias(“person”) annotation. Another way is to configure your custom mappings in the XML configuration – your choice.

To render the same view as a json document all you need to do is change you URL: http://localhost:8080/FinanceManager/person.json. This will render a a json document:

{"people":[
   {"address":
      {"state":"Ohio", "country":"USA", "city":"Springfield", "streetName":"Powerstation", "streetNumber":"1", "zipCode":"99999"},
       "id":2,"version":0,"password":"Smithers","email":"monty@nuclear.com","lastName":"Burns","firstName":"Montgomery"}
   ]
}

The json generation is actually handled by the Jackson which means you have unfortunately no support for circular reference (which is fairly common in OO design) resolution so it is up to you to judge how useful the generated json document will be.

In order to support these features a number of new dependencies have been added to the Spring Finance Manager pom file:

  • Spring Framework OXM
  • XStream
  • Jackson core and mapper
  • Share/Bookmark

24 Responses Subscribe to comments


  1. Chris Hardin

    I tried this, couldn’t get it perfected. I had to apply the @ResponseBody annotation to my Controller method to get it to grab the json accessing the user …/.json. It outputs JSON, but output stream gets truncated. I don’t have this problem using a ModelAndView. Any ideas?

    Aug 30, 2009 @ 06:52


  2. Stefan Schmidt

    Chris,

    I am a little unclear what you mean. I have tried it again and did not have any problems accessing the json response without using @ResponseBody. I noticed however, that the pom file is missing an extra repository which is needed to import the OXM library:

    < repository >
    < id >com.springsource.repository.bundles.milestone.alt< /id >
    < name >SpringSource Enterprise Bundle Repository – External Bundle Milestones II< /name >
    < url >http://repository.springsource.com/maven/bundles/milestone< /url >
    < /repository >

    Can you try again by doing the following steps:

    >svn co http://spring-finance-manager.googlecode.com/svn/trunk/ spring-finance-manager
    >cd spring-finance-manager
    >mvn tomcat:run

    HTH,
    Stefan

    Aug 30, 2009 @ 10:39


  3. Arokia Raj

    hi,
    I am using the architecture u have used in this sample project in my new project and
    was looking for json view implementation and have created it.. today i looked ur blog and it is similar what i have done..

    Thanks and really your blog helps a lot to learn spring 3.

    Thanks,
    Arokia

    Sep 03, 2009 @ 16:33


  4. Jon Hill

    If you request XML for this URL

    http://localhost:8080/FinanceManager/person/1.xml?x=2&y=10

    you get the following root

    Very verbose, and not what you really want.

    Returning a Collection doesn’t suffer from this, but you don’t always want a Collection. I’m struggling to find a decent way round this, any thoughts Stefan?

    Jon

    Oct 09, 2009 @ 03:23


  5. Jon Hill

    In the previous post, should have read:

    ‘… you get the following root

    org.springframework.validation.BeanPropertyBindingResult

    Oct 09, 2009 @ 03:25


  6. Xpert

    Stefan,

    RC1 is out. When are you planning to have the next version?

    Also, curious about your cloud implementation. Any idea when you are planning to start with that.

    Thanks

    Oct 16, 2009 @ 17:57


  7. Stefan Schmidt

    @Jon,

    I am currently traveling so I am a little short in time to check the exact details. If you have done some further research it would be great if you share it on the project’s google code site.

    -Stefan

    Oct 17, 2009 @ 12:17


  8. Stefan Schmidt

    @Xpert,

    Yes, I should be updating the dependencies of the sample application but I think it makes sense to wait until Spring 3 GA is out (should be in a couple of weeks).

    As for the cloud sample, I will see what I can do once I am back home, but that is a few weeks out. Also, we are quite busy to make a GA release for Spring Roo so that will be taking a lot of my time.

    -Stefan

    Oct 17, 2009 @ 12:20


  9. CemKoc

    Stefan,

    We are very grateful for your efforts.

    Is there any workaround about appengine? I have seen related issue at jira but unfortunately could not see any workaround.

    I believe that the community of appengine is very suitable for Roo project. The community strictly need such a thing for Jpa,JDO and Low Level.

    Thanks

    Nov 07, 2009 @ 09:40


  10. Stefan Schmidt

    Hi,

    I think you are mixing this up a little here :) . Spring Finance Manager is not a Roo generated application (even though there are a lot of similarities).

    So for Roo there is indeed a Jira ticket which provides some details about how to convert a Roo application to run on GAE. For the Finance Manager series I have not considered to convert it to GAE. Are you interested to do this and get it up on the Google project site? Not sure how much work it would be given that GAE should also support JPA…

    -Stefan

    Nov 08, 2009 @ 17:05


  11. Xpert

    @Stefan,

    Could you please let us know when are they planning to release 3.0 GA? Will there be a Spring Security 3.0 GA also at that time?

    In the mean time, would it be possible to update the spring finance pom file to use RC2?

    Appreciate your help.

    Thanks

    Nov 22, 2009 @ 08:39


  12. Stefan Schmidt

    @Xpert,

    The Spring 3 GA release is planned for the next few weeks, so it should not be too far away. Spring Security is independent of that release and I would think this release will be a little further out given that there is no RC release out yet.

    -Stefan

    Nov 23, 2009 @ 10:25


  13. Xpert

    @Stefan

    Thanks for the update.

    I was trying to convert to RC2 and it is causing some class cast exceptions in webflow area. On some forums, I read that they are trying to re-factor some classes from webflow into Spring core.

    Could you please let us know if we can expect a new webflow along with GA release or do we have to find workaround for that.

    Thanks

    Nov 23, 2009 @ 12:31


  14. Irshad Buchh

    Hi,
    I have enjoyed all the parts of this blog/ application. Do you plan to add JQuery and DisplayTag support to this application.
    Great work.

    –Irshad.

    Dec 13, 2009 @ 19:43


  15. Xpert

    @Stefan

    Spring 3.0 is out.

    Could you please let us know if the following are compatible:

    Spring 3.0 GA
    Spring Security 3.0 RC2
    Spring Webflow 2.0.8 GA

    With Spring RC2, we had issues with webflow.

    Appreciate your help.

    Dec 17, 2009 @ 11:04


  16. Xpert

    Stefan,

    3.0 GA has been out for some time now. Could you please give us an update on your plans, especially cloud implementation.

    Appreciate your time.

    Thanks

    Jan 15, 2010 @ 17:46


  17. flyte

    I have the exact same problem as Jon Hill above – if I return a single person object, then I get a the root being


    and then eventually, nested way down in the element I see my marshalled object.

    If I tuck the object into a list, then I don’t get the above root and simply get my object within a element. Is this due to XStream?

    Jan 24, 2010 @ 03:18


  18. James Heggs

    Hi there,

    I had the same issue and successfully solved it using the modelKey parameter on the MarshallView.

    I have made a post on the Spring forums:

    http://forum.springsource.org/showpost.php?p=283072&postcount=4

    Feb 10, 2010 @ 07:40


  19. lalit

    @Stefan

    Nice tutorial and covers all the various aspect of an end to end application.

    Apr 07, 2010 @ 16:08


  20. Baskar

    Hi Stefan,

    I would like to use rich faces for UI in this spring finance application, since rich faces has a huge collection of rich-looking components. Would you recommend to do that since I hear from people rich faces itself is a mvc framework, so better use either ?

    PS.
    I don’t want to give up using springs in my system.

    Jan 04, 2011 @ 22:55


  21. jeckiz

    You are the number one

    Jan 21, 2011 @ 10:04


  22. Stefan Schmidt

    I don’t have experience with RichFaces. It is a component library for JSF which has nothing to do with MVC.

    Jan 23, 2011 @ 08:09


  23. Raj

    Thanks for the post.
    If i want to post some person object from javascript, how may i do that and what is the endpoint of the service to do that.

    May 12, 2011 @ 07:58


  24. Stefan Schmidt

    @Raj, Spring MVC offers JSON support. Take a look at the Spring Roo code documented here: http://static.springsource.org/spring-roo/reference/html/base-json.html#d4e2321. You can easily send and parse JSON messages from JS,

    May 12, 2011 @ 09:45

Reply