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

Compare with Current View Page History

« Previous Version 44 Next »

This plugin is only available with Struts 2.1.1 or later

Overview

The REST Plugin provides high level support for the implementation of RESTful resource based web applications. The REST plugin can cooperate with the Convention Plugin to support a zero configuration approach to declaring your actions and results, but you can always use the REST plugin with XML style configuration if you like.

Features

  • Ruby on Rails REST-style URLs
  • Zero XML config when used with Convention Plugin
  • Built-in serialization and deserialization support for XML and JSON
  • Automatic error handling
  • Type-safe configuration of the HTTP response
  • Automatic conditional GET support

RestActionMapper

The main functionality of the REST plugin lies in the interpretation of incoming request URL's according the RESTful rules. In the Struts 2 framework, this 'mapping' of request URL's to Actions is handled by in implementation of the ActionMapper interface. Out of the box, Struts 2 uses the DefaultActionMapper to map URL's to Actions via the logic you are probably already familiar with.

Actions or Controllers? Most Struts 2 developers are familiar with the Action. They are the things that get executed by the incoming requests. In the context of the REST plugin, just to keep you on your toes, we'll adopt the RESTful lingo and refer to our Actions as Controllers. Don't be confused; it's just a name!

The REST plugin provides an alternative implementation, RestActionMapper, that provides the RESTful logic that maps a URL to a give action class ( aka 'controller' in RESTful terms ) and, more specifically, to the invocation of a method on that controller class. The following section, which comes from the Javadoc for the class, details this logic.

RESTful URL Mapping Logic

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

 

Content Types

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

The REST plugin automatically handles serialization to, and deserialization from, each format.

Usage

First, create your Controller classes. Note, Actions normally expose the execute method to as their target method. Controllers expose a different set of methods, indicated in the RESTful URL to controller/method logic described above. For example, the following resource action will support /orders/34 GET and PUT requests:

package org.apache.struts2.rest.example;

public class OrdersController implements ModelDriven<Order> {

    private OrderManager orderManager;
    private String id;
    private Order model;

    // Handles /orders/{id} GET requests
    public HttpHeaders show() {
        model = orderManager.findOrder(id);
        return new DefaultHttpHeaders("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 OrdersController object would be serialized.

You may wonder why the show() method returns a HttpHeaders object and the update() method returns the expected result code String. The REST Plugin adds support for action methods that return HttpHeaders 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 HttpHeaders 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

struts.xml

Instruct Struts to use the REST action mapper:

<constant name="struts.mapper.class" value="rest" />

Because the REST plugin uses the Convention plugin, some settings need to be set in struts.xml:

<constant name="struts.convention.action.suffix" value="Controller"/>
<constant name="struts.convention.action.mapAllMatches" value="true"/>
<constant name="struts.convention.default.parent.package" value="rest-default"/>

and for this example:

<constant name="struts.convention.package.locators" value="example"/>

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.
For more configuration options see the Convention Plugin Documentation

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.defaultExtension

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

xml

Any extension

struts.rest.validationFailureStatusCode

The HTTP status code to return on validation failure

400

Any HTTP status code as an integer

struts.rest.namespace

Optional parameter to specify namespace for REST services

/

eg. /rest

struts.rest.content.restrictToGET

Optional parameter, if set to true blocks returning content from any other methods than GET, if set to false, the content can be returned for any kind of method

true

eg. put struts.rest.content.restrictToGET = false in struts.properties

Installation

This plugin can be installed by copying the plugin jar into your application's /WEB-INF/lib directory. The REST plugin is dependent on the Convention 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