Tapestry
  1. Tapestry
  2. TAPESTRY-2184

Null pointer exception when creating an action link during a component event request

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 5.0.10
    • Fix Version/s: 5.0.11
    • Component/s: tapestry-core
    • Labels:
      None

      Description

      createActionLink cause exception when it is called in the page class(see onActionFromDelete), but works when it is called from the template, this works in 5.0.6 and 7, but fails in 5.0.9 and 5.0.10, sample code and error follows:

      public class TestPage1 {
      @Inject
      private ComponentResources resources;
      private Object[] _objs;
      public Class onActivate(Object[] obj)

      { _objs = obj; return null; }

      public Object[] onPassivate()

      { return _objs;}

      Link onActionFromDelete(Long id)

      { String x = getTheLink(); // this fails with exception return null; }

      public String getTheLink()

      { Link l = resources.createActionLink("DeleteConfirm", false); return l.toURI(); }

      public Object onDeleteConfirm(Long id)

      { return null; }

      }

      template:

      <body>
      <t:ActionLink t:id="Delete" context="1">Delete me</t:ActionLink><br />
      <p>My Link is : $

      {theLink}

      </p>
      </body>

      errors:

      java.lang.NullPointerException
      Stack trace

      • org.apache.tapestry.internal.services.LinkFactoryImpl.collectActivationContextForPage(LinkFactoryImpl.java:217)
      • org.apache.tapestry.internal.services.LinkFactoryImpl.createActionLink(LinkFactoryImpl.java:129)
      • org.apache.tapestry.internal.structure.PageImpl.createActionLink(PageImpl.java:156)

        Activity

        Transition Time In Source Status Execution Times Last Executer Last Execution Date
        Open Open In Progress In Progress
        1d 14h 30m 1 Howard M. Lewis Ship 22/Feb/08 23:06
        In Progress In Progress Closed Closed
        35m 59s 1 Howard M. Lewis Ship 22/Feb/08 23:42
        Mark Thomas made changes -
        Workflow Default workflow, editable Closed status [ 12569370 ] jira [ 12592160 ]
        Mark Thomas made changes -
        Workflow jira [ 12424093 ] Default workflow, editable Closed status [ 12569370 ]
        Hide
        Robert Zeigler added a comment -

        Not quite sure what you mean by "current page", but...
        suppose you have, say, a view block contribution, or edit block contribution, that creates an action link; it'll be in a page, say, ViewBlocks, but the rendering page might be, say, ListOrders. So then if the action handler in ViewBlocks is called, and it, in turn, calls createActionLink, would the "active" page be ViewBlocks, or ListOrders?
        It ought to be ListOrders, but...

        Show
        Robert Zeigler added a comment - Not quite sure what you mean by "current page", but... suppose you have, say, a view block contribution, or edit block contribution, that creates an action link; it'll be in a page, say, ViewBlocks, but the rendering page might be, say, ListOrders. So then if the action handler in ViewBlocks is called, and it, in turn, calls createActionLink, would the "active" page be ViewBlocks, or ListOrders? It ought to be ListOrders, but...
        Howard M. Lewis Ship made changes -
        Resolution Fixed [ 1 ]
        Fix Version/s 5.0.11 [ 12312968 ]
        Status In Progress [ 3 ] Closed [ 6 ]
        Howard M. Lewis Ship made changes -
        Summary Invoking createActionLink() in code throws an NullPointerException even though using an ActionLink component in the template does not Null pointer exception when creating an action link during a component event request
        Hide
        Howard M. Lewis Ship added a comment -

        Ok, this does fail:

        public class ActionViaLinkDemo
        {
        @Persist("flash")
        private String _message;

        @Inject
        private ComponentResources _resources;

        Object[]
        onPassivate()
        {
        return new Object[] { };
        }

        public String getMessage()

        { return _message; }

        void onUpdateMessage(String message)

        { getActionURL(); _message = message; }

        public String getActionURL()

        { Link link = _resources.createActionLink("UpdateMessage", false, "from getActionURL()"); return link.toURI(); }

        }

        Which fails inside onUpdateMessage() with:

        java.lang.NullPointerException
        at org.apache.tapestry.internal.services.LinkFactoryImpl.collectActivationContextForPage(LinkFactoryImpl.java:225)
        at org.apache.tapestry.internal.services.LinkFactoryImpl.createActionLink(LinkFactoryImpl.java:134)
        at $LinkFactory_118435737b9.createActionLink($LinkFactory_118435737b9.java)
        at org.apache.tapestry.internal.structure.PageImpl.createActionLink(PageImpl.java:156)
        at org.apache.tapestry.internal.structure.InternalComponentResourcesImpl.createActionLink(InternalComponentResourcesImpl.java:123)
        at org.apache.tapestry.integration.app1.pages.ActionViaLinkDemo.getActionURL(ActionViaLinkDemo.java:36)
        at org.apache.tapestry.integration.app1.pages.ActionViaLinkDemo.onUpdateMessage(ActionViaLinkDemo.java:29)
        at org.apache.tapestry.integration.app1.pages.ActionViaLinkDemo.dispatchComponentEvent(ActionViaLinkDemo.java)
        at org.apache.tapestry.internal.structure.ComponentPageElementImpl.dispatchEvent(ComponentPageElementImpl.java:843)
        at org.apache.tapestry.internal.structure.ComponentPageElementImpl.triggerContextEvent(ComponentPageElementImpl.java:1004)

        And here's the culprit:

        Page activePage = _pageRenderQueue.getRenderingPage();

        Which is broken when there is no rendering page.

        We'll just assume, for the moment, that the current page is the active page. There's probably some obscure edge case where that won't work, but I can't quite envision it right now.

        Show
        Howard M. Lewis Ship added a comment - Ok, this does fail: public class ActionViaLinkDemo { @Persist("flash") private String _message; @Inject private ComponentResources _resources; Object[] onPassivate() { return new Object[] { }; } public String getMessage() { return _message; } void onUpdateMessage(String message) { getActionURL(); _message = message; } public String getActionURL() { Link link = _resources.createActionLink("UpdateMessage", false, "from getActionURL()"); return link.toURI(); } } Which fails inside onUpdateMessage() with: java.lang.NullPointerException at org.apache.tapestry.internal.services.LinkFactoryImpl.collectActivationContextForPage(LinkFactoryImpl.java:225) at org.apache.tapestry.internal.services.LinkFactoryImpl.createActionLink(LinkFactoryImpl.java:134) at $LinkFactory_118435737b9.createActionLink($LinkFactory_118435737b9.java) at org.apache.tapestry.internal.structure.PageImpl.createActionLink(PageImpl.java:156) at org.apache.tapestry.internal.structure.InternalComponentResourcesImpl.createActionLink(InternalComponentResourcesImpl.java:123) at org.apache.tapestry.integration.app1.pages.ActionViaLinkDemo.getActionURL(ActionViaLinkDemo.java:36) at org.apache.tapestry.integration.app1.pages.ActionViaLinkDemo.onUpdateMessage(ActionViaLinkDemo.java:29) at org.apache.tapestry.integration.app1.pages.ActionViaLinkDemo.dispatchComponentEvent(ActionViaLinkDemo.java) at org.apache.tapestry.internal.structure.ComponentPageElementImpl.dispatchEvent(ComponentPageElementImpl.java:843) at org.apache.tapestry.internal.structure.ComponentPageElementImpl.triggerContextEvent(ComponentPageElementImpl.java:1004) And here's the culprit: Page activePage = _pageRenderQueue.getRenderingPage(); Which is broken when there is no rendering page. We'll just assume, for the moment, that the current page is the active page. There's probably some obscure edge case where that won't work, but I can't quite envision it right now.
        Howard M. Lewis Ship made changes -
        Summary createActionLink cause exception when it is called in the page class, but works when it is called from the template. Invoking createActionLink() in code throws an NullPointerException even though using an ActionLink component in the template does not
        Hide
        Howard M. Lewis Ship added a comment -

        So far I can't get this to fail the way you list it, short of:

        Object[] onPassivate() { return new Object[]

        { null }

        ; }

        Which fails a bit differently:

        java.lang.IllegalArgumentException: Parameter value was null.
        at org.apache.tapestry.ioc.internal.util.Defense.notNull(Defense.java:37)
        at org.apache.tapestry.internal.services.ContextValueEncoderImpl.toClient(ContextValueEncoderImpl.java:33)
        at $ContextValueEncoder_118435737b3.toClient($ContextValueEncoder_118435737b3.java)
        at org.apache.tapestry.internal.services.LinkFactoryImpl.toContextStrings(LinkFactoryImpl.java:239)
        at org.apache.tapestry.internal.services.LinkFactoryImpl.collectActivationContextForPage(LinkFactoryImpl.java:229)
        at org.apache.tapestry.internal.services.LinkFactoryImpl.createActionLink(LinkFactoryImpl.java:134)
        at $LinkFactory_118435737b9.createActionLink($LinkFactory_118435737b9.java)
        at org.apache.tapestry.internal.structure.PageImpl.createActionLink(PageImpl.java:156)
        at org.apache.tapestry.internal.structure.InternalComponentResourcesImpl.createActionLink(InternalComponentResourcesImpl.java:123)
        at org.apache.tapestry.integration.app1.pages.ActionViaLinkDemo.getActionURL(ActionViaLinkDemo.java:34)
        at $PropertyConduit_11843573b25.get($PropertyConduit_11843573b25.java)
        at org.apache.tapestry.internal.bindings.PropBinding.get(PropBinding.java:54)

        Show
        Howard M. Lewis Ship added a comment - So far I can't get this to fail the way you list it, short of: Object[] onPassivate() { return new Object[] { null } ; } Which fails a bit differently: java.lang.IllegalArgumentException: Parameter value was null. at org.apache.tapestry.ioc.internal.util.Defense.notNull(Defense.java:37) at org.apache.tapestry.internal.services.ContextValueEncoderImpl.toClient(ContextValueEncoderImpl.java:33) at $ContextValueEncoder_118435737b3.toClient($ContextValueEncoder_118435737b3.java) at org.apache.tapestry.internal.services.LinkFactoryImpl.toContextStrings(LinkFactoryImpl.java:239) at org.apache.tapestry.internal.services.LinkFactoryImpl.collectActivationContextForPage(LinkFactoryImpl.java:229) at org.apache.tapestry.internal.services.LinkFactoryImpl.createActionLink(LinkFactoryImpl.java:134) at $LinkFactory_118435737b9.createActionLink($LinkFactory_118435737b9.java) at org.apache.tapestry.internal.structure.PageImpl.createActionLink(PageImpl.java:156) at org.apache.tapestry.internal.structure.InternalComponentResourcesImpl.createActionLink(InternalComponentResourcesImpl.java:123) at org.apache.tapestry.integration.app1.pages.ActionViaLinkDemo.getActionURL(ActionViaLinkDemo.java:34) at $PropertyConduit_11843573b25.get($PropertyConduit_11843573b25.java) at org.apache.tapestry.internal.bindings.PropBinding.get(PropBinding.java:54)
        Howard M. Lewis Ship made changes -
        Status Open [ 1 ] In Progress [ 3 ]
        Howard M. Lewis Ship made changes -
        Field Original Value New Value
        Assignee Howard M. Lewis Ship [ hlship ]
        Hide
        Ted Steen added a comment -

        @Davor Hrg, That was my solution also, but as you say, maybe it will misbehave in other situations.

        resources.createActionLink(...) seem to work between setupRender() and cleanupRender().

        Show
        Ted Steen added a comment - @Davor Hrg, That was my solution also, but as you say, maybe it will misbehave in other situations. resources.createActionLink(...) seem to work between setupRender() and cleanupRender().
        Hide
        Davor Hrg added a comment -

        LinkFactoryImpl(line:127)

        Page activePage = _pageRenderQueue.getRenderingPage();

        this is null in this case ...
        I'm not sure if it is safe to assume:

        if(activePage == null) activePage = page;

        for this case this would be ok, but some other situation may misbehave ...

        Show
        Davor Hrg added a comment - LinkFactoryImpl(line:127) Page activePage = _pageRenderQueue.getRenderingPage(); this is null in this case ... I'm not sure if it is safe to assume: if(activePage == null) activePage = page; for this case this would be ok, but some other situation may misbehave ...
        Angelo Chen created issue -

          People

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

            Dates

            • Created:
              Updated:
              Resolved:

              Development