You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

Overview

The Rest Plugin simplifies Rest-style resources to be consumed by both human and machine clients. The goals are to 100% follow Ruby on Rails-style Rest URL conventions and enable XML-free resource development. It builds on the Codebehind Plugin to support automatic configuration of both actions and results.

Error formatting macro: snippet: java.lang.NullPointerException

Or, expressed as a table:

HTTP method

URI

Class.method

parameters

GET

/movie

Movie.index

POST

/movie

Movie.create

PUT

/movie/Thrillers

Movie.update

id="Thrillers"

DELETE

/movie/Thrillers

Movie.destroy

id="Thrillers"

GET

/movie/Thrillers

Movie.show

id="Thrillers"

GET

/movie/Thrillers/edit

Movie.edit

id="Thrillers"

GET

/movie/new

Movie.editNew

In addition to being a Rest-style URL mapper, this plugin provides built-in support for multiple content types, switchable through the URL extension. In this way, a single resource can be exposed as multiple content types without any extra work.

For example, by exposing an "orders" resource, clients can immediately access it via:

http://my.company.com/myapp/orders/1
http://my.company.com/myapp/orders/1.xml
http://my.company.com/myapp/orders/1.xhtml
http://my.company.com/myapp/orders/1.json

and the framework handles the serialization and deserialization automatically.

Features

  • Fully implements Ruby-On-Rails Rest-style URLs
  • Supports XML-free development, without requiring annotations
  • Built-in serialization support for XML and JSON
  • Automatic handling of errors
  • Type-safe configuration of the HTTP response
  • Automatic conditional GET support

Usage

As with the Codebehind Plugin, the first step is to tell the plugin where to find your resource action classes. Modify the configuration of your Struts 2 filter in web.xml and add the 'actionPackages' init-param like so:

Error formatting macro: snippet: java.lang.NullPointerException

Next, create Java objects ending in "Resource" in the configured package. The "Resource" suffix is used to distinguish Rest action resources from regular Struts 2 actions, although it is completely optional and they are functionally the same. Now, add in methods to handle the various requests. For example, the following resource action will support /orders/34 GET and PUT requests:

package org.apache.struts2.rest.example;

public class OrdersResource implements ModelDriven<Order> {

    private OrderManager orderManager;
    private String id;
    private Order model;
   
    // Handles /orders/{id} GET requests
    public RestInfo show() {
        model = orderManager.findOrder(id);
        return new DefaultRestInfo()
            .renderResult("show")
            .withETag(model.getUniqueStamp())
            .lastModified(model.getLastModified());
    }

    // Handles /orders/{id} PUT requests
    public String update() {
        orderManager.updateOrder(model);
        return "update";
    }

    // getters and setters
}

In this example, the ModelDriven interface is used to ensure that only my model, the Order object in this case, is returned to the client, otherwise, the whole OrdersResource object would be serialized.

You may wonder why the show() method returns a RestInfo object and the update() method returns the expected result code String. Well, the Rest Plugin adds in support for action methods that return RestInfo objects as a way for the action to have more control over the response. In this example, we wanted to ensure the response included the ETag header and a last modified date so that the information will be cached properly by the client. The RestInfo object is a convenient way to control the response in a type-safe way.

Also, notice we aren't returning the usual "success" result code in either method. This allows us to use the special features of the Codebehind Plugin to intuitively select the result template to process when this resource is accessed with the .xhtml extension. In this case, we can provide a customized XHTML view of the resource by creating /orders-show.jsp and /orders-update.jsp for the respective methods.

Custom ContentTypeHandlers

If you need to handle extensions that aren't supported by the default handlers, you can create your own ContentTypeHandler implementation and define it in your struts.xml:

<bean name="yaml" type="org.apache.struts2.rest.handler.ContentTypeHandler" class="com.mycompany.MyYamlContentHandler" />

If the built-in content type handlers don't do what you need, you can override the handling of any extension by providing an alternate handler. First, define your own ContentTypeHandler and declare with its own alias. For example:

<bean name="myXml" type="org.apache.struts2.rest.handler.ContentTypeHandler" class="com.mycompany.MyXmlContentHandler" />

Then, tell the Rest Plugin to override the handler for the desired extension with yours. In struts.properties, it would look like this:

struts.rest.handlerOverride.xml=myXml

Example

The plugin ships with a struts2-rest-showcase application that demonstrates a simple Rest web program.

Settings

The following settings can be customized. See the developer guide.

Setting

Description

Default

Possible Values

struts.rest.handlerOverride.EXTENSION

The alias for the ContentTypeHandler implementation that handles the EXTENSION value

N/A

Any declared alias for a ContentTypeHandler implementation

struts.rest.defaultHandlerName

The default extension to use when non is explicitly specified in the request

xml

Any extension

Installation

This plugin can be installed by copying the plugin jar into your application's /WEB-INF/lib directory. It does depend on the Codebehind Plugin, so if aren't using a build system that supports transitive dependencies like Maven 2, you will need to add that plugin as well.

Resources

Version History

From Struts 2.1.1+

  • No labels