Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info

This plugin is only available with Struts 2.1.1 or later

Table of Contents
minLevel2
outlinetrue

Overview

The REST Plugin

Excerpt

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.

...

RESTful URL Mapping Logic

This Restful action mapper enforces Ruby-On-Rails REST-style mappings. If the method is not specified (via '!' or 'method:' prefix), the method is "guessed" at using REST-style conventions that examine the URL and the HTTP method. Special care has been given to ensure this mapper works correctly with the codebehind plugin so that XML configuration is unnecessary.

This mapper supports the following parameters:

  • struts.mapper.idParameterName - If set, this value will be the name of the parameter under which the id is stored. The id will then be removed from the action name. Whether or not the method is specified, the mapper will  try to truncate the identifier from the url and store it as a parameter.
  • struts.mapper.indexMethodName - The method name to call for a GET request with no id parameter. Defaults to index.
  • struts.mapper.getMethodName - The method name to call for a GET request with an id parameter. Defaults to show.
  • struts.mapper.postMethodName - The method name to call for a POST request with no id parameter. Defaults to create.
  • struts.mapper.putMethodName - The method name to call for a PUT request with an id parameter. Defaults to update.
  • struts.mapper.deleteMethodName - The method name to call for a DELETE request with an id parameter. Defaults to destroy.
  • struts.mapper.editMethodName - The method name to call for a GET request with an id parameter and the edit view specified. Defaults to edit.
  • struts.mapper.newMethodName - The method name to call for a GET request with no id parameter and the new view specified. Defaults to editNew.

The following URL's will invoke its methods:

  • GET: /movies => method="index"
  • GET: /movies/Thrillers => method="show", id="Thrillers"
  • GET: /movies/Thrillers;edit => method="edit", id="Thrillers"
  • GET: /movies/Thrillers/edit => method="edit", id="Thrillers"
  • GET: /movies/new => method="editNew"
  • POST: /movies => method="create"
  • PUT: /movies/Thrillers => method="update", id="Thrillers"
  • DELETE: /movies/Thrillers => method="destroy", id="Thrillers"
Note

To simulate the HTTP methods PUT and DELETE, since they aren't supported by HTML, the HTTP parameter "_method" will be used.

Wiki Markup
{snippet:url=rest-plugin/src/main/java/org/apache/struts2/rest/RestActionMapper.java|id=description|javadoc=true}

Or, expressed as a table:

...

In addition to providing mapping of RESTful URL's to Controller ( Action ) invocations, the REST plugin also provides the ability to produce multiple representations of the resource data. By default, the plugin can return the resource in the following content types:*

  • HTML

...

  • XML 

...

  • JSON

There is nothing configure here, just add the conent type extension to your RESTful URL. The framework will take care of the rest. So, for instance, assuming a Controller called Movies and a movie with the id of superman, the following URL's will all hit the

Code Block

http://my.company.com/myapp/movies/superman
http://my.company.com/myapp/movies/superman.xml
http://my.company.com/myapp/movies/superman.xhtml
http://my.company.com/myapp/movies/superman.json

...

This section will walk you through a quick demo. Here are the steps in the sequence that we will follow.*

  • Setting Up your Project

...

  • Configuring your Project

...

  • Writing your Controllers

Setting Up

Assuming you have a normal Struts 2 application, all you need to do for this REST demo is to add the following two plugins: *

  • Struts 2 Rest Plugin

...

Note, you can download the jars for these plugins from Maven Central

...

Instruct Struts to use the REST action mapper:

Code Block
xml
xml

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

...

We're relying on the Convention plugin to find our controllers, so we need to configure the convention plugin a bit:

Code Block
xml
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"/>
<constant name="struts.convention.package.locators" value="example"/>

...

First, you'll need to re-assert the extensions that struts knows about because the rest plugin will have thrown out the default action extension.

Code Block
xml
xml

  <constant name="struts.action.extension" value="xhtml,,xml,json,action"/>

Next, we will configure the PrefixBasedActionMapper, which is part of the core Struts 2 distribution, to have some URL's routed to the Rest mapper and others to the default mapper.

Code Block
xml
xml

  <constant name="struts.mapper.class" value="org.apache.struts2.dispatcher.mapper.PrefixBasedActionMapper" />
  <constant name="struts.mapper.prefixMapping" value="/rest:rest,:struts"/>

And, again, we're relying on the Convention plugin to find our controllers, so we need to configure the convention plugin a bit:

Code Block
xml
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"/>
<constant name="struts.convention.package.locators" value="example"/>

...

Once everything is configured, you need to create the controllers. Controllers are simply actions created with the purpose of handling requests for a give RESTful resource. As we saw in the mapping logic above, various REST URL's will hit different methods on the controller. Traditionally, normal Struts 2 actions expose the execute method as their target method. Here's a sample controller for a orders resource. Note, this sample doesn't implement all of the methods that can be hit via the RESTful action mapper's interpretation of URL's.

Code Block
langjava

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
}

...

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:

Code Block
langxml

<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:

Code Block
langxml

<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:

Code Block

struts.rest.handlerOverride.xml=myXml

...