Details
-
Improvement
-
Status: Closed
-
Major
-
Resolution: Duplicate
-
5.0.8
-
None
-
None
-
None
Description
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()
@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)
}
--------------------------
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++)
}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.
Attachments
Attachments
Issue Links
- is a clone of
-
TAPESTRY-1518 Add support for JDK 1.5 Generics when defining pages and accessing bean properties
- Closed