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

Generics return wrong type when subclassing page

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 5.1.0.4
    • 5.4
    • None

    Description

      I have a custom library that has the following classes:

      {{{
      public abstract class AbstractViewPage<T extends StaticPage<T, V>, V extends StaticPageVersion> {
      private static final Pattern ID = Pattern.compile("^
      d+$");

      @InjectDao(StaticPage.class) private Dao<T> dao;
      @Inject private Response response;

      private T page;

      void onActivate(String key) throws IOException {
      if (ID.matcher(key).matches())
      page = dao.get(Long.parseLong(key));
      else

      { page = dao.get(eq("name", key)); }

      if (page != null && page.getLive() == null)
      page = null;

      if (page == null)
      response.sendError(404, "Page not found");
      }

      public T getPage()

      { return page; }

      public void setPage(T page)

      { this.page = page; }

      /** Returns the versioned content to display. */
      public V getContent()

      { if (page == null) return null; return page.getLive(); }

      }
      }}}

      {{{
      /** Displays a static page */
      @Public
      public class Page extends AbstractViewPage<IFPStaticPage, IFPStaticPageVersion> {

      @Inject private IAuth auth;
      @Inject private HttpServletRequest request;
      @Inject private HttpServletResponse response;

      Object onActivate()

      { IFPStaticPage page = getPage(); if (page != null && page.isRestricted() && auth.getAccount(request, response) == null) return "start"; return null; }

      public boolean isTopLevel()

      { return getPage() == getPage().getSectionPage(); }

      void onEndElementFromBreadcrumb(Element e)

      { if ("a".equals(e.getName())) e.getContainer().raw("  ›  "); }

      }
      }}}

      As you can see, based on generics the method "getContent" should return a IFPStaticPageVersion.
      This works fine when I use this Page.class directly.

      Recently I wanted to extend this Page.class to add a few features specific to one project. When I extended this class (no template so that it would use the Page.class template) I ended up getting an error on the subclass. The error occurred because getContent returned a completely different class instead of IFPStaticPageVersion.

      I work around I found to fix this is to override the getContent method so that it explicitly defines the return type. But I had to do this in both Page.class and the subclass (Page2.class). Here's my addition to both classes:

      {{{

      @Override
      public IFPStaticPageVersion getContent()

      { return super.getContent(); }

      }}}

      Obviously I shouldn't have to do this to get the correct class back (especially not to both Page.class AND Page2.class.

      Attachments

        1. tap5-901-patch.txt
          3 kB
          Dan Adams

        Activity

          People

            Unassigned Unassigned
            mikeleo Mike Leonardo
            Votes:
            3 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: