Uploaded image for project: 'Tapestry 5'
  1. Tapestry 5
  2. TAP5-2032

GenericsUtils does not handle generics properly when extracting the actual type

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: In Progress
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: 5.3.6, 5.5.0, 5.4.3
    • Fix Version/s: None
    • Component/s: tapestry-ioc
    • Labels:

      Description

      We have the following interfaces / classes

      public interface IPersonWithRoleAssociation<A> extends IEntityAssociationWithInfo<A, Person> {
      	PersonRole getRole();
      	void setRole(PersonRole role);
      }
      
      public interface IEntityAssociationWithInfo<P, C> {
      	P getParent();
      	void setParent(P parent);
      
      	C getChild();
      	void setChild(C child);
      }
      
      public class Person implements Serializable {
      	....
      	String name;
      	public String getName() {
      		return name;
      	}
      }
      

      and the page:

      public class EditPersonsWithRoles {
      	@Property(write=false) IPersonWithRoleAssociation<A> personWithRole;
      }
      

      and the template snippet:

      <t:textfield t:id="personSex" t:value="personWithRole.child.name"/>
      

      Leads to the following exception:

      Exception generating conduit for expression 'personWithRole.child.name': ...
      ...
      Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
      	at org.apache.tapestry5.ioc.internal.util.GenericsUtils.resolve(GenericsUtils.java:388) ~[tapestry-ioc-5.3.6.jar:na]
      	at org.apache.tapestry5.ioc.internal.util.GenericsUtils.resolve(GenericsUtils.java:128) ~[tapestry-ioc-5.3.6.jar:na]
      	at org.apache.tapestry5.ioc.internal.util.GenericsUtils.extractActualType(GenericsUtils.java:74) ~[tapestry-ioc-5.3.6.jar:na]
      	at org.apache.tapestry5.internal.services.PropertyConduitSourceImpl$PropertyConduitBuilder.buildGetterMethodAccessTerm(PropertyConduitSourceImpl.java:1119) ~[tapestry-core-5.3.6.jar:na]
      

      At GenericsUtils.java:388 we have:

      resolved = ((ParameterizedType) t).getActualTypeArguments()[i];
      

      where:

      i = 1
      resolved = C
      ((ParameterizedType) t).getActualTypeArguments() = [org.topfive.entities.IPersonWithRoleAssociation<P>]
      

      so the problem seems to be that the code assumes that it can find the type information for C as the second generic parameter for IPersonWithRoleAssociation, when in fact is is the second generic parameter for the superclass IEntityAssociationWithInfo which IPersonWithRoleAssociation extends and passes C explicitly (Person). Everything is fine, if I use a marker interface for Person (IPerson) and declare:

      public interface IPersonWithRoleAssociation<A, P extends IPerson> extends IEntityAssociationWithInfo<A, P>
      

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                thiagohp Thiago Henrique De Paula Figueiredo
                Reporter:
                fhackenberger DI Florian Hackenberger
              • Votes:
                0 Vote for this issue
                Watchers:
                5 Start watching this issue

                Dates

                • Created:
                  Updated: