Author: lukaszlenart Date: Sun Jun 20 19:49:35 2010 New Revision: 956398 URL: http://svn.apache.org/viewvc?rev=956398&view=rev Log: Solved WW-2869 - Actions invoked with <s:action..> gets actionErrors copied from main action
Modified: struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java Modified: struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java?rev=956398&r1=956397&r2=956398&view=diff ============================================================================== --- struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java (original) +++ struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java Sun Jun 20 19:49:35 2010 @@ -15,7 +15,9 @@ */ package com.opensymphony.xwork2.interceptor; +import com.opensymphony.xwork2.ActionChainResult; import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.Result; import com.opensymphony.xwork2.Unchainable; import com.opensymphony.xwork2.inject.Inject; import com.opensymphony.xwork2.util.CompoundRoot; @@ -24,18 +26,23 @@ import com.opensymphony.xwork2.util.logg import com.opensymphony.xwork2.util.logging.LoggerFactory; import com.opensymphony.xwork2.util.reflection.ReflectionProvider; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; /** * <!-- START SNIPPET: description --> - * + * <p/> * An interceptor that copies all the properties of every object in the value stack to the currently executing object, * except for any object that implements {...@link Unchainable}. A collection of optional <i>includes</i> and * <i>excludes</i> may be provided to control how and which parameters are copied. Only includes or excludes may be * specified. Specifying both results in undefined behavior. See the javadocs for {...@link ReflectionProvider#copy(Object, Object, * java.util.Map, java.util.Collection, java.util.Collection)} for more information. - * + * <p/> * <p/> * <b>Note:</b> It is important to remember that this interceptor does nothing if there are no objects already on the stack. * <br/>This means two things: @@ -43,65 +50,65 @@ import java.util.*; * <br/><b/>Two</b>, it is up to you to ensure an object exists in the stack prior to invoking this action. The most typical way this is done * is through the use of the <b>chain</b> result type, which combines with this interceptor to make up the action * chaining feature. - * + * <p/> * <!-- END SNIPPET: description --> - * + * <p/> * <p/> <u>Interceptor parameters:</u> - * + * <p/> * <!-- START SNIPPET: parameters --> - * + * <p/> * <ul> - * + * <p/> * <li>excludes (optional) - the list of parameter names to exclude from copying (all others will be included).</li> - * + * <p/> * <li>includes (optional) - the list of parameter names to include when copying (all others will be excluded).</li> - * + * <p/> * </ul> - * + * <p/> * <!-- END SNIPPET: parameters --> - * + * <p/> * <p/> <u>Extending the interceptor:</u> - * * <p/> - * + * <p/> + * <p/> * <!-- START SNIPPET: extending --> - * + * <p/> * There are no known extension points to this interceptor. - * + * <p/> * <!-- END SNIPPET: extending --> - * + * <p/> * <p/> <u>Example code:</u> - * + * <p/> * <pre> * <!-- START SNIPPET: example --> - * + * <p/> * <action name="someAction" class="com.examples.SomeAction"> * <interceptor-ref name="basicStack"/> * <result name="success" type="chain">otherAction</result> * </action> - * + * <p/> * <action name="otherAction" class="com.examples.OtherAction"> * <interceptor-ref name="chain"/> * <interceptor-ref name="basicStack"/> * <result name="success">good_result.ftl</result> * </action> - * + * <p/> * <!-- END SNIPPET: example --> * </pre> * - * @see com.opensymphony.xwork2.ActionChainResult * @author mrdon * @author tm_jee ( tm_jee(at)yahoo.co.uk ) + * @see com.opensymphony.xwork2.ActionChainResult */ public class ChainingInterceptor extends AbstractInterceptor { - - private static final Logger LOG = LoggerFactory.getLogger(ChainingInterceptor.class); - + + private static final Logger LOG = LoggerFactory.getLogger(ChainingInterceptor.class); + protected Collection<String> excludes; protected Collection<String> includes; - + protected ReflectionProvider reflectionProvider; - + @Inject public void setReflectionProvider(ReflectionProvider prov) { this.reflectionProvider = prov; @@ -112,7 +119,7 @@ public class ChainingInterceptor extends ValueStack stack = invocation.getStack(); CompoundRoot root = stack.getRoot(); - if (root.size() > 1) { + if (root.size() > 1 && isChainResult(invocation)) { List<CompoundRoot> list = new ArrayList<CompoundRoot>(root); list.remove(0); Collections.reverse(list); @@ -121,22 +128,25 @@ public class ChainingInterceptor extends Iterator<CompoundRoot> iterator = list.iterator(); int index = 1; // starts with 1, 0 has been removed while (iterator.hasNext()) { - index = index + 1; + index = index + 1; Object o = iterator.next(); if (o != null) { - if (!(o instanceof Unchainable)) { - reflectionProvider.copy(o, invocation.getAction(), ctxMap, excludes, includes); - } - } - else { - LOG.warn("compound root element at index "+index+" is null"); + if (!(o instanceof Unchainable)) { + reflectionProvider.copy(o, invocation.getAction(), ctxMap, excludes, includes); + } + } else { + LOG.warn("compound root element at index " + index + " is null"); } } } - return invocation.invoke(); } - + + private boolean isChainResult(ActionInvocation invocation) throws Exception { + Result result = invocation.getResult(); + return result != null && ActionChainResult.class.isAssignableFrom(result.getClass()); + } + /** * Gets list of parameter names to exclude * @@ -149,7 +159,7 @@ public class ChainingInterceptor extends /** * Sets the list of parameter names to exclude from copying (all others will be included). * - * @param excludes the excludes list + * @param excludes the excludes list */ public void setExcludes(Collection<String> excludes) { this.excludes = excludes; @@ -167,7 +177,7 @@ public class ChainingInterceptor extends /** * Sets the list of parameter names to include when copying (all others will be excluded). * - * @param includes the includes list + * @param includes the includes list */ public void setIncludes(Collection<String> includes) { this.includes = includes; Modified: struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java?rev=956398&r1=956397&r2=956398&view=diff ============================================================================== --- struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java (original) +++ struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ChainingInterceptorTest.java Sun Jun 20 19:49:35 2010 @@ -126,6 +126,7 @@ public class ChainingInterceptorTest ext mockInvocation.expectAndReturn("getStack", stack); mockInvocation.expectAndReturn("invoke", Action.SUCCESS); mockInvocation.expectAndReturn("getInvocationContext", new ActionContext(new HashMap())); + mockInvocation.expectAndReturn("getResult", new ActionChainResult()); invocation = (ActionInvocation) mockInvocation.proxy(); interceptor = new ChainingInterceptor(); container.inject(interceptor);