Action Commands
At the very basic, the de.odysseus.calyxo.control.Command interface represents something, that can be executed taking a http servlet request and response as parameters. The result of a command execution contains information on how to dispatch the request. To be more concrete, the Command interface defines the single method
public DispatchConfig execute( HttpServletRequest request, HttpServletResponse response) throws Exception;
The de.odysseus.calyxo.control.conf.DispatchConfig interface reflects a dispatch configuration, which contains information on how to dispatch the request.
Though uncommon, a command may generate and write the response on its own, making dispatching obsolete. A command indicates this by answering null.
The Command interface is not intended to be directly implemented by application developers. However, application developers come into touch with it at two points:
First, the controller combines an action's filters and command into a chain of Commands. Therefore, the remaining chain is passed to a filter as a Command object.
And second, action commands have to implement the de.odysseus.calyxo.control.Action interface, which extends the Command interface by adding method
public void init( ActionConfig config, ModuleContext context) throws Exception;
After instantiation, the controller gives an action the opportunity to do some initialization by calling its init() method. The de.odysseus.calyxo.control.conf.ActionConfig interface reflects the action's configuration and provides methods to access parameters, find dispatch configurations and more.
The execute() method will be called during action invocation, as the action command is the last link in the command chain executed by the controller.
The controller instantiates exactly one instance per action configuration. As an important consequence, an action command can maintain its configuration as its internal state. On the other hand, it has to be thread safe, since parallel invocations of the same action will execute the same action command instance.
Since Action is an interface, developers are free to implement action commands anywhere in their class hierarchy. However, Calyxo Control supplies a convenient base action command class, namely de.odysseus.calyxo.control.misc.AbstractAction. If you do not need to inherit from any particular class, we recommend using this one. It provides access to the action configuration, module context and message support objects. Its implementation of init(ActionConfig, ModuleContext) delegates to an init() method, which may be implemented by subclasses to do further initialization.
Consider the following simple action configuration:
<action path="/login" class="org.foo.bar.LoginAction"> <dispatch name="success" action="/welcome"/> <dispatch name="failure" path="/WEB-INF/jsp/login.jsp"/> </action>
The /login action defines class org.foo.bar.LoginAction to be its action command class.
Directly implementing the Action interface
A direct Action implementation might look like this:
package org.foo.bar;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import de.odysseus.calyxo.base.Message;
import de.odysseus.calyxo.base.ModuleContext;
import de.odysseus.calyxo.control.Action;
import de.odysseus.calyxo.control.MessageSupport;
import de.odysseus.calyxo.control.conf.ActionConfig;
import de.odysseus.calyxo.control.conf.DispatchConfig;
public class LoginAction implements Action {
private ActionConfig config;
private MessageSupport messages;
/**
* Initialize action.
*/
public void init(ActionConfig config, ModuleContext context)
throws Exception {
this.config = config;
this.messages = MessageSupport.getInstance(context);
}
/**
* Execute action.
*/
public DispatchConfig execute(
HttpServletRequest request,
HttpServletResponse response) throws Exception {
boolean ok = false;
// do login...
if (ok) {
return config.findDispatchConfig("success");
} else {
Message message = new Message("messages", "login.failed");
messages.addError(request, message);
return config.findDispatchConfig("failure");
}
}
}
Inheriting from AbstractAction
Let's rewrite our action by making it a subclass of AbstractAction and see what it looks like:
package org.foo.bar;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import de.odysseus.calyxo.base.Message;
import de.odysseus.calyxo.control.conf.DispatchConfig;
import de.odysseus.calyxo.control.misc.AbstractAction;
public class LoginAction extends AbstractAction {
/**
* Execute action.
*/
public DispatchConfig execute(
HttpServletRequest request,
HttpServletResponse response) throws Exception {
boolean ok = false;
// do login...
if (ok) {
return getActionConfig().findDispatchConfig("success");
} else {
Message message = new Message("messages", "login.failed");
getMessageSupport().addError(request, message);
return getActionConfig().findDispatchConfig("failure");
}
}
}
Quite compact, isn't it?


