You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by "Howard M. Lewis Ship (JIRA)" <ji...@apache.org> on 2011/09/23 17:18:26 UTC

[jira] [Commented] (TAP5-1656) Problem when inheriting annotated methods from a abstract superclass

    [ https://issues.apache.org/jira/browse/TAP5-1656?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13113502#comment-13113502 ] 

Howard M. Lewis Ship commented on TAP5-1656:
--------------------------------------------


Making some progress here.  I now understand what's causing it and why going to the second page makes it work.

It all comes down to this code:


    public MethodInvocationBundle(MethodDescription methodDescription, MethodAdvice[] advice)
    {
        this.methodDescription = methodDescription;
        this.advice = advice;
    }

    public Method getMethod(Object instance)
    {
        if (method == null)
            method = findMethod(instance.getClass());

        return method;
    }

    @SuppressWarnings("unchecked")
    private Method findMethod(Class clazz)
    {
        try
        {
            Class[] types = new Class[methodDescription.argumentTypes.length];

            for (int i = 0; i < types.length; i++)
            {
                types[i] = PlasticInternalUtils.toClass(clazz.getClassLoader(), methodDescription.argumentTypes[i]);
            }

            return clazz.getDeclaredMethod(methodDescription.methodName, types);
        }
        catch (Exception ex)
        {
            throw new RuntimeException(String.format("Unable to locate Method %s: %s", methodDescription,
                    PlasticInternalUtils.toMessage(ex)), ex);
        }
    }

This MethodInvocationBundle is created for the advice on the base class (Parent) implementation of setupRender().

Here's the trick: if you invoke this for child A (which does not override the setupRender method), this code is invoked with clazz == ChildA and clazz.getDeclaredMethod() fails.

Later, you invoke this for child B, which does override the method. getDeclaredMethod() succeeds, and the result is stored for later invocations for both ChildA and ChildB.

The core of this is going to be: how to get clazz to be the right class (the parent class, not any of the child classes).


> Problem when inheriting annotated methods from a abstract superclass
> --------------------------------------------------------------------
>
>                 Key: TAP5-1656
>                 URL: https://issues.apache.org/jira/browse/TAP5-1656
>             Project: Tapestry 5
>          Issue Type: Bug
>          Components: tapestry-core
>    Affects Versions: 5.3
>            Reporter: Sigbjørn Tvedt
>            Assignee: Howard M. Lewis Ship
>
> I have a parent class and two subclasses.
> The parent is declared as a abstract class as the logic in the subclasses will differ slightly but they are all using Parent.tml. 
> This has been tested with all classes in the package "com.example.newapp.base.Parent" and I also tried to move Parent.class to the "com.example.newapp.base" package.
> (I will keep a testapp on https://github.com/sigbjornt/T5.3-beta-6-bug-demo for a while)
> public abstract class Parent {
>   @Log
>   public void setupRender() {
>   }
> }
> public class ChildA extends Parent {
>  ....
> }
> public class ChildB extends Parent {
>    @Override
>   public void setupRender() {
>     super.setupRender();
>   }
>  ....
> }
> This will be ok as ChildB is accessed before ChildA.
> If ChildA is accessed before ChildB (or ChildB does not call "super.setupRender();"), we get an exeption.
> --stacktrace -- 
> [ERROR] pages.ChildA Render queue error in SetupRender[ChildA]: Unable to locate Method public void setupRender(): com.example.newapp.pages.ChildA.setupRender()
> org.apache.tapestry5.ioc.internal.util.TapestryException: Unable to locate Method public void setupRender(): com.example.newapp.pages.ChildA.setupRender()
> 	at org.apache.tapestry5.internal.structure.ComponentPageElementImpl$AbstractPhase.invoke(ComponentPageElementImpl.java:153)
> 	at org.apache.tapestry5.internal.structure.ComponentPageElementImpl$SetupRenderPhase.render(ComponentPageElementImpl.java:181)
> 	at org.apache.tapestry5.internal.services.RenderQueueImpl.run(RenderQueueImpl.java:72)
> 	at org.apache.tapestry5.internal.services.PageRenderQueueImpl.render(PageRenderQueueImpl.java:124)
> 	at $PageRenderQueue_19bce9b139ae.render(Unknown Source)
> 	at $PageRenderQueue_19bce9b139ad.render(Unknown Source)
> 	at org.apache.tapestry5.internal.services.MarkupRendererTerminator.renderMarkup(MarkupRendererTerminator.java:37)
> 	at org.apache.tapestry5.services.TapestryModule$31.renderMarkup(TapestryModule.java:1998)
> 	at $MarkupRenderer_19bce9b139b0.renderMarkup(Unknown Source)
> 	at org.apache.tapestry5.services.TapestryModule$30.renderMarkup(TapestryModule.java:1982)
> 	at $MarkupRenderer_19bce9b139b0.renderMarkup(Unknown Source)
> 	at org.apache.tapestry5.services.TapestryModule$29.renderMarkup(TapestryModule.java:1964)
> 	at $MarkupRenderer_19bce9b139b0.renderMarkup(Unknown Source)
> 	at org.apache.tapestry5.services.TapestryModule$28.renderMarkup(TapestryModule.java:1949)
> 	at $MarkupRenderer_19bce9b139b0.renderMarkup(Unknown Source)
> 	at org.apache.tapestry5.services.TapestryModule$27.renderMarkup(TapestryModule.java:1935)
> 	at $MarkupRenderer_19bce9b139b0.renderMarkup(Unknown Source)
> 	at org.apache.tapestry5.services.TapestryModule$26.renderMarkup(TapestryModule.java:1917)
> 	at $MarkupRenderer_19bce9b139b0.renderMarkup(Unknown Source)
> 	at org.apache.tapestry5.services.TapestryModule$25.renderMarkup(TapestryModule.java:1898)
> 	at $MarkupRenderer_19bce9b139b0.renderMarkup(Unknown Source)
> 	at $MarkupRenderer_19bce9b139ac.renderMarkup(Unknown Source)
> 	at org.apache.tapestry5.internal.services.PageMarkupRendererImpl.renderPageMarkup(PageMarkupRendererImpl.java:47)
> 	at $PageMarkupRenderer_19bce9b139a9.renderPageMarkup(Unknown Source)
> 	at org.apache.tapestry5.internal.services.PageResponseRendererImpl.renderPageResponse(PageResponseRendererImpl.java:67)
> 	at $PageResponseRenderer_19bce9b1395f.renderPageResponse(Unknown Source)
> 	at org.apache.tapestry5.internal.services.PageRenderRequestHandlerImpl.handle(PageRenderRequestHandlerImpl.java:64)
> 	at org.apache.tapestry5.services.TapestryModule$38.handle(TapestryModule.java:2227)
> 	at $PageRenderRequestHandler_19bce9b13961.handle(Unknown Source)
> 	at $PageRenderRequestHandler_19bce9b1395b.handle(Unknown Source)
> 	at org.apache.tapestry5.internal.services.ComponentRequestHandlerTerminator.handlePageRender(ComponentRequestHandlerTerminator.java:48)
> 	at org.apache.tapestry5.services.InitializeActivePageName.handlePageRender(InitializeActivePageName.java:47)
> 	at $ComponentRequestHandler_19bce9b1395c.handlePageRender(Unknown Source)
> 	at $ComponentRequestHandler_19bce9b1393f.handlePageRender(Unknown Source)
> 	at org.apache.tapestry5.internal.services.PageRenderDispatcher.dispatch(PageRenderDispatcher.java:45)
> 	at $Dispatcher_19bce9b13941.dispatch(Unknown Source)
> 	at $Dispatcher_19bce9b1393c.dispatch(Unknown Source)
> 	at org.apache.tapestry5.services.TapestryModule$RequestHandlerTerminator.service(TapestryModule.java:297)
> 	at com.example.newapp.services.AppModule$1.service(AppModule.java:90)
> 	at $RequestFilter_19bce9b1393b.service(Unknown Source)
> 	at $RequestHandler_19bce9b1393d.service(Unknown Source)
> 	at org.apache.tapestry5.internal.services.RequestErrorFilter.service(RequestErrorFilter.java:26)
> 	at $RequestHandler_19bce9b1393d.service(Unknown Source)
> 	at org.apache.tapestry5.services.TapestryModule$3.service(TapestryModule.java:894)
> 	at $RequestHandler_19bce9b1393d.service(Unknown Source)
> 	at org.apache.tapestry5.services.TapestryModule$2.service(TapestryModule.java:884)
> 	at $RequestHandler_19bce9b1393d.service(Unknown Source)
> 	at org.apache.tapestry5.internal.services.StaticFilesFilter.service(StaticFilesFilter.java:90)
> 	at $RequestHandler_19bce9b1393d.service(Unknown Source)
> 	at org.apache.tapestry5.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:105)
> 	at org.apache.tapestry5.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:95)
> 	at org.apache.tapestry5.ioc.internal.util.ConcurrentBarrier.withRead(ConcurrentBarrier.java:85)
> 	at org.apache.tapestry5.internal.services.CheckForUpdatesFilter.service(CheckForUpdatesFilter.java:119)
> 	at $RequestHandler_19bce9b1393d.service(Unknown Source)
> 	at $RequestHandler_19bce9b13930.service(Unknown Source)
> 	at org.apache.tapestry5.services.TapestryModule$HttpServletRequestHandlerTerminator.service(TapestryModule.java:248)
> 	at org.apache.tapestry5.internal.gzip.GZipFilter.service(GZipFilter.java:53)
> 	at $HttpServletRequestHandler_19bce9b13932.service(Unknown Source)
> 	at org.apache.tapestry5.internal.services.IgnoredPathsFilter.service(IgnoredPathsFilter.java:62)
> 	at $HttpServletRequestFilter_19bce9b1392f.service(Unknown Source)
> 	at $HttpServletRequestHandler_19bce9b13932.service(Unknown Source)
> 	at org.apache.tapestry5.services.TapestryModule$1.service(TapestryModule.java:844)
> 	at $HttpServletRequestHandler_19bce9b13932.service(Unknown Source)
> 	at $HttpServletRequestHandler_19bce9b1392d.service(Unknown Source)
> 	at org.apache.tapestry5.TapestryFilter.doFilter(TapestryFilter.java:160)
> 	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1148)
> 	at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:387)
> 	at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
> 	at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
> 	at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
> 	at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
> 	at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
> 	at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
> 	at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
> 	at org.mortbay.jetty.Server.handle(Server.java:324)
> 	at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:535)
> 	at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:865)
> 	at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:539)
> 	at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
> 	at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
> 	at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
> 	at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:520)
> Caused by: java.lang.RuntimeException: Unable to locate Method public void setupRender(): com.example.newapp.pages.ChildA.setupRender()
> 	at org.apache.tapestry5.internal.plastic.MethodInvocationBundle.findMethod(MethodInvocationBundle.java:63)
> 	at org.apache.tapestry5.internal.plastic.MethodInvocationBundle.getMethod(MethodInvocationBundle.java:42)
> 	at org.apache.tapestry5.internal.plastic.AbstractMethodInvocation.getMethod(AbstractMethodInvocation.java:110)
> 	at org.apache.tapestry5.ioc.internal.services.MethodLogger.entry(MethodLogger.java:63)
> 	at org.apache.tapestry5.ioc.internal.services.LoggingAdvice.advise(LoggingAdvice.java:41)
> 	at org.apache.tapestry5.internal.plastic.AbstractMethodInvocation.proceed(AbstractMethodInvocation.java:86)
> 	at com.example.newapp.base.Parent.setupRender(Parent.java)
> 	at com.example.newapp.base.Parent.setupRender(Parent.java)
> 	at org.apache.tapestry5.internal.structure.ComponentPageElementImpl$SetupRenderPhase.invokeComponent(ComponentPageElementImpl.java:174)
> 	at org.apache.tapestry5.internal.structure.ComponentPageElementImpl$AbstractPhase.invoke(ComponentPageElementImpl.java:133)
> 	... 81 more
> Caused by: java.lang.NoSuchMethodException: com.example.newapp.pages.ChildA.setupRender()
> 	at java.lang.Class.getDeclaredMethod(Class.java:1954)
> 	at org.apache.tapestry5.internal.plastic.MethodInvocationBundle.findMethod(MethodInvocationBundle.java:59)
> 	... 90 more

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira