Olimpiu POP
Olimpiu POP

Reputation: 5067

How to write a Spring web MVC 3 application in a RESTful way?

I worked for some time now on integration projects, mostly building and integrating services. Now I started an own, learning project to build an application from ground up and I am currently stumbling with writing the web UI. I used as framework spring framework and I want that in a first phase to use spring web mvc as UI technology. Nevertheless I intend to use REST controllers as I figured I would like to expose an API that might be consumed by a mobile client in the next step of my self-training. So the question really:

How to to tie the Web MVC front-end to the RESTful controllers behind?

Thank you!

Upvotes: 3

Views: 1123

Answers (2)

Gunslinger
Gunslinger

Reputation: 747

Your REST controllers are mvc controllers and of course there are many alternatives out there for getting them to return json or xml. Here are two alternatives:

Light and simple

Write controllers as normal. Have them return void. Take the HttpServletResponse as an in parameter. Use a json/xml serializer to serialize your result and write the output to the response. The controller doesn't forward to a view.

For instance, you can use http://flexjson.sourceforge.net/ to serialize to json.

An example:

@RequestMapping(value = "item/{someId}", method = RequestMethod.GET)
public void getItemById(HttpServletResponse response,
                        @PathVariable("someId") Long itemId) throws IOException {
    ... your code here, get the Item by the id ...
    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");
    JSONSerializer serializer = new JSONSerializer();
    serializer.exclude("*.class"); //reduce clutter in your output as you see fit
    serializer.serialize(objectToSerialize, response.getWriter());
}

Of course, outputting to json could be stored away in some other method. This method is very easy to implement and it is not hard to understand and work with.

More complicated

Use https://jersey.java.net/. This is not "do-it-yourself", it's a whole framework. Follow these steps:

  1. Write a XSD-file that contains your model to output
  2. Let jersey generate class-files that reflects this model. This becomes java sources that you can read.
  3. Write your controllers with jersey annotations and return your generated model objects (more or less).

XSD

This XSD

<xsd:element name="customerBonus" type="customerBonus"/>
<xsd:complexType name="customerBonus">
    <xsd:sequence>
        <xsd:element name="bonusAmount" type="xsd:long"/>
        <xsd:element name="bonusValidTo" type="xsd:date"/>
        <xsd:element name="upcomingBonusAmount" type="xsd:long"/>
    </xsd:sequence>
</xsd:complexType>

Becomes this java code (not complete for brevity):

@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "customerBonus", propOrder = { "bonusAmount", "bonusValidTo", "upcomingBonusAmount" }) public class CustomerBonus {

protected long bonusAmount;
@XmlElement(required = true)
@XmlSchemaType(name = "date")
protected XMLGregorianCalendar bonusValidTo;
protected long upcomingBonusAmount;

/**
 * Gets the value of the bonusAmount property.
 * 
 */
public long getBonusAmount() {
    return bonusAmount;
}

/**
 * Sets the value of the bonusAmount property.
 * 
 */
public void setBonusAmount(long value) {
    this.bonusAmount = value;
}

Enable the jersey servlet:

<servlet>
    <servlet-name>Jersey Spring Web Application</servlet-name>
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Jersey Spring Web Application</servlet-name>
    <url-pattern>/yourstarturl/*</url-pattern>
</servlet-mapping>

Typical controller:

@Path("cart") //base url for service
@Component
@Scope("request")
public class CartAndOrderResource extends AbstractResursResource {

    @GET
    @Produces({MediaType.APPLICATION_JSON}) //also xml possible here
    @Path("{cartId}") //added to base url, final url = cart/{cartId}
    public JAXBElement<Cart> getCart(@PathParam("cartId") String cartId) {
        return new ObjectFactory().createCart(cartService.getCart(cartId));
    }
}

Upvotes: 1

Chris Thompson
Chris Thompson

Reputation: 35598

There's a great tutorial here on how to do this. To summarize without getting into the specifics of the xml etc, you need to configure the dispatcher servlet that is built into Spring to respond to some set of urls, say /webapp/*. This will cause all requests that start with "/webapp/" to be forwarded to the dispatcher servlet.

You then configure your controller classes like so

@Controller
@RequestMapping("/users")
public class UsersController{

  @RequestMapping("/users/{id}")
  public String getUser(@PathVariable("id")String userId, Model model){

  //get the user, etc etc etc

  //return a string that points to the appropriate jsp page
  }
}

Spring can handle the rest. In this instance you're specifying the user id as part of the URL. You can also do all manner of things like handling posts, gets etc. You can create an arbitrary number of controllers and handler methods. In this case it would respond to the url "/webapp/users/someuserid".

Upvotes: 1

Related Questions