You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by "Davor Hrg (JIRA)" <de...@tapestry.apache.org> on 2008/01/16 23:44:37 UTC

[jira] Created: (TAPESTRY-2053) Generics support for prop binding (PropertyConduitSource)

Generics support for prop binding (PropertyConduitSource)
---------------------------------------------------------

                 Key: TAPESTRY-2053
                 URL: https://issues.apache.org/jira/browse/TAPESTRY-2053
             Project: Tapestry
          Issue Type: Improvement
    Affects Versions: 5.0.8
            Reporter: Davor Hrg




I've tried to make a base class for ListPages.
Most ListPages have a grid with entities from Hibernate,
and I ended up creating same sets of methods for each.
 getter: HibernateEntityDataSource
 property: currentRow

the base ListPage is like this:
---------------------------------------------
public abstract class ListPage<T> {
    
    private Class<T> persistentClass;
    private T current;
    
    public ListPage() {
        this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
    }
    
    @Inject
    private Session _session;
    
    public HibernateEntityDataSource<T> getList(){
        HibernateEntityDataSource<T> documents = HibernateEntityDataSource.create(_session,persistentClass);
        return documents;
    }

    public T getCurrent() {
        return current;
    }

    public void setCurrent(T current) {
        this.current = current;
    }
}
---------------------------------------------

I can then create a concrete page like this:
---------------------------------------------
public class ListDocument extends ListPage<Document>{

}
---------------------------------------------

the template is simple..
---------------------------------------------
<t:grid source="list" rowsPerPage="15" t:id="results" remove="vat,note" row="current"/>
---------------------------------------------


Things are fine until I try to customize table output and use binding expressions.
---------------------------------------------
<t:parameter name="ammountCell">
    ${current.ammount} ${current.currency}
</t:parameter>
---------------------------------------------

Tapestry throws exception stating that property "ammount" can not be found for java.lang.Object.
This is no surprise because erasure of generic info. for the method "getCurrent" return type is java.lang.Object.
One solution is to override offending methods:
---------------------------------------------
@Override public Document getCurrent() {return super.getCurrent();}
@Override public void setCurrent(Document current) {super.setCurrent(current);}
---------------------------------------------
but this is useless nad makes base page obsolete


Generics are no fun for to use with reflection, but the actual type can in be calculated.


****************************************************

I modified PropertyConduitSource just to see if it is feasible.
It covers only my use case and maybe some more, and it should report errors for unmanagable cases.
The implementation was filled with traps and was a bit of headache to get it running.
The getActualType method should be moved to a utility class.... and it will probably get more complicated
to handle all cases.

I added a inner class:
--------------------------
    private static class MethodInfo{
        Method method;
        Class methodType;
        public MethodInfo(Method method, Class methodType) {
            this.method = method;
            this.methodType = methodType;
        }
    }
--------------------------
just to return edequate info for the actualType from buildGetter and buildSetter


added method:
--------------------------
    private Class getActualType(Class type, Type genericReturnTypeDef) {
        Class actualType = null;

        // If a primitive type, convert to wrapper type
        if(genericReturnTypeDef instanceof TypeVariable){
            TypeVariable[] typeParameters = type.getSuperclass().getTypeParameters();
            System.out.println("#"+type.getName());
            Type[] actualTypeParameters = ((ParameterizedType) type.getGenericSuperclass()).getActualTypeArguments();
            TypeVariable genericReturnType = (TypeVariable) genericReturnTypeDef;
            for(int j=0; j<typeParameters.length; j++){
                if(typeParameters[j].equals(genericReturnType)) actualType = (Class) actualTypeParameters[j];
            }
        }else if(genericReturnTypeDef instanceof Class){
            actualType = (Class) genericReturnTypeDef;
        }else if(genericReturnTypeDef instanceof ParameterizedType){
            actualType = (Class) ((ParameterizedType) genericReturnTypeDef).getRawType();
        }else{
            throw new RuntimeException("Could not handle generic info of type "+genericReturnTypeDef+" : "+genericReturnTypeDef.getClass().getName());
        }
        return actualType;
    }
--------------------------
to reconstruct type info from generic declaration
it covers only basics and only reconstructs first level(further info is ignored)
places where method.getReturnType() and getParameterTypes() were used were replaced with
a call to getActualType



$w syntax for javassist had to be used conditionaly since it would generate
   VerifyError: Incompatible object argument for function call
I had no time to get to the bottom of it, the error occured only in the
case when expression came from generic type def. This is only what I've
observed, I haven made tests to say it definitely.
a similar erro happend for people using normal compiler
http://forum.java.sun.com/thread.jspa?threadID=398785&forumID=316
so it may not even be javassist issue.



-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org


[jira] Updated: (TAPESTRY-2053) Generics support for prop binding (PropertyConduitSource)

Posted by "Davor Hrg (JIRA)" <de...@tapestry.apache.org>.
     [ https://issues.apache.org/jira/browse/TAPESTRY-2053?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Davor Hrg updated TAPESTRY-2053:
--------------------------------

    Attachment: TAPESTRY-2053-R612601.patch

patch against R612601

> Generics support for prop binding (PropertyConduitSource)
> ---------------------------------------------------------
>
>                 Key: TAPESTRY-2053
>                 URL: https://issues.apache.org/jira/browse/TAPESTRY-2053
>             Project: Tapestry
>          Issue Type: Improvement
>    Affects Versions: 5.0.8
>            Reporter: Davor Hrg
>         Attachments: TAPESTRY-2053-R612601.patch
>
>
> I've tried to make a base class for ListPages.
> Most ListPages have a grid with entities from Hibernate,
> and I ended up creating same sets of methods for each.
>  getter: HibernateEntityDataSource
>  property: currentRow
> the base ListPage is like this:
> ---------------------------------------------
> public abstract class ListPage<T> {
>     
>     private Class<T> persistentClass;
>     private T current;
>     
>     public ListPage() {
>         this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
>                 .getGenericSuperclass()).getActualTypeArguments()[0];
>     }
>     
>     @Inject
>     private Session _session;
>     
>     public HibernateEntityDataSource<T> getList(){
>         HibernateEntityDataSource<T> documents = HibernateEntityDataSource.create(_session,persistentClass);
>         return documents;
>     }
>     public T getCurrent() {
>         return current;
>     }
>     public void setCurrent(T current) {
>         this.current = current;
>     }
> }
> ---------------------------------------------
> I can then create a concrete page like this:
> ---------------------------------------------
> public class ListDocument extends ListPage<Document>{
> }
> ---------------------------------------------
> the template is simple..
> ---------------------------------------------
> <t:grid source="list" rowsPerPage="15" t:id="results" remove="vat,note" row="current"/>
> ---------------------------------------------
> Things are fine until I try to customize table output and use binding expressions.
> ---------------------------------------------
> <t:parameter name="ammountCell">
>     ${current.ammount} ${current.currency}
> </t:parameter>
> ---------------------------------------------
> Tapestry throws exception stating that property "ammount" can not be found for java.lang.Object.
> This is no surprise because erasure of generic info. for the method "getCurrent" return type is java.lang.Object.
> One solution is to override offending methods:
> ---------------------------------------------
> @Override public Document getCurrent() {return super.getCurrent();}
> @Override public void setCurrent(Document current) {super.setCurrent(current);}
> ---------------------------------------------
> but this is useless nad makes base page obsolete
> Generics are no fun for to use with reflection, but the actual type can in be calculated.
> ****************************************************
> I modified PropertyConduitSource just to see if it is feasible.
> It covers only my use case and maybe some more, and it should report errors for unmanagable cases.
> The implementation was filled with traps and was a bit of headache to get it running.
> The getActualType method should be moved to a utility class.... and it will probably get more complicated
> to handle all cases.
> I added a inner class:
> --------------------------
>     private static class MethodInfo{
>         Method method;
>         Class methodType;
>         public MethodInfo(Method method, Class methodType) {
>             this.method = method;
>             this.methodType = methodType;
>         }
>     }
> --------------------------
> just to return edequate info for the actualType from buildGetter and buildSetter
> added method:
> --------------------------
>     private Class getActualType(Class type, Type genericReturnTypeDef) {
>         Class actualType = null;
>         // If a primitive type, convert to wrapper type
>         if(genericReturnTypeDef instanceof TypeVariable){
>             TypeVariable[] typeParameters = type.getSuperclass().getTypeParameters();
>             System.out.println("#"+type.getName());
>             Type[] actualTypeParameters = ((ParameterizedType) type.getGenericSuperclass()).getActualTypeArguments();
>             TypeVariable genericReturnType = (TypeVariable) genericReturnTypeDef;
>             for(int j=0; j<typeParameters.length; j++){
>                 if(typeParameters[j].equals(genericReturnType)) actualType = (Class) actualTypeParameters[j];
>             }
>         }else if(genericReturnTypeDef instanceof Class){
>             actualType = (Class) genericReturnTypeDef;
>         }else if(genericReturnTypeDef instanceof ParameterizedType){
>             actualType = (Class) ((ParameterizedType) genericReturnTypeDef).getRawType();
>         }else{
>             throw new RuntimeException("Could not handle generic info of type "+genericReturnTypeDef+" : "+genericReturnTypeDef.getClass().getName());
>         }
>         return actualType;
>     }
> --------------------------
> to reconstruct type info from generic declaration
> it covers only basics and only reconstructs first level(further info is ignored)
> places where method.getReturnType() and getParameterTypes() were used were replaced with
> a call to getActualType
> $w syntax for javassist had to be used conditionaly since it would generate
>    VerifyError: Incompatible object argument for function call
> I had no time to get to the bottom of it, the error occured only in the
> case when expression came from generic type def. This is only what I've
> observed, I haven made tests to say it definitely.
> a similar erro happend for people using normal compiler
> http://forum.java.sun.com/thread.jspa?threadID=398785&forumID=316
> so it may not even be javassist issue.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org


[jira] Closed: (TAPESTRY-2053) Generics support for prop binding (PropertyConduitSource)

Posted by "Howard M. Lewis Ship (JIRA)" <de...@tapestry.apache.org>.
     [ https://issues.apache.org/jira/browse/TAPESTRY-2053?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Howard M. Lewis Ship closed TAPESTRY-2053.
------------------------------------------

    Resolution: Duplicate
      Assignee: Howard M. Lewis Ship

Thanks for the ideas; I'm expanding on them slightly for use in TAPESTRY-1518.

> Generics support for prop binding (PropertyConduitSource)
> ---------------------------------------------------------
>
>                 Key: TAPESTRY-2053
>                 URL: https://issues.apache.org/jira/browse/TAPESTRY-2053
>             Project: Tapestry
>          Issue Type: Improvement
>    Affects Versions: 5.0.8
>            Reporter: Davor Hrg
>            Assignee: Howard M. Lewis Ship
>         Attachments: TAPESTRY-2053-R612601.patch
>
>
> I've tried to make a base class for ListPages.
> Most ListPages have a grid with entities from Hibernate,
> and I ended up creating same sets of methods for each.
>  getter: HibernateEntityDataSource
>  property: currentRow
> the base ListPage is like this:
> ---------------------------------------------
> public abstract class ListPage<T> {
>     
>     private Class<T> persistentClass;
>     private T current;
>     
>     public ListPage() {
>         this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
>                 .getGenericSuperclass()).getActualTypeArguments()[0];
>     }
>     
>     @Inject
>     private Session _session;
>     
>     public HibernateEntityDataSource<T> getList(){
>         HibernateEntityDataSource<T> documents = HibernateEntityDataSource.create(_session,persistentClass);
>         return documents;
>     }
>     public T getCurrent() {
>         return current;
>     }
>     public void setCurrent(T current) {
>         this.current = current;
>     }
> }
> ---------------------------------------------
> I can then create a concrete page like this:
> ---------------------------------------------
> public class ListDocument extends ListPage<Document>{
> }
> ---------------------------------------------
> the template is simple..
> ---------------------------------------------
> <t:grid source="list" rowsPerPage="15" t:id="results" remove="vat,note" row="current"/>
> ---------------------------------------------
> Things are fine until I try to customize table output and use binding expressions.
> ---------------------------------------------
> <t:parameter name="ammountCell">
>     ${current.ammount} ${current.currency}
> </t:parameter>
> ---------------------------------------------
> Tapestry throws exception stating that property "ammount" can not be found for java.lang.Object.
> This is no surprise because erasure of generic info. for the method "getCurrent" return type is java.lang.Object.
> One solution is to override offending methods:
> ---------------------------------------------
> @Override public Document getCurrent() {return super.getCurrent();}
> @Override public void setCurrent(Document current) {super.setCurrent(current);}
> ---------------------------------------------
> but this is useless nad makes base page obsolete
> Generics are no fun for to use with reflection, but the actual type can in be calculated.
> ****************************************************
> I modified PropertyConduitSource just to see if it is feasible.
> It covers only my use case and maybe some more, and it should report errors for unmanagable cases.
> The implementation was filled with traps and was a bit of headache to get it running.
> The getActualType method should be moved to a utility class.... and it will probably get more complicated
> to handle all cases.
> I added a inner class:
> --------------------------
>     private static class MethodInfo{
>         Method method;
>         Class methodType;
>         public MethodInfo(Method method, Class methodType) {
>             this.method = method;
>             this.methodType = methodType;
>         }
>     }
> --------------------------
> just to return edequate info for the actualType from buildGetter and buildSetter
> added method:
> --------------------------
>     private Class getActualType(Class type, Type genericReturnTypeDef) {
>         Class actualType = null;
>         // If a primitive type, convert to wrapper type
>         if(genericReturnTypeDef instanceof TypeVariable){
>             TypeVariable[] typeParameters = type.getSuperclass().getTypeParameters();
>             System.out.println("#"+type.getName());
>             Type[] actualTypeParameters = ((ParameterizedType) type.getGenericSuperclass()).getActualTypeArguments();
>             TypeVariable genericReturnType = (TypeVariable) genericReturnTypeDef;
>             for(int j=0; j<typeParameters.length; j++){
>                 if(typeParameters[j].equals(genericReturnType)) actualType = (Class) actualTypeParameters[j];
>             }
>         }else if(genericReturnTypeDef instanceof Class){
>             actualType = (Class) genericReturnTypeDef;
>         }else if(genericReturnTypeDef instanceof ParameterizedType){
>             actualType = (Class) ((ParameterizedType) genericReturnTypeDef).getRawType();
>         }else{
>             throw new RuntimeException("Could not handle generic info of type "+genericReturnTypeDef+" : "+genericReturnTypeDef.getClass().getName());
>         }
>         return actualType;
>     }
> --------------------------
> to reconstruct type info from generic declaration
> it covers only basics and only reconstructs first level(further info is ignored)
> places where method.getReturnType() and getParameterTypes() were used were replaced with
> a call to getActualType
> $w syntax for javassist had to be used conditionaly since it would generate
>    VerifyError: Incompatible object argument for function call
> I had no time to get to the bottom of it, the error occured only in the
> case when expression came from generic type def. This is only what I've
> observed, I haven made tests to say it definitely.
> a similar erro happend for people using normal compiler
> http://forum.java.sun.com/thread.jspa?threadID=398785&forumID=316
> so it may not even be javassist issue.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org