Version 4.10.0

hirondelle.web4j.action
Class ActionImpl

Object
  extended by hirondelle.web4j.action.ActionImpl
All Implemented Interfaces:
Action
Direct Known Subclasses:
ActionTemplateListAndEdit, ActionTemplateSearch, ActionTemplateShowAndApply

public abstract class ActionImpl
extends Object
implements Action

Abstract Base Class (ABC) for implementations of the Action interface.

This ABC provides concise methods for common operations, which will make implementations read more clearly, concisely, and at a higher level of abstraction.

A simple fetch-and-display operation can often be implemented using this class as a base class. However, operations involving user input and/or edits to the datastore should very likely use other abstract base classes, such as ActionTemplateListAndEdit, ActionTemplateSearch, and ActionTemplateShowAndApply.

This class places success/fail messages in session scope, not request scope. This is because such messages often need to survive a redirect operation. For example, when a successful edit to the database occurs, a redirect is usually performed, to avoid problems with browser reloads. The only way a success message can survive a redirect is by being placed in session scope.

This class assumes that a session already exists. If a session does not already exist, then calling such methods will result in an error. In practice, the user will almost always have already logged in, and this will not be a problem. As a backup, actions can always explicitly create a session, if needed, by calling

getRequestParser.getRequest().getSession(true);


Field Summary
static String DATA
          Value "data" - generic key for a single 'data' object placed in scope for a JSP.
static String ERRORS
          Value "web4j_key_for_errors" - identifies a MessageList, placed in session scope, to hold error information for the end user.
static String ITEM_FOR_EDIT
          Value "itemForEdit" - generic key for an object placed in scope for a JSP.
static String ITEMS_FOR_LISTING
          Value "itemsForListing" - generic key for a collection of objects placed in scope for a JSP.
static String MESSAGES
          Value "web4j_key_for_messages" - identifies a MessageList, placed in session scope, to hold messages for the end user.
static String USER_ID
          Value "web4j_key_for_user_id" - identifies the user's id, placed in session scope.
 
Constructor Summary
protected ActionImpl(ResponsePage aNominalPage, RequestParser aRequestParser)
          Constructor.
 
Method Summary
protected  void addError(AppException aEx)
          Add all the error messages attached to aEx.
protected  void addError(String aMessage)
          Add a simple AppResponseMessage describing a failed validation of user input, or a failed datastore operation.
protected  void addError(String aMessage, Object... aParams)
          Add a compound AppResponseMessage describing a failed validation of user input, or a failed datastore operation.
protected  void addMessage(String aMessage)
          Add a simple AppResponseMessage, to be displayed to the end user.
protected  void addMessage(String aMessage, Object... aParams)
          Add a compound AppResponseMessage, to be displayed to the end user.
protected  void addToRequest(String aName, Object aObject)
          Add a name-object pair to request scope.
protected  void addToSession(String aName, Object aObject)
          Add a name-object pair to an existing session.
protected  void copyFromSessionToRequest(String aName)
          Place an object which is in an existing session into request scope as well.
protected  void createSessionAndCsrfToken()
          Create a new session (if one doesn't already exist) outside of the usual user login, and add a CSRF token to the new session to defend against Cross-Site Request Forgery (CSRF) attacks.
protected  void endSession()
          If a session exists, then it is invalidated.
abstract  ResponsePage execute()
          Execute desired operation.
protected  MessageList getErrors()
          Return all the errors passed to all addError methods.
protected  HttpSession getExistingSession()
          Return the existing session.
protected  Object getFromSession(String aName)
          Retrieve an object from an existing session, or null if no object is paired with aName.
protected  Id getIdParam(RequestParameter aReqParam)
          Convenience method for retrieving a parameter as a simple Id.
protected  Collection<Id> getIdParams(RequestParameter aReqParam)
          Convenience method for retrieving a multivalued parameter as a simple Collection<Id>.
protected  Locale getLocale()
          Return the Locale associated with the underlying request.
protected  SafeText getLoggedInUserName()
          Return the name of the logged in user.
protected  MessageList getMessages()
          Return all messages passed to all addMessage methods
protected  Operation getOperation()
          Return the Operation associated with this Action, if any.
protected  DynamicSql getOrderBy(RequestParameter aSortColumn, RequestParameter aOrder, String aDefaultOrderBy)
          Return an ORDER BY clause for an SQL statement.
protected  SafeText getParam(RequestParameter aReqParam)
          Convenience method for retrieving a parameter as SafeText.
protected  String getParamUnsafe(RequestParameter aReqParam)
          Convenience method for retrieving a parameter as raw text, with no escaped characters.
protected  RequestParser getRequestParser()
          Return the RequestParser passed to the constructor.
 ResponsePage getResponsePage()
          Return the resource which will render the final result.
protected  TimeZone getTimeZone()
          Return the TimeZone associated with the underlying request.
protected  Id getUserId()
          Return the Id stored in session scope under the key USER_ID.
protected  boolean hasErrors()
          Return true only if at least one addError method has been called.
protected  void removeFromSession(String aName)
          Synonym for addToSession(aName, null).
protected  void setResponsePage(ResponsePage aNewResponsePage)
          Called by subclasses if the final ResponsePage differs from the nominal one passed to the constructor.
 
Methods inherited from class Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

ERRORS

public static final String ERRORS
Value "web4j_key_for_errors" - identifies a MessageList, placed in session scope, to hold error information for the end user. These errors are used by both WEB4J and the application programmer.

See Also:
Constant Field Values

MESSAGES

public static final String MESSAGES
Value "web4j_key_for_messages" - identifies a MessageList, placed in session scope, to hold messages for the end user. These messages are used by both WEB4J and the application programmer. They typically hold success and information messages.

See Also:
Constant Field Values

USER_ID

public static final String USER_ID
Value "web4j_key_for_user_id" - identifies the user's id, placed in session scope.

Many applications will benefit from having both the user id and the user login name placed in session scope upon login. The Servlet Container will place the user login name in session scope upon login, but it will not place the corresponding user id (the database's primary key of the user record) in session scope.

If an application chooses to place the user's underlying database id into session scope under this USER_ID key, then the user's id will be returned by getUserId().

See Also:
Constant Field Values

ITEM_FOR_EDIT

public static final String ITEM_FOR_EDIT
Value "itemForEdit" - generic key for an object placed in scope for a JSP.

Not mandatory to use this generic key. Provided simply as a convenience.

See Also:
Constant Field Values

ITEMS_FOR_LISTING

public static final String ITEMS_FOR_LISTING
Value "itemsForListing" - generic key for a collection of objects placed in scope for a JSP.

Not mandatory to use this generic key. Provided simply as a convenience.

See Also:
Constant Field Values

DATA

public static final String DATA
Value "data" - generic key for a single 'data' object placed in scope for a JSP. Usually used with structured data, such as JSON, XML, CSV, and so on.

Not mandatory to use this generic key. Provided simply as a convenience.

See Also:
Constant Field Values
Constructor Detail

ActionImpl

protected ActionImpl(ResponsePage aNominalPage,
                     RequestParser aRequestParser)
Constructor.

This constructor will add an attribute named 'Operation' to the request. Its value is deduced as specified by getOperation(). This attribute is intended for JSPs, which can use it to access the Operation regardless of its original source.

Parameters:
aNominalPage - simply one of the possible ResponsePages, arbitrarily chosen as a "default". It may be changed after construction by calling setResponsePage(hirondelle.web4j.action.ResponsePage). Recommended that the "success" page be chosen as the nominal page. If not, then selection of any of the possible ResponsePages is acceptable.
aRequestParser - allows parsing of request parameters into higher level java objects.
Method Detail

execute

public abstract ResponsePage execute()
                              throws AppException
Description copied from interface: Action
Execute desired operation.

Typical operations include :

Returns an identifier for the resource (for example a JSP) which will display the end result of this Action (using either a forward or a redirect).

Specified by:
execute in interface Action
Throws:
AppException

getResponsePage

public final ResponsePage getResponsePage()
Return the resource which will render the final result.


getOperation

protected final Operation getOperation()
Return the Operation associated with this Action, if any.

The Operation is found as follows :

  1. if there is a request parameter named 'Operation', and it has a value, pass its value to Operation.valueFor(String)
  2. if the above style fails, then the 'extension' is examined. For example, a request to .../MyAction.list?x=1 would result in Operation.List being added to request scope, since the extension value list is known to Operation.valueFor(String). This style is useful for implementing fine-grained <security-constraint> items in web.xml. See the User Guide for more information.
  3. if both of the above methods fail, return null

When using the 'extension' style, please note that web.xml contains related servlet-mapping settings. Such settings control which HTTP requests (as defined by a url-pattern) are passed from the Servlet Container to your application in the first place. Thus, any 'extensions' which your application intends to use must have a corresponding servlet-mapping setting in your web.xml.


getLoggedInUserName

protected final SafeText getLoggedInUserName()
Return the name of the logged in user.

By definition in the servlet specification, a successfully logged in user will always have a non-null return value for HttpServletRequest.getUserPrincipal().

If the user is not logged in, this method will always return null.

This method returns SafeText, not a String. The user name is often rendered in the view. Since in general the user name may contain special characters, it is appropriate to model it as SafeText.


getUserId

protected final Id getUserId()
Return the Id stored in session scope under the key USER_ID. If no such item is found, then return null.

The user id should only be used in server-side code, and never presented to the user in a JSP.


setResponsePage

protected final void setResponsePage(ResponsePage aNewResponsePage)
Called by subclasses if the final ResponsePage differs from the nominal one passed to the constructor.

If an implementation calls this method, it is usually called in execute().


addToRequest

protected final void addToRequest(String aName,
                                  Object aObject)
Add a name-object pair to request scope.

If the pair already exists, it is updated with aObject.

Parameters:
aName - satisfies Util.textHasContent(String).
aObject - if null and a corresponding name-object pair exists, then the pair is removed from request scope.

getExistingSession

protected final HttpSession getExistingSession()
Return the existing session.

If a session does not already exist, then an error will result.


addToSession

protected final void addToSession(String aName,
                                  Object aObject)
Add a name-object pair to an existing session.

If the pair already exists, it is updated with aObject.

Parameters:
aName - satisfies Util.textHasContent(String).
aObject - if null and a corresponding name-object pair exists, then the pair is removed from session scope.

removeFromSession

protected final void removeFromSession(String aName)
Synonym for addToSession(aName, null).


getFromSession

protected final Object getFromSession(String aName)
Retrieve an object from an existing session, or null if no object is paired with aName.

Parameters:
aName - satisfies Util.textHasContent(String).

copyFromSessionToRequest

protected final void copyFromSessionToRequest(String aName)
Place an object which is in an existing session into request scope as well.

When serving the last page in a session, some session items may still be needed for rendering the final page.

For example, a log off page in a mutlilingual application might present a "goodbye" message in the language that the user was using. Since the session is being destroyed, the Locale stored in the session must be first copied into request scope before the session is killed.

Parameters:
aName - identifies an Object which is currently in session scope, and satisfies Util.textHasContent(String). If no attribute of the given name is found in the current session, then a null is added to the request scope under this name.

endSession

protected final void endSession()
If a session exists, then it is invalidated. This method should be called only when the user is logging out.


addError

protected final void addError(String aMessage)
Add a simple AppResponseMessage describing a failed validation of user input, or a failed datastore operation.

One of the addError methods must be called when a failure occurs.


addError

protected final void addError(String aMessage,
                              Object... aParams)
Add a compound AppResponseMessage describing a failed validation of user input, or a failed datastore operation.

One of the addError methods must be called when a failure occurs.


addError

protected final void addError(AppException aEx)
Add all the error messages attached to aEx.

One of the addError methods must be called when a failure occurs.


getErrors

protected final MessageList getErrors()
Return all the errors passed to all addError methods.


hasErrors

protected final boolean hasErrors()
Return true only if at least one addError method has been called.


addMessage

protected final void addMessage(String aMessage)
Add a simple AppResponseMessage, to be displayed to the end user.


addMessage

protected final void addMessage(String aMessage,
                                Object... aParams)
Add a compound AppResponseMessage, to be displayed to the end user.


getMessages

protected final MessageList getMessages()
Return all messages passed to all addMessage methods


getLocale

protected final Locale getLocale()
Return the Locale associated with the underlying request.

The configured implementation of LocaleSource defines how Locale is looked up.


getTimeZone

protected final TimeZone getTimeZone()
Return the TimeZone associated with the underlying request.

The configured implementation of TimeZoneSource defines how TimeZone is looked up.


getRequestParser

protected final RequestParser getRequestParser()
Return the RequestParser passed to the constructor.


getIdParam

protected final Id getIdParam(RequestParameter aReqParam)
Convenience method for retrieving a parameter as a simple Id.

Synonym for getRequestParser().toId(RequestParameter).


getIdParams

protected final Collection<Id> getIdParams(RequestParameter aReqParam)
Convenience method for retrieving a multivalued parameter as a simple Collection<Id>.

Synonym for getRequestParser().toIds(RequestParameter).


getParam

protected final SafeText getParam(RequestParameter aReqParam)
Convenience method for retrieving a parameter as SafeText.

Synonym for getRequestParser().toSafeText(RequestParameter).


getParamUnsafe

protected final String getParamUnsafe(RequestParameter aReqParam)
Convenience method for retrieving a parameter as raw text, with no escaped characters.

This method call is unsafe in the sense that it returns String instead of SafeText. It is usually preferable to use SafeText, since it protects against Cross-Site Scripting attacks.

If, however, the caller needs to use a request parameter value to perform a computation, as opposed to presenting user data in markup, then this method is provided as a convenience.


getOrderBy

protected final DynamicSql getOrderBy(RequestParameter aSortColumn,
                                      RequestParameter aOrder,
                                      String aDefaultOrderBy)
Return an ORDER BY clause for an SQL statement.

Provided as a convenience for the common task of creating an ORDER BY clause from request parameters.

Parameters:
aSortColumn - carries a ResultSet column identifer, either a numeric column index, or the name of the column itself.
aOrder - carries the value ASC or DESC (ignores case).
aDefaultOrderBy - default text to be used if the request parameters are not present, or have no content.

createSessionAndCsrfToken

protected final void createSessionAndCsrfToken()
Create a new session (if one doesn't already exist) outside of the usual user login, and add a CSRF token to the new session to defend against Cross-Site Request Forgery (CSRF) attacks.

This method exists to extend the CsrfFilter, to allow it to apply to a form/action that does not already have a user logged in.

Warning: you can only call this method in Actions for which the SuppressUnwantedSessions filter is NOT in effect.

Warning: This method should be used with care when using Tomcat. This method creates an 'anonymous' session, unattached to any user login. Should the user log in afterwards, a robust web application should assign a new session id. (See OWASP for more information.) The problem is that Tomcat 5 and 6 do not follow this rule, and will retain any existing session id when the user logs in.

This method is needed only when the user has not yet logged in. An excellent example of operations not requiring a login are operations that deal with account management on a typical public web site :

For such forms, it's strongly recommended that corresponding Actions call this method. This will allow the CsrfFilter mechanism to be used to defend such forms against CSRF attack. As a second benefit, it will also allow information messages sent to the end user to survive redirect operations.


Version 4.10.0

Copyright Hirondelle Systems. Published October 19, 2013 - User Guide - All Docs.