Commits

Anonymous committed 83cda5a

XW-99: Validators now use ValueStack to find values, alleviating the problem where ModelDriven Actions would have to have different field names in validations and form fields (which would cause error messages not to show up).

git-svn-id: http://svn.opensymphony.com/svn/xwork/trunk/src@59e221344d-f017-0410-9bd5-d282ab1896d7

Comments (0)

Files changed (9)

java/com/opensymphony/xwork/util/OgnlValueStack.java

 
 import java.io.ObjectStreamException;
 import java.io.Serializable;
+
 import java.util.Map;
 
 

java/com/opensymphony/xwork/validator/validators/ExpressionValidator.java

 
     public void validate(Object object) throws ValidationException {
         Boolean answer = Boolean.FALSE;
-        OgnlValueStack stack = ActionContext.getContext().getValueStack();
-        Object obj = null;
-
-        try {
-            obj = stack.findValue(expression);
-        } catch (Exception e) {
-            log.warn("Caught exception while evaluating expression " + expression, e);
-        }
+        Object obj = getFieldValue(expression, object);
 
         if ((obj != null) && (obj instanceof Boolean)) {
             answer = (Boolean) obj;

java/com/opensymphony/xwork/validator/validators/FieldExpressionValidator.java

         String fieldName = getFieldName();
 
         Boolean answer = Boolean.FALSE;
-        OgnlValueStack stack = ActionContext.getContext().getValueStack();
-        Object obj = stack.findValue(expression);
+        Object obj = getFieldValue(expression, object);
 
         if ((obj != null) && (obj instanceof Boolean)) {
             answer = (Boolean) obj;

java/com/opensymphony/xwork/validator/validators/ValidatorSupport.java

     }
 
     protected Object getFieldValue(String name, Object object) throws ValidationException {
-        try {
-            return Ognl.getValue(OgnlUtil.compile(name), Ognl.createDefaultContext(object), object);
-        } catch (OgnlException e) {
-            final String msg = "Caught exception while getting value for field " + name;
-            log.error(msg, e);
-            throw new ValidationException(msg);
+        OgnlValueStack stack = ActionContext.getContext().getValueStack();
+
+        boolean pop = false;
+
+        if (!stack.getRoot().contains(object)) {
+            stack.push(object);
+            pop = true;
         }
+
+        Object retVal = stack.findValue(name);
+
+        if (pop) {
+            stack.pop();
+        }
+
+        return retVal;
     }
 
     protected void addActionError(Object object) {

java/com/opensymphony/xwork/validator/validators/VisitorFieldValidator.java

     public void validate(Object object) throws ValidationException {
         String fieldName = getFieldName();
         Object value = this.getFieldValue(fieldName, object);
+        OgnlValueStack stack = ActionContext.getContext().getValueStack();
+        stack.push(object);
+
         String visitorContext = (context == null) ? ActionContext.getContext().getName() : context;
 
         if (value == null) {
         } else {
             validateObject(fieldName, value, visitorContext);
         }
+
+        stack.pop();
     }
 
     private void validateObject(String fieldName, Object o, String visitorContext) throws ValidationException {

test/com/opensymphony/xwork/ModelDrivenAction-validation.xml

+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.dtd">
+<validators>
+    <field name="count">
+        <field-validator type="required">
+            <message>You must enter a value for count.</message>
+        </field-validator>
+        <field-validator type="int">
+            <param name="min">1</param>
+            <param name="max">10</param>
+            <message>count must be between ${min} and ${max}, current value is ${count}.</message>
+        </field-validator>
+    </field>
+</validators>

test/com/opensymphony/xwork/validator/ModelDrivenValidationTest.java

+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.Action;
+import com.opensymphony.xwork.ActionProxy;
+import com.opensymphony.xwork.ActionProxyFactory;
+import com.opensymphony.xwork.ModelDrivenAction;
+import com.opensymphony.xwork.ActionContext;
+import junit.framework.TestCase;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+
+/**
+ * ModelDrivenValidationTest
+ * @author Jason Carreira
+ * Created Oct 1, 2003 10:08:25 AM
+ */
+public class ModelDrivenValidationTest extends TestCase {
+
+    public void testModelDrivenValidation() throws Exception {
+        Map params = new HashMap();
+        params.put("count",new String[]{"11"});
+        Map context = new HashMap();
+        context.put(ActionContext.PARAMETERS, params);
+        ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(null,"TestModelDrivenValidation",context);
+        assertEquals(Action.SUCCESS, proxy.execute());
+        ModelDrivenAction action = (ModelDrivenAction) proxy.getAction();
+        assertTrue(action.hasFieldErrors());
+        assertTrue(action.getFieldErrors().containsKey("count"));
+        assertEquals("count must be between 1 and 10, current value is 11.", ((List)action.getFieldErrors().get("count")).get(0));
+    }
+
+    protected void setUp() throws Exception {
+    }
+
+    protected void tearDown() throws Exception {
+    }
+}

test/xwork-default.xml

             <interceptor name="static-params" class="com.opensymphony.xwork.interceptor.StaticParametersInterceptor"/>
             <interceptor name="model-driven" class="com.opensymphony.xwork.interceptor.ModelDrivenInterceptor"/>
             <interceptor name="component" class="com.opensymphony.xwork.interceptor.component.ComponentInterceptor"/>
+            <interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
             <interceptor name="test" class="com.opensymphony.xwork.MockInterceptor">
                 <param name="foo">expectedFoo</param>
             </interceptor>
                 <param name="expectedFoo">foo123</param>
             </interceptor-ref>
         </action>
+
+        <action name="TestModelDrivenValidation" class="com.opensymphony.xwork.ModelDrivenAction">
+            <interceptor-ref name="defaultStack"/>
+            <interceptor-ref name="validation"/>
+        </action>
     </package>
 
     <package name="bar" extends="default" namespace="/foo/bar">
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.