Actions
The three most important terms in Madvoc are:
- action path - the HTTP request path or the URL;
- action - handler method, mapped to action path, processes requests; and
- result - handler for whatever action method returns, provides a response (using e.g. JSP). Often results threat returned object as a result path.
These three makes the whole cycle of handling request and providing response. Most of the configuration in Madvoc is done by convention, so always keep in mind this three dimensions of request processing.
Action path
Action is action method defined in action class, mapped to some URL - the action path. Madvoc uses naming convention (CoC) and annotations to define action path from action method. By default, action path is built from package, class and method name of an action or its annotations, using the following convention:
action path = /<action_package>/<action_class>.<action_method>.<extension>
extension
- extension value (default: "html"), defined by Madvoc configuration or specified in the annotation;action_method
- part of the action path that comes from action method, by default it is method name;action_class
- part of the action path that comes from action class, by default it is un-capitalized class name with the last word stripped;action_package
- optional part of the action path that comes from action's package.
By default, each part of action path is defined from method/class/package name so you don't have to explicitly specify anything. Still, each part of action path can be explicitly defined by corresponding annotation value, so you can easily override defaults.
Action class & action method
Bare minimum for creating an action is putting annotations on POJO class and one of its methods that is going to handle the action path request:
@MadvocAction public class HelloAction { @Action public void world() { } }
This action class and action method is mapped to the following action
path: /hello.world.html
. As said, each part of action path may be set
explicitly in annotations; the following action:
@MadvocAction("holla") public class HelloAction { @Action("mundo") public void world() { } }
is mapped to /holla.mundo.html
. Moreover, action paths are
built by simple string concatenation, so it is possible to set more
complex paths using annotations:
@MadvocAction("foo/boo") public class HelloAction { @Action("zoo/hello.exec") public void world() { } }
This action is mapped to: /foo/boo.zoo/hello.exec.html
.
One action class may contain more then one actions (action methods). This happens often, especially when you have set of similar requests over some same resource.
Custom extension
It sounds reasonable that most of the website's action paths end with
the same extension. Therefore, the default extension is defined in
global Madvoc configuration. However, it is still possible to set
custom extension using @Action
annotation's element extension
:
@MadvocAction public class HelloAction { @Action(extension="jpg") public void world() { } @Action(extension=Action.NONE) public void foo() { } }
The first action is mapped to: /hello.world.jpg
. The second one is
mapped to: /hello.foo
.
Action's extension is either default one or one defined by @Action
element extension
. There is no default convention in setting
action's extension.
Since Madvoc is very extensible, it is also possible to extend its
component dedicated for action path registration and to implement custom
behavior. For example, it is easy to develop such feature where any
method that starts with store...
has extension .do
instead of the
default one.
Full action path
To override Madvoc action naming conventions without coding, just specify the full action path in the annotation by using the prefix '/':
@MadvocAction public class HelloAction { @Action("/bonjour-monde.html") public void world() { } }
Obviously, this action is mapped to /bonjour-monde.html
. When action
path defined in @Action
starts with '/' it is considered as
full action path and all other names (class name, extension) are
ignored.
When full action path is specified, Madvoc will not append default
extension nor the custom one (defined by @Action
s element extension
).
Action packages
By default, packages are ignored and not used when building action paths. Nevertheless, it make sense to group several action paths (i.e. action classes) in one folder (i.e. package). Madvoc provides way how to include packages when building action paths.
First, this feature must be turned on by setting the root package, one that will be mapped to the web root. This can be set during Madvoc initialization. One way of doing this is:
public class MyWebApplication extends WebApplication { @Override protected void init(MadvocConfig madvocConfig, ServletContext servletContext) { madvocConfig.getRootPackages().addRootPackageOf(IndexAction.class); } }
Root package is defined by a package name and a path that package is mapped
to. For web root you may omit the path. Also, the package name can be defined
by passing the action class, like in above example. Therefore, above
configuration snippet defines one root package (package where IndexAction
class belongs to) mapped to the web root (/
).
When root packages are defined, Madvoc will use package name of action classes relative to the build action path. The package name is relative from the root package. The following action:
package org.jodd.madvoc.doc; @MadvocAction public class HelloAction { @Action public void world() { } }
is mapped to /doc/hello.world.html
, if the root package is set to:
org.jodd.madvoc
.
You can specify more then one root package. Be careful not to overlap mapping paths!
Root packages may be defined by putting an empty class named
MadvocRootPackage
(name is configurable) that is annotated with
@MadvocAction
. This class serves just as an marker for root packages.
Finally, it is possible to specify custom action package using
@MadvocAction
annotation on package (in package-info.java
).
It is also possible to override package annotation value with
@MadvocAction
annotation of action class: if its value starts with
'/' then package value is ignored.
Sometimes developer wants to group some action classes in separate
subpackage, but doesn't want to change the action path (e.g. the root
path). By specifying @MadvocAction("/")
on sub-packages Madvoc will
map all containing classes to the web root, as they were there and not
in the sub-package:
@MadvocAction("/") package com.....; import jodd.madvoc.meta.MadvocAction;
HTTP request methods
By default, Madvoc will ignore value of HTTP request method. No matter
if it is POST, GET or other, mapped action method will be invoked. If
needed, Madvoc offers more control considering HTTP methods: it allows
to specify one for action method, using @Action
annotation's element
method
:
@MadvocAction public class FormAction { @Action(method = "POST") public void store() { } }
This action method is mapped to /form.store.html
and will be invoked
only for POST HTTP request methods. GET and others will simply return
error 404 (page not found).
When HTTP method is specified, Madvoc will register such action path
with appended HTTP method information. Action from above example is
therefore mapped to: /form.store.html#POST
.
When looking up for the action path among registered once, Madvoc first tries to find action path with specified HTTP method. If such action path does not exist, Madvoc will lookup for action path with no HTTP method information.
Similar as for extensions, it is possible to extend Madvoc to programatically specify HTTP method to actions that match some custom criteria.
Nice practice is to specify the extension such as do
using @Action
annotation to all actions that are mapped to POST request (i.e. form
submissions) and then to programatically set POST for those actions, and
GET to all others; if it is not explicitly set different.
Default action methods
As seen, Madvoc uses action method name (or annotation value) for
creating action path. Moreover, it is possible to have action path that
doesn't include action method name - what is often needed for
'common' pages (such as index.html
, about.html
, error.html
). By
default, Madvoc will ignore action method name for methods named as
execute
and view
. Such action methods are so-called the default
ones. So, the following action:
@MadvocAction public class IndexAction { @Action public void view() { } }
is mapped simply to: /index.html
. If more than one default method name
is used, Madvoc will either take the last one, or will throw an
exception indicating duplicated action paths (depending on
configuration). Furthermore, default action names are part of global
Madvoc configuration and can be customized as needed.
Alternatively, @Action
annotation value element may be set to NONE
value. Then the method name will be ignored when building action path.
Therefore, following action has the same action path mapping:
@MadvocAction public class IndexAction { @Action(Action.NONE) public void foo() { } }
Action mapping cheat-sheet
Following table summarize default behavior of ActionMethodParser
-
Madvoc component dedicated for building action paths from registered
actions.
package | class | method | action path |
---|---|---|---|
* | * | /foo | /foo |
* | * | /foo.ext | /foo.ext |
* | /boo | foo | /boo.foo.html |
* | /boo | foo.ext | /boo.foo.ext.html |
(none) | boo | foo | /boo.foo.html |
(none) | boo | view/execute | /boo.html |
/zoo | boo | foo | /zoo/boo.foo.html |