Author: lukaszlenart
Date: Wed May 22 11:10:29 2013
New Revision: 1485149
URL: http://svn.apache.org/r1485149
Log:
WW-4071 Adds new ValidationErrorAware interface to allow notify action about
action/field errors
Added:
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ValidationErrorAware.java
struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationErrorAwareTest.java
Modified:
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java
Modified:
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java?rev=1485149&r1=1485148&r2=1485149&view=diff
==============================================================================
---
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java
(original)
+++
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java
Wed May 22 11:10:29 2013
@@ -71,14 +71,14 @@ import java.lang.reflect.Method;
* <p/>
* <pre>
* <!-- START SNIPPET: example -->
- * <p/>
+ *
* <action name="someAction" class="com.examples.SomeAction">
* <interceptor-ref name="params"/>
* <interceptor-ref name="validation"/>
* <interceptor-ref name="workflow"/>
* <result name="success">good_result.ftl</result>
* </action>
- * <p/>
+ *
* <-- In this case myMethod as well as mySecondMethod of the action class
* will not pass through the workflow process -->
* <action name="someAction" class="com.examples.SomeAction">
@@ -89,7 +89,7 @@ import java.lang.reflect.Method;
* </interceptor-ref name="workflow">
* <result name="success">good_result.ftl</result>
* </action>
- * <p/>
+ *
* <-- In this case, the result named "error" will be used when
* an action / field error is found -->
* <-- The Interceptor will only be applied for myWorkflowMethod method of
action
@@ -104,7 +104,7 @@ import java.lang.reflect.Method;
* </interceptor-ref>
* <result name="success">good_result.ftl</result>
* </action>
- * <p/>
+ *
* <!-- END SNIPPET: example -->
* </pre>
*
@@ -121,7 +121,7 @@ public class DefaultWorkflowInterceptor
private static final Logger LOG =
LoggerFactory.getLogger(DefaultWorkflowInterceptor.class);
private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
-
+
private String inputResultName = Action.INPUT;
/**
@@ -149,31 +149,73 @@ public class DefaultWorkflowInterceptor
if (validationAwareAction.hasErrors()) {
if (LOG.isDebugEnabled()) {
- LOG.debug("Errors on action " + validationAwareAction + ",
returning result name 'input'");
+ LOG.debug("Errors on action [#0], returning result name
[#1]", validationAwareAction, inputResultName);
}
String resultName = inputResultName;
+ resultName = processValidationWorkflowAware(action,
resultName);
+ resultName = processInputConfig(action,
invocation.getProxy().getMethod(), resultName);
+ resultName = processValidationErrorAware(action, resultName);
- if (action instanceof ValidationWorkflowAware) {
- resultName = ((ValidationWorkflowAware)
action).getInputResultName();
- }
+ return resultName;
+ }
+ }
- InputConfig annotation =
action.getClass().getMethod(invocation.getProxy().getMethod(),
EMPTY_CLASS_ARRAY).getAnnotation(InputConfig.class);
- if (annotation != null) {
- if (!annotation.methodName().equals("")) {
- Method method =
action.getClass().getMethod(annotation.methodName());
- resultName = (String) method.invoke(action);
- } else {
- resultName = annotation.resultName();
- }
- }
+ return invocation.invoke();
+ }
+ /**
+ * Process {@link ValidationWorkflowAware} interface
+ */
+ private String processValidationWorkflowAware(final Object action, final
String currentResultName) {
+ String resultName = currentResultName;
+ if (action instanceof ValidationWorkflowAware) {
+ resultName = ((ValidationWorkflowAware)
action).getInputResultName();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Changing result name from [#0] to [#1] because of
processing [#2] interface applied to [#3]",
+ currentResultName, resultName,
InputConfig.class.getSimpleName(),
ValidationWorkflowAware.class.getSimpleName(), action);
+ }
+ }
+ return resultName;
+ }
- return resultName;
+ /**
+ * Process {@link InputConfig} annotation applied to method
+ */
+ protected String processInputConfig(final Object action, final String
method, final String currentResultName) throws Exception {
+ String resultName = currentResultName;
+ InputConfig annotation = action.getClass().getMethod(method,
EMPTY_CLASS_ARRAY).getAnnotation(InputConfig.class);
+ if (annotation != null) {
+ if (!annotation.methodName().equals("")) {
+ Method m =
action.getClass().getMethod(annotation.methodName());
+ resultName = (String) m.invoke(action);
+ } else {
+ resultName = annotation.resultName();
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Changing result name from [#0] to [#1] because of
processing annotation [#2] on action [#3]",
+ currentResultName, resultName,
InputConfig.class.getSimpleName(), action);
}
}
+ return resultName;
+ }
- return invocation.invoke();
+ /**
+ * Notify action if it implements {@see ValidationErrorAware} interface
+ */
+ protected String processValidationErrorAware(final Object action, final
String currentResultName) {
+ String resultName = currentResultName;
+ if (action instanceof ValidationErrorAware) {
+ String validationErrorAwareResult = ((ValidationErrorAware)
action).actionErrorOccurred();
+ if (validationErrorAwareResult != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Changing result name from [#0] to [#1] because
of processing interface [#2] on action [#3]",
+ currentResultName, resultName,
ValidationErrorAware.class.getSimpleName(), action);
+ }
+ resultName = validationErrorAwareResult;
+ }
+ }
+ return resultName;
}
}
Added:
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ValidationErrorAware.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ValidationErrorAware.java?rev=1485149&view=auto
==============================================================================
---
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ValidationErrorAware.java
(added)
+++
struts/struts2/trunk/xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ValidationErrorAware.java
Wed May 22 11:10:29 2013
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2007,2009 The Apache Software Foundation.
+ *
+ * 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 com.opensymphony.xwork2.interceptor;
+
+/**
+ * ValidationErrorAware classes can be notified about validation errors
+ * before {@link
com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor} will return
'inputResultName' result
+ * to allow change or not the result name
+ *
+ * This interface can be only applied to action which already implements
{@link com.opensymphony.xwork2.ValidationAware} interface!
+ *
+ * @since 2.3.15
+ */
+public interface ValidationErrorAware {
+
+ /**
+ * Allows to notify action about occurred action/field errors
+ *
+ * @return new result name or null to keep result of {@link
com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor}
+ */
+ String actionErrorOccurred();
+
+}
Added:
struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationErrorAwareTest.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationErrorAwareTest.java?rev=1485149&view=auto
==============================================================================
---
struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationErrorAwareTest.java
(added)
+++
struts/struts2/trunk/xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ValidationErrorAwareTest.java
Wed May 22 11:10:29 2013
@@ -0,0 +1,103 @@
+package com.opensymphony.xwork2.interceptor;
+
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ActionProxy;
+import com.opensymphony.xwork2.ObjectFactory;
+import com.opensymphony.xwork2.Validateable;
+import com.opensymphony.xwork2.ValidationAware;
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.config.entities.InterceptorConfig;
+import com.opensymphony.xwork2.validator.ValidationInterceptor;
+import junit.framework.Assert;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+
+import java.util.HashMap;
+
+public class ValidationErrorAwareTest extends XWorkTestCase {
+
+ private DefaultWorkflowInterceptor interceptor;
+ private ActionInvocation invocation;
+ private String result = "testing123";
+ private String actionResult = "action1234";
+
+ public void testChangeResultWhenNotifyAboutValidationErrors() throws
Exception {
+ // given
+ ValidationInterceptor validationInterceptor = create();
+
+ // when
+ validationInterceptor.intercept(invocation);
+
+ // then
+ assertEquals(actionResult, interceptor.intercept(invocation));
+ }
+
+ public void testNotChangeResultWhenNotifyAboutValidationError() throws
Exception {
+ // given
+ actionResult = null;
+ ValidationInterceptor validationInterceptor = create();
+
+ // when
+ validationInterceptor.intercept(invocation);
+
+ // then
+ Assert.assertEquals(Action.INPUT, interceptor.intercept(invocation));
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ ActionConfig config = new ActionConfig.Builder("", "name", "").build();
+ ValidateErrorAction action =
EasyMock.createNiceMock(ValidateErrorAction.class);
+ invocation = EasyMock.createNiceMock(ActionInvocation.class);
+ interceptor = new DefaultWorkflowInterceptor();
+ ActionProxy proxy = EasyMock.createNiceMock(ActionProxy.class);
+
+ EasyMock.expect(action.actionErrorOccurred()).andAnswer(new
IAnswer<String>() {
+ public String answer() throws Throwable {
+ return actionResult;
+ }
+ }).anyTimes();
+ EasyMock.expect(action.hasErrors()).andReturn(true).anyTimes();
+
+ EasyMock.expect(invocation.getProxy()).andReturn(proxy).anyTimes();
+ EasyMock.expect(invocation.getAction()).andReturn(action).anyTimes();
+ EasyMock.expect(invocation.invoke()).andAnswer(new IAnswer<String>() {
+ public String answer() throws Throwable {
+ return result;
+ }
+ }).anyTimes();
+
+ EasyMock.expect(proxy.getConfig()).andReturn(config).anyTimes();
+ EasyMock.expect(proxy.getMethod()).andReturn("execute").anyTimes();
+
+
+ EasyMock.replay(invocation);
+ EasyMock.replay(action);
+ EasyMock.replay(proxy);
+
+ ActionContext contex = new ActionContext(new HashMap<String,
Object>());
+ ActionContext.setContext(contex);
+ contex.setActionInvocation(invocation);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ protected ValidationInterceptor create() {
+ ObjectFactory objectFactory =
container.getInstance(ObjectFactory.class);
+ return (ValidationInterceptor) objectFactory.buildInterceptor(
+ new InterceptorConfig.Builder("model",
ValidationInterceptor.class.getName()).build(), new HashMap<String, String>());
+ }
+
+ private interface ValidateErrorAction extends Action, Validateable,
ValidationAware, ValidationErrorAware {
+
+ String execute();
+
+ }
+}