org.springframework.webflow.action.AbstractAction Maven / Gradle / Ivy
/*
* Copyright 2002-2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.webflow.action;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.ClassUtils;
import org.springframework.webflow.Action;
import org.springframework.webflow.AttributeCollection;
import org.springframework.webflow.CollectionUtils;
import org.springframework.webflow.Event;
import org.springframework.webflow.RequestContext;
import org.springframework.webflow.support.EventFactorySupport;
/**
* Base action that provides assistance commonly needed by action
* implementations. This includes:
*
* - Implementing {@link InitializingBean} to receive an init callback
* when deployed within a Spring bean factory.
*
- Exposing convenient event factory methods to create common result
* {@link Event} objects such as "success" and "error".
*
- A hook for inserting action pre and post execution logic.
*
*
* @author Keith Donald
* @author Erwin Vervaet
*/
public abstract class AbstractAction implements Action, InitializingBean {
/**
* Logger, usable in subclasses.
*/
protected final Log logger = LogFactory.getLog(getClass());
/**
* Returns the helper delegate for creating action execution result events.
* @return the event factory support
*/
public EventFactorySupport getEventFactorySupport() {
return new EventFactorySupport();
}
public void afterPropertiesSet() throws Exception {
try {
initAction();
}
catch (Exception ex) {
throw new BeanInitializationException("Initialization of this Action failed: " + ex.getMessage(), ex);
}
}
/**
* Action initializing callback, may be overriden by subclasses to perform
* custom initialization logic.
*
* Keep in mind that this hook will only be invoked when this action is
* deployed in a Spring application context since it uses the Spring
* {@link InitializingBean} mechanism to trigger actionn initialisation.
*/
protected void initAction() throws Exception {
}
/**
* Returns a "success" result event.
*/
protected Event success() {
return getEventFactorySupport().success(this);
}
/**
* Returns a "success" result event with the provided result object as a
* parameter.
* @param result the action success result
*/
protected Event success(Object result) {
return getEventFactorySupport().success(this, result);
}
/**
* Returns an "error" result event.
*/
protected Event error() {
return getEventFactorySupport().error(this);
}
/**
* Returns an "error" result event caused by the provided exception.
* @param e the exception that caused the error event, to be configured as
* an event attribute
*/
protected Event error(Exception e) {
return getEventFactorySupport().error(this, e);
}
/**
* Returns a "yes" result event.
*/
protected Event yes() {
return getEventFactorySupport().yes(this);
}
/**
* Returns a "no" result event.
*/
protected Event no() {
return getEventFactorySupport().no(this);
}
/**
* Returns yes() if the boolean result is true, no() if false.
* @param booleanResult the boolean
* @return yes or no
*/
protected Event result(boolean booleanResult) {
return getEventFactorySupport().event(this, booleanResult);
}
/**
* Returns a result event for this action with the specified identifier.
* Typically called as part of return, for example:
*
*
* protected Event doExecute(RequestContext context) {
* // do some work
* if (some condition) {
* return result("success");
* } else {
* return result("error");
* }
* }
*
*
* Consider calling the error() or success() factory methods for returning
* common results.
* @param eventId the result event identifier
* @return the action result event
*/
protected Event result(String eventId) {
return getEventFactorySupport().event(this, eventId);
}
/**
* Returns a result event for this action with the specified identifier and
* the specified set of attributes. Typically called as part of return, for
* example:
*
*
* protected Event doExecute(RequestContext context) {
* // do some work
* AttributeMap resultAttributes = new AttributeMap();
* resultAttributes.put("name", "value");
* if (some condition) {
* return result("success", resultAttributes);
* } else {
* return result("error", resultAttributes);
* }
* }
*
*
* Consider calling the error() or success() factory methods for returning
* common results.
* @param eventId the result event identifier
* @param resultAttributes the event attributes
* @return the action result event
*/
protected Event result(String eventId, AttributeCollection resultAttributes) {
return getEventFactorySupport().event(this, eventId, resultAttributes);
}
/**
* Returns a result event for this action with the specified identifier and
* a single attribute.
* @param eventId the result id
* @param resultAttributeName the attribute name
* @param resultAttributeValue the attribute value
* @return the action result event
*/
protected Event result(String eventId, String resultAttributeName, Object resultAttributeValue) {
return result(eventId, CollectionUtils.singleEntryMap(resultAttributeName, resultAttributeValue));
}
public final Event execute(RequestContext context) throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("Action '" + getActionNameForLogging() + "' beginning execution");
}
Event result = doPreExecute(context);
if (result == null) {
result = doExecute(context);
if (logger.isDebugEnabled()) {
if (result != null) {
logger.debug("Action '" + getActionNameForLogging() + "' completed execution; result is '" + result.getId() + "'");
}
else {
logger.debug("Action '" + getActionNameForLogging() + "' completed execution; result is [null]");
}
}
doPostExecute(context);
}
else {
if (logger.isInfoEnabled()) {
logger.info("Action execution disallowed; pre-execution result is '" + result.getId() + "'");
}
}
return result;
}
// subclassing hooks
/**
* Internal helper to return the name of this action for logging
* purposes. Defaults to the sort class name.
* @see ClassUtils#getShortName(java.lang.Class)
*/
protected String getActionNameForLogging() {
return ClassUtils.getShortName(getClass());
}
/**
* Pre-action-execution hook, subclasses may override. If this method
* returns a non-null
event, the doExecute()
* method will not be called and the returned event will be used to
* select a transition to trigger in the calling action state. If this
* method returns null
, doExecute()
will be
* called to obtain an action result event.
*
* This implementation just returns null
.
* @param context the action execution context, for accessing and setting
* data in "flow scope" or "request scope"
* @return the non-null
action result, in which case the
* doExecute()
will not be called, or null
if
* the doExecute()
method should be called to obtain the
* action result
* @throws Exception an unrecoverable exception occured, either
* checked or unchecked
*/
protected Event doPreExecute(RequestContext context) throws Exception {
return null;
}
/**
* Template hook method subclasses should override to encapsulate their
* specific action execution logic.
* @param context the action execution context, for accessing and setting
* data in "flow scope" or "request scope"
* @return the action result event
* @throws Exception an unrecoverable exception occured, either
* checked or unchecked
*/
protected abstract Event doExecute(RequestContext context) throws Exception;
/**
* Post-action execution hook, subclasses may override. Will only be called
* if doExecute()
was called, e.g. when doPreExecute()
* returned null
.
*
* This implementation does nothing.
* @param context the action execution context, for accessing and setting
* data in "flow scope" or "request scope"
* @throws Exception an unrecoverable exception occured, either
* checked or unchecked
*/
protected void doPostExecute(RequestContext context) throws Exception {
}
}