You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by "Howard M. Lewis Ship (JIRA)" <de...@tapestry.apache.org> on 2008/01/25 01:06:45 UTC

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

     [ 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