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


 

 

Reply via email to