Hello, I have been having a little trouble with the interceptor stack but I have quite a bit of info, so I'm hoping someone can help me out.
Here it goes: I created my own interceptor stack with the following: [code] <interceptor-stack name="crudStack"> <interceptor-ref name="token"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="params"/> <interceptor-ref name="user"/> <----------- Note this interceptor <interceptor-ref name="prepare"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="params"/> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"/> <interceptor-ref name="workflow"/> </interceptor-stack> [/code] The user interceptor which I created puts the user into the value stack. However I noticed for some forms the xwork validation RequiredStringValidator started failing even though the input was valid. For example, the following form fails validation [shortened for explanation purposes]: [code] <!-- Form to save a collection name --> <s:form method="post" > <s:textfield label="%{getText('name')}" name="collectionName"/> </s:form> [/code] However this form works [shortened for explanation purposes]: <!-- Form to save a language type --> <s:form method="post"> <s:textfield label="%{getText('name')}" name="languageType.name"/> </s:form> Notice the difference is the first one I am setting the value directly on the action where in the second form, I am setting a value on an object within the action. Furthermore, When I change the stack to the following both forms work: [code] <interceptor-stack name="crudStack"> <interceptor-ref name="token"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="params"/> <interceptor-ref name="prepare"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="params"/> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"/> <interceptor-ref name="workflow"/> <interceptor-ref name="user"/> <----------- Moved interceptor to bottom of stack </interceptor-stack> [/code] I did some more digging and I found the difference is: When ognl is able to find the value itself in the tree for the validator a string rather than an array with a single value is retuned causing the validation to pass. So when ognl.java executes the following method: [code] public static Object getValue( Object tree, Map context, Object root, Class resultType ) throws OgnlException { Object result; OgnlContext ognlContext = (OgnlContext)addDefaultContext(root, context); result = ((Node)tree).getValue( ognlContext, root ); if (resultType != null) { result = getTypeConverter( context ).convertValue( context, root, null, null, result, resultType); } return result; } [/code] For the SECOND form, which passes, the code: result = ((Node)tree).getValue( ognlContext, root ); finds a value and returns however, for the FIRST form, which fails, ognl gets a null from: result = ((Node)tree).getValue( ognlContext, root ); and executes then executes: result = getTypeConverter( context ).convertValue( context, root, null, null, result, resultType); which is actually a call to: com.opensymphony.xwork2.util.XWorkMapPropertyAccessor.getProperty(Map context, Object target, Object name) which delegates to its parent class method: ognl.MapPropertyAccessor.getProperty(context, target, name) Now, this actually finds the value and returns it as a string array with a single value. It returns this array to the RequiredStringValidator so in the validate(Object object) method the following code evaluates to true because a String[] is not an instance of String: [code] if (!(value instanceof String)) { addFieldError(fieldName, object); } [/code] If you have any thoughts, they would be greatly appreciated. Thanks again, -Nate