If you’re reading this then you’re probably aware that the new Spring 3.0 release will have REST support (If you’re not familiar with REST here is a nice intro). In this article I’m going to describe the basic steps required to quickly get a RESTful XML web service going using the latest Spring 3 release candidate (3.0.0.RC3). In future follow-up articles I will describe how to switch between JSON and XML using selectors and how to use the Spring REST Template to read RESTful web services.
Before I get started I’m going to need to make some assumptions about you, the reader. This is not a beginner Spring, MVC, or Java EE tutorial, so in order to keep the length of this article reasonable I need to assume certain knowledge. First, I’m hoping that you are familiar with basic Spring 2.5.3+ IoC fundamentals. It would also be very helpful to understand Spring MVC fundamentals as well. You’ll also need to be familiar with the structure and configuration of a Java EE web project. Finally, if you plan to download and use the example code, it’s necessary to know enough about Maven to be able to build a project.
Getting Spring 3.0.0.RC3
Obviously before you do anything you need to get the Spring 3 binaries. I recommend using Maven to handle the Spring JARs and their dependencies. This article will assume that you are using Maven. However, if you are a Maven holdout then you can download the binaries and put them in your classpath manually if you wish. Since 3.0.0 has not been released yet, the only way to give Maven access to it is via Spring’s bundle repositories. I find that the easiest way to do this is to include therepository
entries in my settings.xml file, but you can also put them in the POM file for your project or even add them to Nexus as proxy repositories if you are in such an environment. The entries should look like this:
With these entries in place Maven should now be able to import Spring 3.0 binaries and certain other useful bundles.
Configuring the POM file
I’m using the following dependencies. If you’re using Maven you can probably get away with not declaring all of them. If you’re not using Maven you may find that there are some that you still need. That’s because Maven does transitive dependency management for you. The thing to note here is that, starting with Spring 3.0, there is no “everything jar”, so you have to figure out what JARs you’ll need for a particular functionality.
The Book Search Service
I’ve tried to keep the example as simple as possible without being too trivial. I chose a book search as it seemed fairly simple. The idea is to use a search service to return a POJO or a list of POJOs of some kind (e.g. Book.java) in response to a query. In this example I’m searching for books or authors. If the class structure doesn’t seem that well thought out, that’s because it’s not; it’s just an example. It also might not meet your definition of “RESTful.” If that’s the case then I apologize in advance for ruining your day.
Book.java
Author.java
Publisher.java
Address.java
You’ll notice that there’s not much interesting about any of these classes save for the annotations. The@XStreamAlias
annotation is used by XStream to tell it what to name the XML element representing a class. The default is to use a fully-qualified class name (e.g.
), which can get verbose and also exposes the underlying class. If you don’t mind about either of those things then you don’t need to worry about using the annotations.
My ultra-simple search interface looks like this:
BookService.java
My implementation is not important, but for simplicity and portability I’ve chosen mock data. You can implement your own to use a database or whatever you like.
The Controller
The controller for this example is just a plain old Spring MVC annotated controller with one difference:@PathVariable
. This annotation binds URL template variables to method parameters. It is described in more detail in an article by Arjen Poutsma of the Spring team.
BookServiceController.java
Once again: nothing out of the ordinary. I’m simply using the @RequestMapping
annotation to bind URL templates to methods and then using an injected BookService to do the work. I’m also returning a model and view. Something to note is that I’m prefixing the name of the model object with the constantBindingResult.MODEL_KEY_PREFIX
. This is necessary because of what seems to be a bug in theMarshallingView.java
class. Then again, maybe it’s undocumented behavior. Either way – including this prefix will save you headaches.
Wiring it up
Now that I’ve got my model classes created and my controller created and annotated, I’ll need to do a little configuration. The first thing I want to configure is the web.xml file. I need to add a Servlet and Servlet mapping.
WEB-INF/web.xml (excerpt)
Here I’ve created a Spring DispatcherServlet named books
and mapped it to the /booksearch/*
URL pattern. Nothing new here. Now I need to configure the Spring context XML file for this Servlet.
WEB-INF/books-servlet.xml (excerpt)
Pretty standard. As you can see I’m scanning the com.stupidjavatricks.restexample
package for annotated classes. I’m using a BeanNameViewResolver
to keep the example simple, but you could get much more complex behavior using other ViewResolvers including a new favorite of mine:ContentNegotiatingViewResolver
. The view I’m adding here is a MarshallingView
, which takes POJOs and marshals them to XML, automatically. In order for this to work, I need to pass a Marshaller
object to the MarshallingView
constructor. I chose XStreamMarshaller because I’m familiar with XStream, but you could choose any of the other implementations including CastorMarshaller
, XmlBeansMarshaller
, etc (Something to note about these marshallers is that they implement both the Marshaller
andUnMarshaller
interfaces.). You’ll notice that I set the autodetectAnnotations
property to true. This will allow XStream to take advantage of any annotated classes on the classpath. This convenience comes at a price however, so if you wish you can explicitly tell XStream which annotated classes to look for. You would do this in the Spring XML context by removing the autodetectAnnotations
property and passing a list of classes to the annotatedClasses
property. Check the XStreamMarshaller API for more configuration settings.
Testing
You can build and run this any number of ways. I use Maven to build and Apache Tomcat to run it.
You can download the code here.
From the spring-rest-example-model project directory you can run mvn install
. Then from within the spring-rest-example project directory mvn package
. Check the target directory of the last project for the WAR file and deploy it to the Tomcat webapps
directory and start the server. For a list of all authors and all books in this example you can browse to http://localhost:8080/spring-rest-example/booksearch/authors/ and http://localhost:8080/spring-rest-example/booksearch/books/respectively.
No comments:
Post a Comment