You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2021/09/27 10:21:51 UTC

[struts] 01/01: WW-5143 WW-5142 Upgrades OVal to ver. 3.2.1 and upgrades XStream to ver 1.4.18

This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5142-oval
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 8ab65d79ef0ca2baec359608f5180a6ea54fcb71
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Mon Sep 27 12:21:43 2021 +0200

    WW-5143 WW-5142 Upgrades OVal to ver. 3.2.1 and upgrades XStream to ver 1.4.18
---
 .../interceptor/DefaultOValValidationManager.java  |  35 ++--
 .../interceptor/OValValidationInterceptor.java     | 188 +++++++++++++--------
 .../oval/interceptor/OValValidationManager.java    |   2 +-
 .../oval/interceptor/ModelDrivenAction.java        |   4 +-
 .../interceptor/OValValidationInterceptorTest.java |  43 ++---
 pom.xml                                            |   4 +-
 6 files changed, 146 insertions(+), 130 deletions(-)

diff --git a/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/DefaultOValValidationManager.java b/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/DefaultOValValidationManager.java
index 4af986c..7b396b9 100644
--- a/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/DefaultOValValidationManager.java
+++ b/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/DefaultOValValidationManager.java
@@ -48,8 +48,8 @@ public class DefaultOValValidationManager implements OValValidationManager {
     private static final Logger LOG = LogManager.getLogger(DefaultOValValidationManager.class);
 
     protected static final String VALIDATION_CONFIG_SUFFIX = "-validation.xml";
-    protected final Map<String, List<Configurer>> validatorCache = new HashMap<String, List<Configurer>>();
-    protected final Map<String, Configurer> validatorFileCache = new HashMap<String, Configurer>();
+    protected final Map<String, List<Configurer>> validatorCache = new HashMap<>();
+    protected final Map<String, Configurer> validatorFileCache = new HashMap<>();
 
     protected boolean validateJPAAnnotations;
 
@@ -66,7 +66,7 @@ public class DefaultOValValidationManager implements OValValidationManager {
         this.fileManager = fileManagerFactory.getFileManager();
     }
 
-    public synchronized List<Configurer> getConfigurers(Class clazz, String context, boolean validateJPAAnnotations) {
+    public synchronized List<Configurer> getConfigurers(Class<?> clazz, String context, boolean validateJPAAnnotations) {
         this.validateJPAAnnotations =validateJPAAnnotations;
         final String validatorKey = buildValidatorKey(clazz, context);
 
@@ -75,14 +75,14 @@ public class DefaultOValValidationManager implements OValValidationManager {
                 List<Configurer> configurers = buildXMLConfigurers(clazz, context, true, null);
 
                 //add an annotation configurer
-                addAditionalConfigurers(configurers);
+                addAdditionalConfigurers(configurers);
                 validatorCache.put(validatorKey, configurers);
             }
         } else {
             List<Configurer> configurers = buildXMLConfigurers(clazz, context, false, null);
 
             //add an annotation configurer
-            addAditionalConfigurers(configurers);
+            addAdditionalConfigurers(configurers);
             validatorCache.put(validatorKey, configurers);
         }
 
@@ -90,7 +90,7 @@ public class DefaultOValValidationManager implements OValValidationManager {
         return validatorCache.get(validatorKey);
     }
 
-    private void addAditionalConfigurers(List<Configurer> configurers) {
+    private void addAdditionalConfigurers(List<Configurer> configurers) {
         AnnotationsConfigurer annotationsConfigurer = new AnnotationsConfigurer();
         configurers.add(annotationsConfigurer);
 
@@ -102,24 +102,21 @@ public class DefaultOValValidationManager implements OValValidationManager {
         }
     }
 
-    protected static String buildValidatorKey(Class clazz, String context) {
-        StringBuilder sb = new StringBuilder(clazz.getName());
-        sb.append("/");
-        sb.append(context);
-        return sb.toString();
+    protected static String buildValidatorKey(Class<?> clazz, String context) {
+        return clazz.getName() + "/" + context;
     }
 
-    private List<Configurer> buildXMLConfigurers(Class clazz, String context, boolean checkFile, Set<String> checked) {
-        List<Configurer> configurers = new ArrayList<Configurer>();
+    private List<Configurer> buildXMLConfigurers(Class<?> clazz, String context, boolean checkFile, Set<String> checked) {
+        List<Configurer> configurers = new ArrayList<>();
 
         if (checked == null) {
-            checked = new TreeSet<String>();
+            checked = new TreeSet<>();
         } else if (checked.contains(clazz.getName())) {
             return configurers;
         }
 
         if (clazz.isInterface()) {
-            for (Class anInterface : clazz.getInterfaces()) {
+            for (Class<?> anInterface : clazz.getInterfaces()) {
                 configurers.addAll(buildXMLConfigurers(anInterface, context, checkFile, checked));
             }
         } else {
@@ -129,7 +126,7 @@ public class DefaultOValValidationManager implements OValValidationManager {
         }
 
         // look for validators for implemented interfaces
-        for (Class anInterface1 : clazz.getInterfaces()) {
+        for (Class<?> anInterface1 : clazz.getInterfaces()) {
             if (checked.contains(anInterface1.getName())) {
                 continue;
             }
@@ -160,19 +157,19 @@ public class DefaultOValValidationManager implements OValValidationManager {
     }
 
 
-    protected XMLConfigurer buildAliasValidatorConfigs(Class aClass, String context, boolean checkFile) {
+    protected XMLConfigurer buildAliasValidatorConfigs(Class<?> aClass, String context, boolean checkFile) {
         String fileName = aClass.getName().replace('.', '/') + "-" + context + VALIDATION_CONFIG_SUFFIX;
 
         return loadFile(fileName, aClass, checkFile);
     }
 
-    protected XMLConfigurer buildClassValidatorConfigs(Class aClass, boolean checkFile) {
+    protected XMLConfigurer buildClassValidatorConfigs(Class<?> aClass, boolean checkFile) {
         String fileName = aClass.getName().replace('.', '/') + VALIDATION_CONFIG_SUFFIX;
 
         return loadFile(fileName, aClass, checkFile);
     }
 
-    protected XMLConfigurer loadFile(String fileName, Class clazz, boolean checkFile) {
+    protected XMLConfigurer loadFile(String fileName, Class<?> clazz, boolean checkFile) {
         URL fileUrl = ClassLoaderUtil.getResource(fileName, clazz);
         if ((checkFile && fileManager.fileNeedsReloading(fileUrl)) || !validatorFileCache.containsKey(fileName)) {
 
diff --git a/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/OValValidationInterceptor.java b/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/OValValidationInterceptor.java
index 58f1fd2..0bb2bba 100644
--- a/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/OValValidationInterceptor.java
+++ b/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/OValValidationInterceptor.java
@@ -28,22 +28,26 @@ import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
 import com.opensymphony.xwork2.interceptor.PrefixMethodInvocationUtil;
 import com.opensymphony.xwork2.util.ValueStack;
-import net.sf.oval.exception.ExpressionEvaluationException;
-import net.sf.oval.expression.ExpressionLanguage;
-import net.sf.oval.expression.ExpressionLanguageOGNLImpl;
-import ognl.Ognl;
-import ognl.OgnlException;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.LogManager;
 import com.opensymphony.xwork2.validator.DelegatingValidatorContext;
 import com.opensymphony.xwork2.validator.ValidatorContext;
 import net.sf.oval.ConstraintViolation;
 import net.sf.oval.Validator;
 import net.sf.oval.configuration.Configurer;
 import net.sf.oval.context.FieldContext;
+import net.sf.oval.context.IterableElementContext;
+import net.sf.oval.context.MapKeyContext;
+import net.sf.oval.context.MapValueContext;
 import net.sf.oval.context.MethodReturnValueContext;
 import net.sf.oval.context.OValContext;
+import net.sf.oval.exception.ExpressionEvaluationException;
+import net.sf.oval.expression.ExpressionLanguage;
+import net.sf.oval.expression.ExpressionLanguageOGNLImpl;
+import net.sf.oval.localization.context.OValContextRenderer;
+import ognl.Ognl;
+import ognl.OgnlException;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.apache.struts2.oval.annotation.Profiles;
 
 import java.lang.reflect.Field;
@@ -54,7 +58,7 @@ import java.util.Map;
 /*
  This interceptor provides validation using the OVal validation framework
  */
-public class OValValidationInterceptor extends MethodFilterInterceptor {
+public class OValValidationInterceptor extends MethodFilterInterceptor implements MethodNameExtractor {
 
     public static final String STRUTS_OVAL_VALIDATE_JPAANNOTATIONS = "struts.oval.validateJPAAnnotations";
 
@@ -69,10 +73,11 @@ public class OValValidationInterceptor extends MethodFilterInterceptor {
     protected boolean validateJPAAnnotations;
     protected TextProviderFactory textProviderFactory;
 
-    private ExpressionLanguage ognlExpressionLanguage;
+    private final ExpressionLanguage ognlExpressionLanguage;
 
     public OValValidationInterceptor() {
         ognlExpressionLanguage = new ExpressionLanguageOGNL();
+        Validator.setContextRenderer(new StrutsContextRenderer());
     }
 
     @Inject
@@ -143,8 +148,8 @@ public class OValValidationInterceptor extends MethodFilterInterceptor {
 
             try {
                 PrefixMethodInvocationUtil.invokePrefixMethod(
-                        invocation,
-                        new String[]{VALIDATE_PREFIX, ALT_VALIDATE_PREFIX});
+                    invocation,
+                    new String[]{VALIDATE_PREFIX, ALT_VALIDATE_PREFIX});
             } catch (Exception e) {
                 // If any exception occurred while doing reflection, we want
                 // validate() to be executed
@@ -164,7 +169,7 @@ public class OValValidationInterceptor extends MethodFilterInterceptor {
     }
 
     protected void performOValValidation(Object action, ValueStack valueStack, String methodName, String context) throws NoSuchMethodException {
-        Class clazz = action.getClass();
+        Class<?> clazz = action.getClass();
         //read validation from xmls
         List<Configurer> configurers = validationManager.getConfigurers(clazz, context, validateJPAAnnotations);
 
@@ -172,33 +177,31 @@ public class OValValidationInterceptor extends MethodFilterInterceptor {
         // Note: For Oval <= 1.70, API requires "validator.addExpressionLanguage("ognl", ognlExpressionLanguage)".
         validator.getExpressionLanguageRegistry().registerExpressionLanguage("ognl", ognlExpressionLanguage);  // Usage for Oval >= 1.80 due to API changes
         //if the method is annotated with a @Profiles annotation, use those profiles
-        Method method = clazz.getMethod(methodName, new Class[0]);
-        if (method != null) {
-            Profiles profiles = method.getAnnotation(Profiles.class);
-            if (profiles != null) {
-                String[] profileNames = profiles.value();
-                if (profileNames != null && profileNames.length > 0) {
-                    validator.disableAllProfiles();
-                    LOG.debug("Enabling profiles [{}]", StringUtils.join(profileNames, ","));
-                    for (String profileName : profileNames)
-                        validator.enableProfile(profileName);
-                }
+        Method method = clazz.getMethod(methodName);
+        Profiles profiles = method.getAnnotation(Profiles.class);
+        if (profiles != null) {
+            String[] profileNames = profiles.value();
+            if (profileNames != null && profileNames.length > 0) {
+                validator.disableAllProfiles();
+                LOG.debug("Enabling profiles [{}]", StringUtils.join(profileNames, ","));
+                for (String profileName : profileNames)
+                    validator.enableProfile(profileName);
             }
         }
 
         //perform validation
         List<ConstraintViolation> violations = validator.validate(action);
-        addValidationErrors(violations.toArray(new ConstraintViolation[violations.size()]), action, valueStack, null);
+        addValidationErrors(violations.toArray(new ConstraintViolation[0]), action, valueStack, null);
     }
 
-	private void addValidationErrors(ConstraintViolation[] violations, Object action, ValueStack valueStack, String parentFieldname) {
-		if (violations != null) {
+    private void addValidationErrors(ConstraintViolation[] violations, Object action, ValueStack valueStack, String parentFieldname) {
+        if (violations != null) {
             ValidatorContext validatorContext = new DelegatingValidatorContext(action, textProviderFactory);
             for (ConstraintViolation violation : violations) {
                 //translate message
                 String key = violation.getMessage();
 
-                String message = key;
+                String message;
                 // push context variable into stack, to allow use ${max}, ${min} etc in error messages
                 valueStack.push(violation.getMessageVariables());
                 //push the validator into the stack
@@ -211,71 +214,65 @@ public class OValValidationInterceptor extends MethodFilterInterceptor {
                 }
 
                 if (isActionError(violation)) {
-                	LOG.debug("Adding action error '{}'", message);
+                    LOG.debug("Adding action error '{}'", message);
                     validatorContext.addActionError(message);
                 } else {
-                    ValidationError validationError = buildValidationError(violation, message);
+                    ValidationError validationError = buildValidationError(violation.getContextPath(), message);
 
                     // build field name
                     String fieldName = validationError.getFieldName();
                     if (parentFieldname != null) {
-                    	fieldName = parentFieldname + "." + fieldName;
+                        fieldName = parentFieldname + "." + fieldName;
                     }
 
-                	LOG.debug("Adding field error [{}] with message '{}'", fieldName, validationError.getMessage());
+                    LOG.debug("Adding field error [{}] with message '{}'", fieldName, validationError.getMessage());
                     validatorContext.addFieldError(fieldName, validationError.getMessage());
 
-                    // don't add "model." prefix to fields of model in model driven action
-                    if ((action instanceof ModelDriven) && "model".equals(fieldName)) {
-                    	fieldName = null;
-                    }
-
                     // add violations of member object fields
                     addValidationErrors(violation.getCauses(), action, valueStack, fieldName);
                 }
             }
         }
-	}
-
-
+    }
 
 
     /**
      * Get field name and message, used to add the validation error to fieldErrors
      */
-    protected ValidationError buildValidationError(ConstraintViolation violation, String message) {
-        OValContext context = violation.getContext();
-        if (context instanceof FieldContext) {
-            Field field = ((FieldContext) context).getField();
-            String className = field.getDeclaringClass().getName();
-
-            //the default OVal message shows the field name as ActionClass.fieldName
-            String finalMessage = StringUtils.removeStart(message, className + ".");
-
-            return new ValidationError(field.getName(), finalMessage);
-        } else if (context instanceof MethodReturnValueContext) {
-            Method method = ((MethodReturnValueContext) context).getMethod();
-            String className = method.getDeclaringClass().getName();
-            String methodName = method.getName();
-
-            //the default OVal message shows the field name as ActionClass.fieldName
-            String finalMessage = StringUtils.removeStart(message, className + ".");
-
-            String fieldName = null;
-            if (methodName.startsWith("get")) {
-                fieldName = StringUtils.uncapitalize(StringUtils.removeStart(methodName, "get"));
-            } else if (methodName.startsWith("is")) {
-                fieldName = StringUtils.uncapitalize(StringUtils.removeStart(methodName, "is"));
+    protected ValidationError buildValidationError(List<OValContext> contextPath, String message) {
+        StringBuilder fieldName = new StringBuilder();
+        String finalMessage = message;
+        for (OValContext context : contextPath) {
+            if (fieldName.length() > 0) {
+                fieldName.append(".");
             }
 
-            //the result will have the full method name, like "getName()", replace it by "name" (obnly if it is a field)
-            if (fieldName != null)
-                finalMessage = finalMessage.replaceAll(methodName + "\\(.*?\\)", fieldName);
-
-            return new ValidationError(StringUtils.defaultString(fieldName, methodName), finalMessage);
+            if (context instanceof FieldContext) {
+                Field field = ((FieldContext) context).getField();
+                String className = field.getDeclaringClass().getName();
+
+                //the default OVal message shows the field name as ActionClass.fieldName
+                finalMessage = StringUtils.removeStart(finalMessage, className + ".");
+                fieldName.append(field.getName());
+            } else if (context instanceof MethodReturnValueContext) {
+                Method method = ((MethodReturnValueContext) context).getMethod();
+                String className = method.getDeclaringClass().getName();
+                String methodName = method.getName();
+
+                //the default OVal message shows the field name as ActionClass.fieldName
+                finalMessage = StringUtils.removeStart(message, className + ".");
+                fieldName.append(extractName(method));
+
+                //the result will have the full method name, like "getName()", replace it by "name" (obnly if it is a field)
+                if (fieldName.length() == 0) {
+                    finalMessage = finalMessage.replaceAll(methodName + "\\(.*?\\)", fieldName.toString());
+                }
+            } else {
+                fieldName.append(context.toStringUnqualified());
+            }
         }
 
-        return new ValidationError(violation.getCheckName(), message);
+        return new ValidationError(fieldName.toString(), message);
     }
 
     /**
@@ -285,9 +282,9 @@ public class OValValidationInterceptor extends MethodFilterInterceptor {
         return false;
     }
 
-    class ValidationError {
-        private String fieldName;
-        private String message;
+    static class ValidationError {
+        private final String fieldName;
+        private final String message;
 
         ValidationError(String fieldName, String message) {
             this.fieldName = fieldName;
@@ -309,9 +306,9 @@ class ExpressionLanguageOGNL extends ExpressionLanguageOGNLImpl {
 
     private static final Logger LOG = LogManager.getLogger(ExpressionLanguageOGNL.class);
 
-    public Object evaluate(final String expression, final Map<String, ? > values) throws ExpressionEvaluationException {
+    public Object evaluate(final String expression, final Map<String, ?> values) throws ExpressionEvaluationException {
         try {
-            LOG.debug("Evaluating OGNL expression: {1}", expression);
+            LOG.debug("Evaluating OGNL expression: {}", expression);
             return Ognl.getValue(expression, ActionContext.getContext().getContextMap(), values);
         } catch (final OgnlException ex) {
             throw new ExpressionEvaluationException("Evaluating script with OGNL failed.", ex);
@@ -319,3 +316,48 @@ class ExpressionLanguageOGNL extends ExpressionLanguageOGNLImpl {
     }
 }
 
+class StrutsContextRenderer implements OValContextRenderer, MethodNameExtractor {
+
+    @Override
+    public String render(final OValContext context) {
+        return context.toStringUnqualified();
+    }
+
+    @Override
+    public String render(List<OValContext> contextPath) {
+        final StringBuilder sb = new StringBuilder(3 * contextPath.size());
+        boolean isFirst = true;
+        for (final OValContext ctx : contextPath) {
+            final boolean isContainerElementContext = ctx instanceof IterableElementContext || ctx instanceof MapKeyContext || ctx instanceof MapValueContext;
+            if (isFirst) {
+                isFirst = false;
+            } else if (isContainerElementContext) {
+                // do nothing special
+            } else {
+                sb.append('.');
+            }
+
+            if (ctx instanceof MethodReturnValueContext) {
+                sb.append(extractName(((MethodReturnValueContext) ctx).getMethod()));
+            } else {
+                sb.append(render(ctx));
+            }
+        }
+        return sb.toString();
+    }
+
+}
+
+interface MethodNameExtractor {
+
+    default String extractName(Method method) {
+        String methodName = method.getName();
+        if (methodName.startsWith("get")) {
+            return StringUtils.uncapitalize(StringUtils.removeStart(methodName, "get"));
+        } else if (methodName.startsWith("is")) {
+            return StringUtils.uncapitalize(StringUtils.removeStart(methodName, "is"));
+        }
+        return methodName;
+    }
+
+}
diff --git a/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/OValValidationManager.java b/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/OValValidationManager.java
index a3a6d69..0b3fd03 100644
--- a/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/OValValidationManager.java
+++ b/plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/OValValidationManager.java
@@ -63,5 +63,5 @@ public interface OValValidationManager {
      *                  updated.
      * @return a list of xml configurers for the given class and context.
      */
-    List<Configurer> getConfigurers(Class clazz, String context, boolean validateJPAAnnotations);
+    List<Configurer> getConfigurers(Class<?> clazz, String context, boolean validateJPAAnnotations);
 }
diff --git a/plugins/oval/src/test/java/org/apache/struts2/oval/interceptor/ModelDrivenAction.java b/plugins/oval/src/test/java/org/apache/struts2/oval/interceptor/ModelDrivenAction.java
index a64cd2b..c4b7a2e 100644
--- a/plugins/oval/src/test/java/org/apache/struts2/oval/interceptor/ModelDrivenAction.java
+++ b/plugins/oval/src/test/java/org/apache/struts2/oval/interceptor/ModelDrivenAction.java
@@ -28,10 +28,10 @@ import com.opensymphony.xwork2.ModelDriven;
 public class ModelDrivenAction extends ActionSupport implements ModelDriven<Person> {
 
 	@AssertValid
-	private Person model = new Person();
+	private Person person = new Person();
 
 	public Person getModel() {
-		return model;
+		return person;
 	}
 
 }
diff --git a/plugins/oval/src/test/java/org/apache/struts2/oval/interceptor/OValValidationInterceptorTest.java b/plugins/oval/src/test/java/org/apache/struts2/oval/interceptor/OValValidationInterceptorTest.java
index cf0f840..3a88c51 100644
--- a/plugins/oval/src/test/java/org/apache/struts2/oval/interceptor/OValValidationInterceptorTest.java
+++ b/plugins/oval/src/test/java/org/apache/struts2/oval/interceptor/OValValidationInterceptorTest.java
@@ -21,7 +21,6 @@ package org.apache.struts2.oval.interceptor;
 import com.opensymphony.xwork2.ActionProxy;
 import com.opensymphony.xwork2.XWorkTestCase;
 import com.opensymphony.xwork2.interceptor.ValidationAware;
-import junit.framework.AssertionFailedError;
 import net.sf.oval.configuration.Configurer;
 import org.apache.struts2.config.StrutsXmlConfigurationProvider;
 
@@ -59,7 +58,7 @@ public class OValValidationInterceptorTest extends XWorkTestCase {
         assertNotNull(fieldErrors);
         assertEquals(4, fieldErrors.size());
         assertValue(fieldErrors, "name", Arrays.asList("name cannot be null"));
-        assertValue(fieldErrors, "SisyphusHasTheAnswer", Arrays.asList("SisyphusHasTheAnswer() cannot be null"));
+        assertValue(fieldErrors, "SisyphusHasTheAnswer", Arrays.asList("SisyphusHasTheAnswer cannot be null"));
         assertValue(fieldErrors, "thereAnyMeaningInLife", Arrays.asList("thereAnyMeaningInLife cannot be null"));
         assertValue(fieldErrors, "theManingOfLife", Arrays.asList("theManingOfLife cannot be null"));
     }
@@ -281,21 +280,10 @@ public class OValValidationInterceptorTest extends XWorkTestCase {
 
         Map<String, List<String>> fieldErrors = ((ValidationAware) baseActionProxy.getAction()).getFieldErrors();
         assertNotNull(fieldErrors);
-        assertEquals(5, fieldErrors.size()); // 5: as there will be field errors for 'model' and 'address' themselves
-        assertValue(fieldErrors, "name", Arrays.asList("name cannot be null"));
-        assertValue(fieldErrors, "email", Arrays.asList("email cannot be null"));
-        try {
-            // Oval version <= 1.40 validation error for invalid data reports: "net.sf.oval.constraint.AssertValid.violated".
-            assertValue(fieldErrors, "address", Arrays.asList("net.sf.oval.constraint.AssertValid.violated"));
-            // Oval version <= 1.40 validation error for minimum length reports: "street cannot be smaller than 7 characters".
-            assertValue(fieldErrors, "address.street", Arrays.asList("street cannot be smaller than 7 characters"));
-        } catch (AssertionFailedError afe) {
-            // Oval version >= 1.50 validation error for invalid data reports: "address is invalid".
-            assertValue(fieldErrors, "address", Arrays.asList("address is invalid"));
-            // Oval version >= 1.50 validation error for minimum length reports: "street cannot be shorter than 7 characters".
-            assertValue(fieldErrors, "address.street", Arrays.asList("street cannot be shorter than 7 characters"));
-        }
-
+        assertEquals(3, fieldErrors.size()); // 5: as there will be field errors for 'model' and 'address' themselves
+        assertValue(fieldErrors, "person.name", Arrays.asList("person.name cannot be null"));
+        assertValue(fieldErrors, "person.email", Arrays.asList("person.email cannot be null"));
+        assertValue(fieldErrors, "person.address.street", Arrays.asList("person.address.street cannot be shorter than 7 characters"));
     }
 
     public void testMemberObject() throws Exception {
@@ -308,24 +296,12 @@ public class OValValidationInterceptorTest extends XWorkTestCase {
 
         Map<String, List<String>> fieldErrors = ((ValidationAware) baseActionProxy.getAction()).getFieldErrors();
         assertNotNull(fieldErrors);
-        assertEquals(5, fieldErrors.size()); // 5: as there will be field errors for 'person' and 'person.address' themselves
-        assertValue(fieldErrors, "person.name", Arrays.asList("name cannot be null"));
-        assertValue(fieldErrors, "person.email", Arrays.asList("email cannot be null"));
-        try {
-            // Oval version <= 1.40 validation error for invalid data reports: "net.sf.oval.constraint.AssertValid.violated".
-            assertValue(fieldErrors, "person.address", Arrays.asList("net.sf.oval.constraint.AssertValid.violated"));
-            // Oval version <= 1.40 validation error for minimum length reports: "street cannot be smaller than 7 characters".
-            assertValue(fieldErrors, "person.address.street", Arrays.asList("street cannot be smaller than 7 characters"));
-        } catch (AssertionFailedError afe) {
-            // Oval version >= 1.50 validation error for invalid data reports: "address is invalid".
-            assertValue(fieldErrors, "person.address", Arrays.asList("address is invalid"));
-            // Oval version >= 1.50 validation error for minimum length reports: "street cannot be shorter than 7 characters".
-            assertValue(fieldErrors, "person.address.street", Arrays.asList("street cannot be shorter than 7 characters"));
-        }
-
+        assertEquals(3, fieldErrors.size()); // 5: as there will be field errors for 'person' and 'person.address' themselves
+        assertValue(fieldErrors, "person.name", Arrays.asList("person.name cannot be null"));
+        assertValue(fieldErrors, "person.email", Arrays.asList("person.email cannot be null"));
+        assertValue(fieldErrors, "person.address.street", Arrays.asList("person.address.street cannot be shorter than 7 characters"));
     }
 
-
     private void assertValue(Map<String, List<String>> map, String key, List<String> expectedValues) {
         assertNotNull(map);
         assertNotNull(key);
@@ -341,4 +317,5 @@ public class OValValidationInterceptorTest extends XWorkTestCase {
         super.setUp();
         loadConfigurationProviders(new StrutsXmlConfigurationProvider("oval-test.xml"));
     }
+
 }
diff --git a/pom.xml b/pom.xml
index 7dff37b..2f6efd6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1115,13 +1115,13 @@
             <dependency>
                 <groupId>net.sf.oval</groupId>
                 <artifactId>oval</artifactId>
-                <version>1.90</version>
+                <version>3.2.1</version>
             </dependency>
 
             <dependency>
                 <groupId>com.thoughtworks.xstream</groupId>
                 <artifactId>xstream</artifactId>
-                <version>1.4.17</version>
+                <version>1.4.18</version>
                 <exclusions>
                     <exclusion>
                         <groupId>io.github.x-stream</groupId>