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