Tapestry
  1. Tapestry
  2. TAPESTRY-1518

Add support for JDK 1.5 Generics when defining pages and accessing bean properties

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 5.0, 5.0.3, 5.0.4
    • Fix Version/s: 5.0.10
    • Component/s: tapestry-core, tapestry-ioc
    • Labels:
      None

      Description

      Base.java

      class abstract Base<T>{
      private T entity;
      public void setEntity(T t)

      { this.entity=entity; }

      public T getEntity(T t)

      { return this.entity; }

      protected abstract Class<T> getEntityClass();
      onPrepareFromMyForm(){
      if(this.entity == null){
      try

      { this.entity=getEntityClass().newInstance(); }

      catch(Exception e)

      { throw new RuntimeException(e); }

      }
      }
      .....
      }

      ProductPage.java

      public class ProductPage extends Base<Product>{
      protected Class<Product> getEntityClass()

      { return Product.class; }

      }

      ProductPage.html

      <t:form t:id="MyForm">
      <t:errors/>
      <t:label for="input"/>
      <input t:type="textfield" t:id="input" value="entity.name" size="40" t:validate="required,minlength=3"/>
      <br/>
      <input type="submit" value="Submit"/>
      </t:form>

      exception:
      Could not convert 'entity.name' into a component parameter binding: Class java.lang.Object does not contain a property named 'name' (within property expression 'entity.name').

      When I debug the app,I fiind PropertyConduitSourceImpl.readMethodForTerm before onPrepareFromMyForm method.

      I think the method should be after onPrepareFromMyForm method.

        Issue Links

          Activity

          Hide
          Howard M. Lewis Ship added a comment -

          This could be a bit of a problem because of type erasure.

          Show
          Howard M. Lewis Ship added a comment - This could be a bit of a problem because of type erasure.
          Hide
          Jun Tsai added a comment -

          In javassist javadoc pages
          I find:

          public CtMethod[] getDeclaredMethods()

          Gets all methods declared in the class. The inherited methods are not included.

          public CtMethod[] getMethods()

          Returns an array containing CtMethod objects representing all the non-private methods of the class. That array includes pon-private methods inherited from the superclasses.

          I guess InternalClassTransformationImpl can use CtClass.getMethods() method to find all methods (include inherited methods.)

          Show
          Jun Tsai added a comment - In javassist javadoc pages I find: public CtMethod[] getDeclaredMethods() Gets all methods declared in the class. The inherited methods are not included. public CtMethod[] getMethods() Returns an array containing CtMethod objects representing all the non-private methods of the class. That array includes pon-private methods inherited from the superclasses. I guess InternalClassTransformationImpl can use CtClass.getMethods() method to find all methods (include inherited methods.)
          Hide
          Jun Tsai added a comment -

          wrong comment

          see #1521

          Show
          Jun Tsai added a comment - wrong comment see #1521
          Hide
          Howard M. Lewis Ship added a comment -

          I'm slogging away at this one.

          Something that will work today is that you can make your base class abstract, with abstract getters and setters for the parameterized type, In this way, when you implement the abstract class, you will provide new methods that have the correct return type (even after type erasure) ... but then you need to redefine the field in each subclass, which is most of the work I think you are trying to avoid.

          What I'm seeing is that the data available at runtime is very limited; in the case of a non-abstract base class, the Method objects are the Methods as defined on the base class (as type Object), which kind of makes sense.

          Show
          Howard M. Lewis Ship added a comment - I'm slogging away at this one. Something that will work today is that you can make your base class abstract, with abstract getters and setters for the parameterized type, In this way, when you implement the abstract class, you will provide new methods that have the correct return type (even after type erasure) ... but then you need to redefine the field in each subclass, which is most of the work I think you are trying to avoid. What I'm seeing is that the data available at runtime is very limited; in the case of a non-abstract base class, the Method objects are the Methods as defined on the base class (as type Object), which kind of makes sense.
          Hide
          Howard M. Lewis Ship added a comment -

          This is coming along pretty nicely. The question is going to be how much of the information will be available at runtime. Specifically, using @Inject or @ApplicatinState with a generic type will probably not work.

          Show
          Howard M. Lewis Ship added a comment - This is coming along pretty nicely. The question is going to be how much of the information will be available at runtime. Specifically, using @Inject or @ApplicatinState with a generic type will probably not work.
          Hide
          Howard M. Lewis Ship added a comment -

          I'm very happy with this ... the integration tests now include an example of a GenericEditor<T> base class and a TrackEditor extends GenericEditor<Track>. You get all the functionality with zero code, just define your concrete class and lock down the generic parameters. This will be huge.

          Show
          Howard M. Lewis Ship added a comment - I'm very happy with this ... the integration tests now include an example of a GenericEditor<T> base class and a TrackEditor extends GenericEditor<Track>. You get all the functionality with zero code, just define your concrete class and lock down the generic parameters. This will be huge.
          Hide
          Howard M. Lewis Ship added a comment -

          BTW, the type of property is communicated out properly ... that means that the BeanEditForm can instantiate the correct type of bean automatically, you don't need some of the code in your example (the getEntityClass() method).

          Show
          Howard M. Lewis Ship added a comment - BTW, the type of property is communicated out properly ... that means that the BeanEditForm can instantiate the correct type of bean automatically, you don't need some of the code in your example (the getEntityClass() method).

            People

            • Assignee:
              Howard M. Lewis Ship
              Reporter:
              Jun Tsai
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development