I'm Solomon Duskis, NYC consultant and a Java/J2EE guy. I work at Sungard Consulting Services in NYC. The postings on this site are my own and do not necessarily represent the positions, strategies or opinions of my employer. Solomon is a DZone MVB and is not an employee of DZone and has posted 22 posts at DZone. You can read more from them at their website. View Full User Profile

Integrating JBoss RESTEasy and Spring MVC

10.15.2009
| 101431 views |
  • submit to reddit

Building websites is a tough job. It's even tougher when you also have to support XML and JSON data services. Developers need to provide increasingly sophisticated AJAXy UIs. Marketing groups and other business units are becoming more savvy to the benefits of widgets and web APIs. If you're a Java developer who needs to implement those sexy features, you're likely going to accomplish that work with a dizzying variety of frameworks for web development, data access and business logic.

The Spring Framework has a strong presence based on the premise of seamless (no pun intended) integration of all of those frameworks. The Spring framework integrates with a host of JEE standard technologies, such as EJBs and JSP. Spring MVC is a sub-project of the larger Spring Framework that has its own Controller API and also integrates other web development frameworks such as JSF, Struts and Tiles.

While the Spring Framework also integrates with new JEE technologies as they develop, however, for a variety of reasons the Spring framework has not integrated with the tour de force JAX-RS standard which delivers an API for constructing RESTful services. There are six implementations of the JAX-RS standard, and each provides some level of integration with Spring. Most of those integrations work with the Spring framework proper, but don't take advantage of the benefits of Spring MVC. JBoss RESTEasy integrates with both the Spring Framework proper and also with the Spring MVC sub-project.

In this article, we're going to explore how to use RESTEasy along with Spring MVC application. We'll deep dive into the internals of Spring MVC, we'll discuss JAX-RS and how they related to MVC web development. We'll also touch on quite a few technologies beyond Spring MVC and RESTEasy, including Jetty and maven. We're also going to discuss theoretical concepts relating to REST and Dependency Injection. This article has to cover quite a bit of ground and you'll be gaining quite a few tools you can use to develop complex web applications. If you follow this article, you'll be constructing an end-to-end web application, however, feel free to skim the article to find material that's relevant to you.

REST and JAX-RS

REST has been an increasingly trendy topic over the last three years. We as a development community have been looking at REST as an effective way to perform distributed programming and data-oriented services. In fact, the Java community's REST leaders got together and created a standard spec to standardize some RESTful ideas in JSR 311 - JAX-RS the Java API for XML and RESTful Services. The focus of JAX-RS was to create an API that Java developers could use to perform RESTful data exchanges. However, the Java community quickly saw the similarities between JAX-RS and MVC (Model View Control) infrastructures. James Strachan, a long time Java community member and open source contributor (to things like DOM4J, Groovy - he created the language, and recently the Apache Camel and CXF ESBs) suggested that JAX-RS as the one Java web framework to rule them all?. Jersey, the production ready JAX-RS reference implementation, has a built in JSP rendering mechanism. The RESTEasy community built a similar mechanism in HTMLEasy.

The Jersey and and HTMLEasy approaches work well for simpler websites, but they don't solve some of the more complex needs of an application. If you want more complex functionality, you'll need a more sophisticated web-development platform, such as Spring MVC. A combination of Spring MVC and RESTEasy will have the following benefits compared to the simpler approaches:

  • Session based objects
  • Freedom of choice - chose the right tool for the job
    1. Spring MVC integrates with a whole bunch of MVC frameworks, including Spring MVC, Struts2 and now RESTEasy
    2. Spring MVC integrates with a whole bunch of View frameworks, including JSP, JSF, Tiles and much more
  • Integrated AJAX components - the freedom of choice can make end-to-end AJAX calls a breeze, assuming you chose the appropriate framework
  • More control over URL mapping

This article tackles some more advanced topics. If you want some relevant background, we have a reference section at the end of this article. Before we take a look at code, let's take a more in depth view of Spring MVC.

Spring MVC

Spring MVC is broken down into three pluggable sub-systems:

  1. Handler Mapping - Map a URL to Spring Bean/Controller. Spring allows quite a few methods to perform this mapping. It can be based on the name of a Spring bean, it could be a URL to bean map, it could be based on an external configuration file or it could be based on annotations. Handler Mappings allow you to configure complex mappings without resorting to complex web.xml files.

  2. Handler Adapter - Invoke the Controller. Hander Adapters know what type of spring beans they can call and performs invocations on the types of beans it knows about. There are Handler Adapters for Spring MVC classic, spring @MVC, Struts, Struts2, Servlets, Wicket, Tapestry, DWR and more.

  3. View Mapping - Invoke the View. View Mappers know how to translate a logical view name produced by a Controller into a concrete View implementation. A name like "customers" may translate into any of the following technologies: JSP/JSTL, JSF, Velocity, FreeMarker, Struts Tiles, Tiles2, XSLT, Jasper Reports, XML, JSon, RSS, Atom, PDF, Excel, and more

RESTEasy plugs into Spring MVC in all three sub-systems.

  1. JAX-RS Resources/Controllers are defined by annotations; therefore RESTEasy provides a ResteasyHandlerMapper that knows how to convert a URL to a RESTEasy managed JAX-RS controller method.

  2. Once RESTEasy determines which method to invoke, the ResteasyHandlerMapping performs the invocation. The invocation can either be an object, which invokes the default JAX-RS behavior which transforms the resulting Object to a Represetation such as XML or JSON. Additionally, you return a traditional Spring ModelAndView which can refer to a logical view name and a map of data to be rendered by the View.

  3. The default JAX-RS behavior creates a ResteasyView which uses JAX-RS's configurable MessageBodyReader and MessageBodyWriter transformation framework. RESTEasy can produce XML and JSON using JAXB, but can be configured to use other view technologies such as Jackson, which is a performant and flexible JSON provider, Flex AMF.

This separation of Controller and View concepts allows you to mix and match your Controller and View technologies. RESTEasy Resources can call any Spring managed Views and other Controller technologies can be rendered by a ResteasyView. You can either use RESTEasy as your sole MVC framework, if it fits your needs, or you can augment an existing Controller infrastructure with data services provided by RESTEasy.

Just as importantly, you can leverage all of the other functionality that Spring provides, such as DAO abstraction, transaction management and AOP.

Your First SpringMVC/RESTEasy Application

Before we start reviewing the project, let's review a quick checklist of items we will be reviewing. The project files fall into two categories: configuration and source code. All of the code that will be covered is available in the RESTEasy repository and can be downloaded (as a tar.gz file), or browsed.

Here is a list of files that each category will require.

Configuration Files:

  • web.xml - servlet configuration with Spring MVC artifacts - Spring MVC's DispatcherServlet, and map to /contacts/*
  • springmvc-servlet.xml - a Spring application context configuration with all of the Spring beans this project needs, including RESTEasy setup (one line) and JSP configuration
  • pom.xml - maven 2 dependency configuration, including required repositories, RESTEasy dependencies and embedded Jetty setup

Source Code:

The code we're going to show you can be broken down into four layers:

  • Controller - Controlling the flow between the HTTP request, the Model and the View
    • ContactsResource.java - a RESTful Controller with JAX-RS annotations and some traditional HTML controller methods. It will be annotated with Spring's @Controller and @Autowired annotations as well.
  • Model - the domain model and service objects in our case. In our case, we have 2 domain objects: Contact and Contacts; and 1 Service object: ContractService

  • View - How the domain model is transformed for consumer use. JAX-RS performs automated conversion to XML based on annotations on our domain model. We'll be using JSP for object to HTML conversion.

  • Test - JAX-RS provides quite a bit of functionality, we're writing quite a bit of code, and all of that is wrapped in quite a bit of configuration. This article will focus on testing our code, configuration and deployment in an automated JUnit test.
    • ContractTest.java - a RESTEasy ReSTful Unit test for the ContractsResource functionality, embedded server included

There's a lot of ground to cover, and we'll cover the most interesting pieces of the source first. Our first pass will cover the web.xml and springmvc-servlet.xml configuration files as well as the ContactsResource.java and ContactTest.java source files. Our second pass will cover the remaining topics.

Published at DZone with permission of Solomon Duskis, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

christophe charles replied on Fri, 2009/10/23 - 6:52am

Thanks !

Seb Cha replied on Wed, 2009/11/04 - 12:16pm

Good JAX-RS tutorial !

Tony Childs replied on Sat, 2010/05/01 - 9:58am

Thanks for the great article. There is something I have not been able to figure out, however.

Without Spring integration the RestEasy ConfigurationBootstrap.createDeployment() method adds any RestEasy context params - more specifically "resteasy.media.type.mappings" to map type extensions to MIME types.

Unfortunately, when Spring is integrated, these mappings are not picked up. I have been stepping through the code trying to figure out how I might be able to pass these context params to RestEasy when I noticed you had authored some classes in the Resteasy-Spring integration package, so I thought you might be the best person to ask. What would be the best way to get these mappings to RestEasy?

Thanks, Tony

Tony Childs replied on Sat, 2010/05/01 - 11:02am

After further examination of the startup behavior I managed to figure out a way to get the mappings in there. I copied your springmvc-resteasy.cml file and used it as a template for my own custom file. I then added/changed the folloing lines:

<bean id="jsonType" class="javax.ws.rs.core.MediaType" factory-method="valueOf">
   <constructor-arg value="application/json"/>
</bean>

<bean id="xmlType" class="javax.ws.rs.core.MediaType" factory-method="valueOf">
   <constructor-arg value="application/xml"/>
</bean>

<bean id="resteasy.dispatcher" class="org.jboss.resteasy.core.SynchronousDispatcher"
      depends-on="resteasy.intializer">
   <constructor-arg ref="resteasy.providerFactory"/>
   <property name="mediaTypeMappings">
      <map>
         <entry key="json" value-ref="jsonType"/>
         <entry key="xml" value-ref="xmlType"/>
      </map>
   </property>
</bean>

Suresh Bhaskaran replied on Fri, 2010/08/27 - 7:53pm in response to: christophe charles

Great Article! If any of you run into the following issue: "No mapping found for HTTP request with URI [/main/blog/list] in DispatcherServlet with name 'spring' ERROR org.jboss.resteasy.springmvc.ResteasyHandlerMapping - Resource Not Found: Could not find resource for relative Then all you have to do is modify your spring app context xml file: Add these 2 lines: (I am omitting the cone opening and closing cone brackets, as they do not appear here for some reasons: context:component-scan base-package="com.zyrisinc.googlecheckout.service" bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" property name="order" value="0" bean bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"

Pasta Farian replied on Wed, 2010/09/22 - 2:44pm

Update: I can access it by going to http://localhost:8080/examples-resteasy-springMVC-2.1-SNAPSHOT/contacts but when I try to add a contact, I end up back on http://localhost:8080/contacts which gives me a 404 and apparently no contacts were added. By the way, with Tomcat I needed to add jstl.jar to the runtime. ----- Hi, Great article. Very helpful. I am having trouble running this WAR on Tomcar 6. The WAR deploys without any errors but when I go to http://localhost:8080/contacts I get a HTTP 404. Can anyone deploy this on Tomcat successfully? or do I need to make some changes to the servlet mapping? Thanks.

Clay Press replied on Sun, 2011/10/16 - 11:07pm

Two Years After, this jboss/resteasy/spring/maven tutorial still builds and tests as advertised.  Nice demo.

Will java rest keep pace with the dynamic type competitive alternatives in the POST-sun.com era?  Which decision trumps:  resteasy vs jersey vs spring vs restlet <or> java/c@ vs python/ruby.

Two Years Later, where will java rest be

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.