FemtoWeb/ActionSupport

From LoadingByte Wiki
Jump to navigation Jump to search

It is quite a repetitive task to create action classes. Moreover, when just implementing the plain Action interface, the programmer is left alone without any hints. The com.quartercode.femtoweb.api.ActionSupport class makes the development of actions more intuitive and reduces boilerplate code. Note, however, that it still stays inside the original scope of FemtoWeb and doesn't introduce completely new features like database access or form validation.

Basic Usage

Creating a new action using ActionSupport is quite easy. You just have to create a new class called XyzAction (of course, Xyz can be freely chosen) somewhere in the action base package or a subpackage of it. The new class must extend the com.quartercode.femtoweb.api.ActionSupport class (instead of implementing the com.quartercode.femtoweb.api.Action interface):

public class XyzAction extends ActionSupport {

    @Override
    protected Action doExecute() throws Exception {

        // Do stuff ...

        return new View(getClass(), "xyz.jsp");
    }

}

Behavior

Skip this part if you have already read the corresponding section about action behavior on the actions page.

The method doExecute() is called each time a user makes a request to the URI the action is mapped to. Note that a new instance of the action class is created for each request as well. The execute method should do everything that is required for the final JSP to work (e.g. contact the database, parse parameters, "push" request attributes) and then return a resolution (in most cases, a View).

Absolutely visit the page about resolutions for more information on what resolutions are and which types of resolutions exist. Without that knowledge, you won't be able to create actions.

Utility Fields

Any action class which extends ActionSupport also inherits the following protected fields. Those fields can be used from everywhere in the class.

Field Type Field Name Description
javax.servlet.http.HttpServletRequest request The internal JEE request object which represents the currently processed request.
javax.servlet.http.HttpServletResponse response The internal JEE response object which represents the response to the currently processed request.
com.quartercode.femtoweb.api.Context context An object which provides some framework settings, as well as some methods which depend on those settings. Although you will probably barely use this object, more information about it can be obtained through its JavaDoc.

Utility Methods

Although all necessary objects are available through utility fields, you don't need to directly access them in most cases. Instead, you can use the following utility methods.

Parameter Access

There are three utility methods available for reading HTTP request GET or POST parameters. All these methods ignore whether a parameter is GET or POST.

getParam()

Signature: String getParam(String name)

This method retrieves the HTTP request parameter that has the given name. For example, say that the current request URI is .../search?query=test&page=3. A call to this method with the parameter name query would yield the parameter value test. Of course, this method also supports access to POST parameters.

getParams()

Signature: List<String> getParams(String name)

This method retrieves all the HTTP request parameters that have the given name. For example, say that the current request URI is .../search?query=test&filter=red&filter=green (e.g. because multiple checkboxes have the same name, in this case filter). A call to this method with the parameter name filter would yield the parameter value list ["red", "green"]. Of course, this method also supports access to POST parameters.

Note that this method returns an empty list ([]) instead of null if the retrieved parameter doesn't actually exist. That behavior has been chosen for additional convenience.

isParamSet()

Signature: boolean isParamSet(String name)

This method returns whether the HTTP request parameter with the given name exists. For example, say that the current request URI is .../search?query=test&page=3. A call to this method with the parameter name query would yield true. However, a call with the parameter name user would return false because there's no such parameter in the request. Of course, this method also supports POST parameters.

Attribute Pushing

If you conclude a request by rendering a JSP, you probably want to hand over some data to that JSP. You can do that by pushing objects. Before the three possible methods for pushing values are introduced, the following JSP will show how to read the pushed objects using EL.

<html>
    <head>
        ...
    </head>
    <body>
        <p>Your selected product has the following price:</p>
        <p>${product.price}</p>
    </body>
</html>

In the action class, you can now push an object under the name product. As long as the product object has a JavaBean property price, the value of that property will be displayed. Of course, you can push all kinds of objects; even plain strings and primitives are possible.

If you are not familiar with the concept of EL and the JSP core taglib, we strongly recommend learning those technologies.

push()

Signature: void push(String name, Object value)

This method pushes the given key-value-pair as a request attribute so JSPs that conclude this action can use it. For example, say that we push the object product with the JavaBean property price. Any JSP following this very action could then access that price property of the product attribute using a variety of different ways (the easiest one being the EL expression ${product.price}).

repushSingle()

Signature: void repushSingle(String name)

This method pushes the given single parameter value (also see getParam()) if it exists. For example, say that we have a form which looks like this:

<form> <!-- The form sends its data to itself when you click submit -->
    <input type="text" name="query" /&gt;
    <!-- Submit button ... -->
</form>

If you click the submit button, the action that backs the JSP could retrieve and process the query parameter. However, when the JSP is displayed again (e.g. because form validation failed), the input field depicted above would no longer contain the text input by the user. In order to fix that, the action could always repush the parameter query so that the value can be reused by the input:

<form>
    <input type="text" name="query" value="${query}" />
    <!-- Submit button ... -->
</form>

You could say that this method just invokes the given code:

if (isParamSet(paramName)) {
    push(paramName, getParam(paramName));
}

repushMultiple()

Signature: void repushMultiple(String name)

This method pushes all values of the given parameter (also see getParams()) as a list if it exists. If you wonder what this could be useful for, take a look at repushSingle(). The documentation of that method discusses "repushing" a single parameter value. Of course, the JSP code for processing of a multiple parameter value is slightly more complicated. Still, it could be used for preserving the state of checkboxes or other multiple choice inputs.

Session Attribute Access

There are two shortcut methods available for quickly retrieving and setting session attributes. In contrast to pushed values, such attributes are preserved after the current request has been answered. In JSPs, session attributes can be accessed like simple pushed objects.

getSessionAttr()

Signature: Object getSessionAttr(String name)

This method returns the object which is assigned to the given name in the currently processed request's session. It might return null if no object is assigned to the name, or if no session has yet been created in the first place.

setSessionAttr()

Signature: void setSessionAttr(String name, Object value)

This method assigns the given object to the given name in the currently processed request's session. If another object is already assigned to the same name, the old object is replaced with the new one. That also means that a session attribute can be removed by just passing a null value into this method.