001: /*
002: * Copyright (c) 2002-2006 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.xwork;
006:
007: import com.opensymphony.xwork.interceptor.PreResultListener;
008: import com.opensymphony.xwork.util.OgnlValueStack;
009:
010: import java.io.Serializable;
011:
012: /**
013: * An ActionInvocation represents the execution state of an Action. It holds the Interceptors and the Action instance.
014: * By repeated re-entrant execution of the invoke() method, initially by the ActionProxy, then by the Interceptors, the
015: * Interceptors are all executed, and then the Action and the Result.
016: *
017: * @author Jason Carreira
018: * @see com.opensymphony.xwork.ActionProxy
019: */
020: public interface ActionInvocation extends Serializable {
021:
022: /**
023: * Get the Action associated with this ActionInvocation
024: */
025: Object getAction();
026:
027: /**
028: * @return whether this ActionInvocation has executed before. This will be set after the Action and the Result have
029: * executed.
030: */
031: boolean isExecuted();
032:
033: /**
034: * Gets the ActionContext associated with this ActionInvocation. The ActionProxy is
035: * responsible for setting this ActionContext onto the ThreadLocal before invoking
036: * the ActionInvocation and resetting the old ActionContext afterwards.
037: */
038: ActionContext getInvocationContext();
039:
040: /**
041: * Get the ActionProxy holding this ActionInvocation
042: */
043: ActionProxy getProxy();
044:
045: /**
046: * If the ActionInvocation has been executed before and the Result is an instance of ActionChainResult, this method
047: * will walk down the chain of ActionChainResults until it finds a non-chain result, which will be returned. If the
048: * ActionInvocation's result has not been executed before, the Result instance will be created and populated with
049: * the result params.
050: *
051: * @return a Result instance
052: */
053: Result getResult() throws Exception;
054:
055: /**
056: * Gets the result code returned from this ActionInvocation
057: */
058: String getResultCode();
059:
060: /**
061: * Sets the result code, possibly overriding the one returned by the
062: * action.
063: * <p/>
064: * <p/>
065: * The "intended" purpose of this method is to allow PreResultListeners to
066: * override the result code returned by the Action.
067: * </p>
068: * <p/>
069: * <p/>
070: * If this method is used before the Action executes, the Action's returned
071: * result code will override what was set. However the Action could (if
072: * specifically coded to do so) inspect the ActionInvocation to see that
073: * someone "upstream" (e.g. an Interceptor) had suggested a value as the
074: * result, and it could therefore return the same value itself.
075: * </p>
076: * <p/>
077: * <p/>
078: * If this method is called between the Action execution and the Result
079: * execution, then the value set here will override the result code the
080: * action had returned. Creating an Interceptor that implements
081: * PreResultListener will give you this oportunity.
082: * </p>
083: * <p/>
084: * <p/>
085: * If this method is called after the Result has been executed, it will
086: * have the effect of raising an exception.
087: * </p>
088: *
089: * @throws IllegalStateException if called after the Result has been
090: * executed.
091: * @see #isExecuted()
092: */
093: void setResultCode(String resultCode);
094:
095: /**
096: * @return the ValueStack associated with this ActionInvocation
097: */
098: OgnlValueStack getStack();
099:
100: /**
101: * Register a com.opensymphony.xwork.interceptor.PreResultListener to be notified after the Action is executed and
102: * before the Result is executed. The ActionInvocation implementation must guarantee that listeners will be called in
103: * the order in which they are registered. Listener registration and execution does not need to be thread-safe.
104: */
105: void addPreResultListener(PreResultListener listener);
106:
107: /**
108: * Invokes the next step in processing this ActionInvocation. If there are more Interceptors, this will call the next
109: * one. If Interceptors choose not to short-circuit ActionInvocation processing and return their own return code,
110: * they will call invoke() to allow the next Interceptor to execute. If there are no more Interceptors to be applied,
111: * the Action is executed. If the ActionProxy getExecuteResult() method returns true, the Result is also executed.
112: */
113: String invoke() throws Exception;
114:
115: /**
116: * Invokes only the action (not interceptors or results). This is useful in rare situations where advanced usage
117: * with the interceptor/action/result workflow is being manipulated for certain functionality. Specifically,
118: * WebWork's execAndWait interceptor takes advantage of this method.
119: */
120: String invokeActionOnly() throws Exception;
121: }
|