[ http://mc4j.org/jira/browse/STS-426?page=comments#action_10841 ] 
            
Alan Burlison commented on STS-426:
-----------------------------------

My previous comment was correct, the current code which tries to traverse the 
inheritance hierarchy mapping from subclass to superclass is doing things the 
wrong way round:

----------
PropertyExpressionEvaluation.java:404

        // Now if the super type is parameterized try and loop through the type 
variables
        // and type arguments in tandem matching a concrete parameter to the 
type variable
        for (Class beanClass=lastBean; beanClass != null; 
beanClass=beanClass.getSuperclass()) {
            Type stype = beanClass.getGenericSuperclass();
----------

I've added the following torture test to the Stripes test harness:

----------
class Class1<A,B,C,D,E> extends GenericsBindingTestsBaseClass<A,B,C,D,E> { }

class Class2<D,E,B,A,C> extends Class1<D,E,B,A,C> { }

class Class3<Y,W,Z,V,X> extends Class2<Y,W,Z,V,X> { }

class Class4<Z,Y,X,W,V> extends Class3<Z,Y,X,W,V> { }

public class GenericsBindingTests2 extends 
Class4<TestBean,Double,Boolean,Long,Date> implements ActionBean {
        :
}
----------

I've modified the code so that it stores the mapping info in a list of hashes 
where the key is the TypeVariable we wish to map, and the value is the 
associated Type (which may in turn be a TypeVariable or a Class).  I've also 
added debug code to display the progress of the mapping process.  If we 
traverse this list in the same order as the current code (subclass to 
superclass), we see the following:

----------
called to resolve JB
found bean class class net.sourceforge.stripes.controller.GenericsBindingTests2
    [1: class net.sourceforge.stripes.controller.Class4] Z maps to class 
net.sourceforge.stripes.test.TestBean
    [1: class net.sourceforge.stripes.controller.Class4] Y maps to class 
java.lang.Double
    [1: class net.sourceforge.stripes.controller.Class4] X maps to class 
java.lang.Boolean
    [1: class net.sourceforge.stripes.controller.Class4] W maps to class 
java.lang.Long
    [1: class net.sourceforge.stripes.controller.Class4] V maps to class 
java.util.Date
    [2: class net.sourceforge.stripes.controller.Class3] Y maps to Z
    [2: class net.sourceforge.stripes.controller.Class3] W maps to Y
    [2: class net.sourceforge.stripes.controller.Class3] Z maps to X
    [2: class net.sourceforge.stripes.controller.Class3] V maps to W
    [2: class net.sourceforge.stripes.controller.Class3] X maps to V
    [3: class net.sourceforge.stripes.controller.Class2] D maps to Y
    [3: class net.sourceforge.stripes.controller.Class2] E maps to W
    [3: class net.sourceforge.stripes.controller.Class2] B maps to Z
    [3: class net.sourceforge.stripes.controller.Class2] A maps to V
    [3: class net.sourceforge.stripes.controller.Class2] C maps to X
    [4: class net.sourceforge.stripes.controller.Class1] A maps to D
    [4: class net.sourceforge.stripes.controller.Class1] B maps to E
    [4: class net.sourceforge.stripes.controller.Class1] C maps to B
    [4: class net.sourceforge.stripes.controller.Class1] D maps to A
    [4: class net.sourceforge.stripes.controller.Class1] E maps to C
    [5: class net.sourceforge.stripes.controller.GenericsBindingTestsBaseClass] 
JB maps to A
    [5: class net.sourceforge.stripes.controller.GenericsBindingTestsBaseClass] 
N maps to B
    [5: class net.sourceforge.stripes.controller.GenericsBindingTestsBaseClass] 
E maps to C
    [5: class net.sourceforge.stripes.controller.GenericsBindingTestsBaseClass] 
K maps to D
    [5: class net.sourceforge.stripes.controller.GenericsBindingTestsBaseClass] 
V maps to E
mapping JB...
level 1
level 2
level 3
level 4
level5
typemap[5] maps JB to A
    got typevar, keep going
couldn't map to Class
----------

However if we reverse the order and scan from superclass to subclass, we see 
this:

----------
called to resolve JB
found bean class class net.sourceforge.stripes.controller.GenericsBindingTests2
    [1: class net.sourceforge.stripes.controller.Class4] Z maps to class 
net.sourceforge.stripes.test.TestBean
    [1: class net.sourceforge.stripes.controller.Class4] Y maps to class 
java.lang.Double
    [1: class net.sourceforge.stripes.controller.Class4] X maps to class 
java.lang.Boolean
    [1: class net.sourceforge.stripes.controller.Class4] W maps to class 
java.lang.Long
    [1: class net.sourceforge.stripes.controller.Class4] V maps to class 
java.util.Date
    [2: class net.sourceforge.stripes.controller.Class3] Y maps to Z
    [2: class net.sourceforge.stripes.controller.Class3] W maps to Y
    [2: class net.sourceforge.stripes.controller.Class3] Z maps to X
    [2: class net.sourceforge.stripes.controller.Class3] V maps to W
    [2: class net.sourceforge.stripes.controller.Class3] X maps to V
    [3: class net.sourceforge.stripes.controller.Class2] D maps to Y
    [3: class net.sourceforge.stripes.controller.Class2] E maps to W
    [3: class net.sourceforge.stripes.controller.Class2] B maps to Z
    [3: class net.sourceforge.stripes.controller.Class2] A maps to V
    [3: class net.sourceforge.stripes.controller.Class2] C maps to X
    [4: class net.sourceforge.stripes.controller.Class1] A maps to D
    [4: class net.sourceforge.stripes.controller.Class1] B maps to E
    [4: class net.sourceforge.stripes.controller.Class1] C maps to B
    [4: class net.sourceforge.stripes.controller.Class1] D maps to A
    [4: class net.sourceforge.stripes.controller.Class1] E maps to C
    [5: class net.sourceforge.stripes.controller.GenericsBindingTestsBaseClass] 
JB maps to A
    [5: class net.sourceforge.stripes.controller.GenericsBindingTestsBaseClass] 
N maps to B
    [5: class net.sourceforge.stripes.controller.GenericsBindingTestsBaseClass] 
E maps to C
    [5: class net.sourceforge.stripes.controller.GenericsBindingTestsBaseClass] 
K maps to D
    [5: class net.sourceforge.stripes.controller.GenericsBindingTestsBaseClass] 
V maps to E

mapping JB...
level 5
typemap[5] maps JB to A
    got typevar, keep going
level 4
typemap[4] maps A to D
    got typevar, keep going
level 3
typemap[3] maps D to Y
    got typevar, keep going
level 2
typemap[2] maps Y to Z
    got typevar, keep going
level 1
typemap[1] maps Z to class net.sourceforge.stripes.test.TestBean
    got real class class net.sourceforge.stripes.test.TestBean, done
returning type class net.sourceforge.stripes.test.TestBean
----------

So there are actually two bugs here - first the code doesn't work properly on 
generically parameterized bean types, although it does work on beans that are 
specified as generic parameters - see the following:

public class GenericsBindingTestsBaseClass<JB,N,E,K,V> {
     JB bean;                                                        // This is 
handled just fine
     TestGenericBean<N,E> genericBean;   // This triggers STS-426
:
}

The second bug is that where the inheritance hierarchy is >1 level deep, the 
mapping of TypeVariable to real Type doesn't work as it traverses the 
inheritance hierarchy in the wrong order. 

> NPE in PropertyExpressionEvaluation.getScalarType with generics
> ---------------------------------------------------------------
>
>                 Key: STS-426
>                 URL: http://mc4j.org/jira/browse/STS-426
>             Project: Stripes
>          Issue Type: Bug
>          Components: Validation
>    Affects Versions: Release 1.4.3
>         Environment: OpemSolaris / Tomcat 5.5.17
>            Reporter: Alan Burlison
>         Assigned To: Tim Fennell
>         Attachments: PropertyExpressionEvaluation.java.patch.v1, 
> PropertyExpressionEvaluation.java.patch.v2
>
>
> I have a generic class that is used to store result set scrolling information 
> for query pages.  Specifically, the class holds the maximum 
> and minimum key values for the rows displayed on the page:
> public class ResultPageState<K> {
> // Methods elided
>      private K minKey;
>      private K maxKey;
>      private boolean moreBefore;
>      private boolean moreAfter;       
> }
> I store an appropriately-typed instance of this class inside my ActionBeans, 
> e.g. if the keys are Strings:
>      private ResultPageState<String> pageState;
> In the associated JSP I refer to the pageState as follows:
> <ss:hidden name="pageState.minKey"/>
> <ss:hidden name="pageState.maxKey"/>
> <ss:hidden name="pageState.moreBefore"/>
> <ss:hidden name="pageState.moreAfter"/>
> When rendering the page the values are retrieved correctly:
> <input name="pageState.minKey" value="quinn" type="hidden" />
> <input name="pageState.maxKey" value="zach" type="hidden" />
> <input name="pageState.moreBefore" value="true" type="hidden" />
> <input name="pageState.moreAfter" value="false" type="hidden" />
> But during the binding phase of Action submit processing a NPE is thrown:
> 23 Oct 2007 12:54:59,956 DEBUG Could not bind property with name 
> [pageState.maxKey] to bean of type: UserSearchAction
> java.lang.NullPointerException
>          at 
> net.sourceforge.stripes.util.bean.PropertyExpressionEvaluation.getScalarType(PropertyExpressionEvaluation.java:479)
>          at 
> net.sourceforge.stripes.controller.DefaultActionBeanPropertyBinder.bind(DefaultActionBeanPropertyBinder.java:265)
>          at 
> net.sourceforge.stripes.controller.DispatcherHelper$3.intercept(DispatcherHelper.java:185)
>          at 
> net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:157)
>          at 
> net.sourceforge.stripes.controller.BeforeAfterMethodInterceptor.intercept(BeforeAfterMethodInterceptor.java:107)
>          at 
> net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:154)
>          at 
> net.sourceforge.stripes.controller.ExecutionContext.wrap(ExecutionContext.java:73)
>          at 
> net.sourceforge.stripes.controller.DispatcherHelper.doBindingAndValidation(DispatcherHelper.java:182)
>          at 
> net.sourceforge.stripes.controller.DispatcherServlet.doBindingAndValidation(DispatcherServlet.java:217)
>          at 
> net.sourceforge.stripes.controller.DispatcherServlet.doPost(DispatcherServlet.java:142)
>          at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
> The offending code seems to be in 
> net.sourceforge.stripes.util.beanPropertyExpressionEvaluation.convertToClass 
> - if it fails to resolve the type to a Class it returns null, and that 
> results in the NPE in PropertyExpressionEvaluation.getScalarType.  The 
> comments on convertToClass seem to suggest that it should cope with generics, 
> but in this case it obviously doesn't.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://mc4j.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to