Integrating JBoss RESTEasy and Spring MVC
Jetty
Running Jetty is rather simple. You've seen most of the details of the pom.xml when we previously discussed it. Running jetty through maven involves running the following command:
mvn jetty:run(If you haven't done so already, download the file as a tar ball, and change the pom.xml's version of the two RESTEasy dependencies to 1.2.RC1)
That command will launch Jetty, and allow you to browse our project at http://localhost:8080/contacts. Add a few contacts, and view them either as a group at /contacts in HTML, as a group in XML at /contact/data, or individually as XML by following the links found at /contacts.
Congratulations. You now have a running Spring MVC/RESTEasy application. We need one more thing to consider this application complete: a JUnit test.ContractTest.java
RESTEasy provides a mechanism for easily launching a Spring MVC/RESTEasy application. RESTEasy also comes with a robust REST client framework. This article will cover bits and pieces of the test, but you can view the entire code in the RESTEasy SVN.
To start, we're going to set up an interface that the RESTEasy client can use to create a client for our application. It consists of abstract methods annotated with JAX-RS annotations:
@Path(ContactsResource.CONTACTS_URL)
public interface ContactProxy {
@Path("data") @POST @Consumes(MediaType.APPLICATION_XML)
Response createContact(Contact contact);
@GET @Produces(MediaType.APPLICATION_XML)
Contact getContact(@ClientURI String uri);
@GET
String getString(@ClientURI String uri);
}
All methods on ContactProxy inherit the ContactsResource.CONTACTS_URL path ("/contacts") as the root URL, just like a server-side JAX-RS resource. This interface's has three methods:
- Create a contact - the createContact method maps to a POST to "/contacts/data". The method accepts a Contact object which will be converted to XML before it's sent to the server. The result is a JAX-RS Response object which contains the response status and headers. One of those headers includes the LOCATION of the new contact
- Get an XML Contact - Given a URL to a Contact, such as the URL returned by the createContact method's response's LOCATION header, GET an XML response and create a Contact object from it.
- Get a Response as a String - Given a URL, such as a Contact URL or anything else on the server, retrieve a String result.
This interface will be used by RESTEasy to construct a concrete instance that uses the JAX-RS annotations to perform the actual HTTP calls. Next, let's create the embedded server and use RESTEasy to create that instance of a ContactProxy:
private static ContactProxy proxy;
private static TJWSEmbeddedSpringMVCServer server;
public static final String host = "http://localhost:8080/";
@BeforeClass
public static void setup() {
server = new TJWSEmbeddedSpringMVCServer("classpath:springmvc-servlet.xml", 8080);
server.start();
RegisterBuiltin.register(ResteasyProviderFactory.getInstance());
proxy = ProxyFactory.create(ContactProxy.class, host);
}
@AfterClass
public static void end() {
server.stop();
}
JUnit invokes methods annotated by @BeforeClass before any test methods run. Methods annotated by @AfterClass are triggered by JUnit before after all test methods are complete. In our case, the setup method will instantiate a server that contains a SpringMVC Servlet on port 8080 that is configured by the same Spring XML configuration file we used in Jetty. It also invokes the two lines of code required to create a RESTEasy client. RegisterBuiltin sets up the RESTEasy run time, and must be run one time per client. ProxyFactory.create tells RESTEasy to read the annotations on the ContactProxy interface and to create a Java Proxy instance that knows how to perform the HTTP requests we'll need for our test:
@Test
public void testData() {
Response response = proxy.createContact(new Contact("Solomon", "Duskis"));
String duskisUri = (String) response.getMetadata().getFirst(HttpHeaderNames.LOCATION);
Assert.assertTrue(duskisUri.endsWith(ContactsResource.CONTACTS_URL + "/data/Duskis"));
Assert.assertEquals("Solomon", proxy.getContact(duskisUri).getFirstName());
...
}
This test creates a new Contact, checks the server's response to make sure that the URL is consistent with the test's expectations. It then re-retrieves the Contact and confirms that the firstName is indeed what was sent sent in. While this is a pretty trivial looking test, it performs quite a bit of HTTP activity and business logic.
Conclusion
This article discussed quite a bit of philosophy and design considerations in building a RESTful web application with RESTEasy and Spring MVC. We also built an end to end application with RESTEasy, Spring MVC, Maven, Jetty and JUnit. Even though the content in this article was significant, the code presented here is relatively short compared to other Java alternatives. We touched on subjects like designing REST Applications, creating Spring applications, the RESTEasy client infrastructure and testing RESTful applications. Each of those subjects merit their own articles. There were also other subjects that we simply couldn't fit into this article (as long as it is), including JavaScript to the toolkit to allow closer integration between the browser and your RESTful application, integrating with Flex and more. The code presented in this article can serve as a spring board (again, no pun intended) for all of those ideas.
About the Authors
Solomon Duskis
Solomon Duskis is a Senior Manager at SunGard Consulting Services. He's been developing for 22 years -- 12 years in professional capacity. He has experience in various industries such as Finance, Media, Insurance and Health. He contributes to Open Source projects such as JBoss Resteasy and the Spring framework. He is a published author of Spring Persistence - A Running Start, and the upcoming book Spring Persistence with Hibernate.
Richard Burton
Richard Burton is the co-founder of a small independent consulting firm called SmartCode LLC. He is an Open Source fanatic with over 10 years of experience in various industries such as Automotive, Insurance, Finance and fondly remembers the .com era. In his spare time, he contributes to Open Source projects such as SiteMesh 3, Struts 2, and more.
Reference
REST
- Roy Fielding's REST Thesis - Architectural Styles and the Design of Network-based Software Architectures(December 2000)
- Bill Burke's Introduction to REST (August 2008 - DZone)
- How to GET a cup of coffee (October 2008 - InfoQ)
- Roy Fielding REST APIs Must Be Hypertext Driven (October 2008 - Untagled Roy's blog - take a look at the URI: roy.gbiv.com )
JAX-RS
- Bill Burke's Putting Java to REST (September 2008 - DZone)
- An overview of JAX-RS 1.0 Features
- James Strachan's JAX-RS as the one Java web framework to rule them all? (January 2009 - James' blog)
RESTEasy
Spring
- Spring 2.5 reference
- Oh, just search google for "spring framework"
Spring MVC
- « first
- ‹ previous
- 1
- 2
- 3
- 4
(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
Seb Cha replied on Wed, 2009/11/04 - 12:16pm
Tony Childs replied on Sat, 2010/05/01 - 9:58am
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
<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
Pasta Farian replied on Wed, 2010/09/22 - 2:44pm
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