Actions are controller classes in the web layer that can be directly invoked by a browser request. It is a legacy term coined by the struts framework, and broadly adopted by several other java web frameworks.
Any class that implements the Action interface is considered an Action, but it is strongly recommended to make it also extend AbstractAction in order to take advantage of some convenience methods such as redirect(), forward(), etc. Actions are loaded automatically from the configured classpath packages.
Actions are identified by either their fully qualified names, but they usually can be identified by a short name that is equal to the name of the class with the "Action" suffix removed, if any: Blog would be the short name of com.acme.action.BlogAction. This short name can be used to indicate the target action of a form, a URL, or a redirect Resolution.
Any public Action method that receives no arguments and returns a Resolution instance is automatically considered an Event, and can be invoked from the browser. Event execution will be skipped if any validation or conversion errors occur or any Interceptor decides to interrupt the execution flow.
Actions may use the @Event annotation to define a default event that will be used when no event has been specified. If there is only one event it will automatically be set as default.
Actions and Events will be mapped to the lowercase version of the action short name, using dashes to separate words. This mapping can be modified using JAX-RS annotations to specify a different name or additional parameters embedded in the URL:
Events may also specify the allowed http methods used to invoke it. By default, an event with no specified method is mapped to serve GET and POST requests.
// by default this action would have been mapped as /blog-entries/
@Path("/entries")
public class BlogEntriesAction extends AbstractAction {
// /entries/foo (GET/POST)
public Resolution foo() { ... }
// /entries/foo-bar (DELETE)
@DELETE @Path("foo-bar")
public Resolution bar() { ... }
// receive one "id" parameter
@Path("baz/{id}")
public Resolution baz() { ... }
// receive three parameters, the last one is optional
@Path("create/{entry.year}-{entry.month}-{entry.day?}")
public Resolution create() { ... }
}
Since browsers only supports the GET and POST methods, forms will include a internal hidden field to override the http method.
Any conversion error of embedded parameters (e.g. alphanumeric text for integer parameters) will be transformed to a http 400 error response (malformed request).
Frequently you will need to generate a URL pointing to a target action and event. UrlBuilder includes a simple API to generate URLs:
UrlBuilder url = new UrlBuilder();
url.setAction(BlogAction.class);
url.setEvent("save");
url.addParameter("foo", "bar");
url.getURL(request); // ==> blog/save?foo=bar
The following is the execution flow diagram of a Loom request:
The execution flow may be interrupted at any time by configured interceptors in this order:
If the current request has Conversion or Validation errors the event method invocation will be skipped.
Interceptors are classes that implement the corresponding listener interface and may decide to stop the workflow by returning a non-null Resolution or let it continue. Interceptors can implement more than one listener interface, and are associated to Event instances by AnnotationProcessors. For concrete examples see the Interceptor class hierarchy.