diff --git a/core/src/main/java/org/apache/struts2/interceptor/validation/AnnotationValidationInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/validation/AnnotationValidationInterceptor.java index e157e9c36..a6ea8ec92 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/validation/AnnotationValidationInterceptor.java +++ b/core/src/main/java/org/apache/struts2/interceptor/validation/AnnotationValidationInterceptor.java @@ -22,8 +22,11 @@ package org.apache.struts2.interceptor.validation; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collection; +import org.apache.commons.lang.ArrayUtils; + import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.util.AnnotationUtils; import com.opensymphony.xwork2.validator.ValidationInterceptor; @@ -43,8 +46,22 @@ public class AnnotationValidationInterceptor extends ValidationInterceptor { if (action != null) { Method method = getActionMethod(action.getClass(), invocation.getProxy().getMethod()); Collection annotatedMethods = AnnotationUtils.getAnnotatedMethods(action.getClass(), SkipValidation.class); - if (annotatedMethods.contains(method)) { + if (annotatedMethods.contains(method)) return invocation.invoke(); + + //check if method overwites an annotated method + Class clazz = action.getClass().getSuperclass(); + while (clazz != null) { + annotatedMethods = AnnotationUtils.getAnnotatedMethods(clazz, SkipValidation.class); + if (annotatedMethods != null) { + for (Method annotatedMethod : annotatedMethods) { + if (annotatedMethod.getName().equals(method.getName()) + && Arrays.equals(annotatedMethod.getParameterTypes(), method.getParameterTypes()) + && Arrays.equals(annotatedMethod.getExceptionTypes(), method.getExceptionTypes())) + return invocation.invoke(); + } + } + clazz = clazz.getSuperclass(); } } diff --git a/core/src/test/java/org/apache/struts2/interceptor/validation/AnnotationValidationInterceptorTest.java b/core/src/test/java/org/apache/struts2/interceptor/validation/AnnotationValidationInterceptorTest.java index 7d54ba900..a8173aa67 100644 --- a/core/src/test/java/org/apache/struts2/interceptor/validation/AnnotationValidationInterceptorTest.java +++ b/core/src/test/java/org/apache/struts2/interceptor/validation/AnnotationValidationInterceptorTest.java @@ -67,13 +67,19 @@ public class AnnotationValidationInterceptorTest extends StrutsTestCase { mockActionProxy.verify(); } + public void testShouldSkipBase2() throws Exception { + mockActionProxy.expectAndReturn("getMethod", "skipMeBase2"); + interceptor.doIntercept((ActionInvocation)mockActionInvocation.proxy()); + mockActionProxy.verify(); + } + public void testShouldSkip2() throws Exception { mockActionProxy.expectAndReturn("getMethod", "skipMe2"); interceptor.doIntercept((ActionInvocation)mockActionInvocation.proxy()); mockActionProxy.verify(); } - public void testDontShouldSkipBase() throws Exception { + public void testShouldNotSkipBase() throws Exception { mockActionProxy.expectAndReturn("getMethod", "dontSkipMeBase"); mockActionProxy.expectAndReturn("getActionName", "foo"); mockActionProxy.expectAndReturn("getMethod", "dontSkipMeBase"); @@ -96,6 +102,10 @@ public class AnnotationValidationInterceptorTest extends StrutsTestCase { public String skipMe2() { return "skipme2"; } + + public String skipMeBase() { + return "skipme"; + } } public static class TestActionBase { @@ -105,6 +115,11 @@ public class AnnotationValidationInterceptorTest extends StrutsTestCase { return "skipme"; } + @SkipValidation + public String skipMeBase2() { + return "skipme"; + } + public String dontSkipMeBase() { return "dontskipme"; }