Click
  1. Click
  2. CLK-625

createPage makes htm-to-class duplicates

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.1.0
    • Fix Version/s: 2.3.0-M1
    • Component/s: core
    • Labels:
      None

      Description

      We have

      • ControlListenerType1Page.htm - in web root
        and
        ControlListenerType1Page.java with:

      @Bindable protected ActionLink bugMaker = new ActionLink(this, "makeBug");

      public boolean makeBug () {
      Page p = getContext().createPage("ControlListenerType1Page.htm");// without leading /
      if (!(p instanceof ControlListenerType1Page))

      { throw new Error("very bad"); }

      //successfully! BUT now htm-to-class map contains two mappings for ControlListenerType1Page.class:
      // ControlListenerType1Page.htm->ControlListenerType1Page.class and
      // /ControlListenerType1Page.htm->ControlListenerType1Page.class

      p = getContext().createPage(ControlListenerType1Page.class);
      //^^^throws java.lang.IllegalArgumentException with message:
      //Page class resolves to multiple paths: net.sf.apr.cui.ControlListenerType1Page -> [/ControlListenerType1Page.htm, ControlListenerType1Page.htm]

      setForward(p); return true;
      }

      1. CLK-625.patch
        0.7 kB
        Md. Jahid Shohel

        Activity

        Hide
        Andrew Fink added a comment -

        Page p = getContext().createPage("/ControlListenerType1Page.htm");// with leading /
        works (of course) fine.

        Show
        Andrew Fink added a comment - Page p = getContext().createPage("/ControlListenerType1Page.htm");// with leading / works (of course) fine.
        Hide
        Md. Jahid Shohel added a comment -

        I tried to re-create the problem. Seems like it was fixed or it was not a problem at all. I tried to re-create the problem with -

        HomePage homePage = (HomePage) getContext().createPage("home.htm"); //without leading /

        And that created an exception (and that is how it should be) -

        [Click] [error] handleException: java.lang.IllegalArgumentException: No Page class configured for path: home.htm
        at org.apache.click.ClickServlet.createPage(ClickServlet.java:1694)
        at org.apache.click.Context.createPage(Context.java:547)
        at com.working.DestinationPage.onLinkClick(DestinationPage.java:14)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.click.util.ClickUtils.invokeMethod(ClickUtils.java:2763)
        at org.apache.click.util.ClickUtils.invokeListener(ClickUtils.java:1747)
        at org.apache.click.util.ActionListenerAdaptor.onAction(ActionListenerAdaptor.java:59)
        at org.apache.click.ActionEventDispatcher.fireActionEvent(ActionEventDispatcher.java:240)
        at org.apache.click.ActionEventDispatcher.fireActionEvents(ActionEventDispatcher.java:217)
        at org.apache.click.ActionEventDispatcher.fireActionEvents(ActionEventDispatcher.java:146)
        at org.apache.click.ClickServlet.performOnProcess(ClickServlet.java:719)
        at org.apache.click.ClickServlet.processPageEvents(ClickServlet.java:607)
        at org.apache.click.ClickServlet.processPage(ClickServlet.java:561)
        at org.apache.click.ClickServlet.handleRequest(ClickServlet.java:383)
        at org.apache.click.ClickServlet.doGet(ClickServlet.java:276)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
        at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
        at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:390)
        at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
        at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
        at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
        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:326)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
        at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:926)
        at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)
        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:410)
        at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

        Show
        Md. Jahid Shohel added a comment - I tried to re-create the problem. Seems like it was fixed or it was not a problem at all. I tried to re-create the problem with - HomePage homePage = (HomePage) getContext().createPage("home.htm"); //without leading / And that created an exception (and that is how it should be) - [Click] [error] handleException: java.lang.IllegalArgumentException: No Page class configured for path: home.htm at org.apache.click.ClickServlet.createPage(ClickServlet.java:1694) at org.apache.click.Context.createPage(Context.java:547) at com.working.DestinationPage.onLinkClick(DestinationPage.java:14) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.click.util.ClickUtils.invokeMethod(ClickUtils.java:2763) at org.apache.click.util.ClickUtils.invokeListener(ClickUtils.java:1747) at org.apache.click.util.ActionListenerAdaptor.onAction(ActionListenerAdaptor.java:59) at org.apache.click.ActionEventDispatcher.fireActionEvent(ActionEventDispatcher.java:240) at org.apache.click.ActionEventDispatcher.fireActionEvents(ActionEventDispatcher.java:217) at org.apache.click.ActionEventDispatcher.fireActionEvents(ActionEventDispatcher.java:146) at org.apache.click.ClickServlet.performOnProcess(ClickServlet.java:719) at org.apache.click.ClickServlet.processPageEvents(ClickServlet.java:607) at org.apache.click.ClickServlet.processPage(ClickServlet.java:561) at org.apache.click.ClickServlet.handleRequest(ClickServlet.java:383) at org.apache.click.ClickServlet.doGet(ClickServlet.java:276) at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:390) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) 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:326) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:926) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549) 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:410) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
        Hide
        Md. Jahid Shohel added a comment -

        We can close this issue

        Show
        Md. Jahid Shohel added a comment - We can close this issue
        Hide
        Bob Schellink added a comment -

        Interesting, perhaps the error is specific to Tomcat or another servlet container?

        Show
        Bob Schellink added a comment - Interesting, perhaps the error is specific to Tomcat or another servlet container?
        Hide
        Andrew Fink added a comment -

        1) click.xml MODE must be development, debug or trace.

        In production/profile mode all works fine (throwing exception):
        java.lang.IllegalArgumentException: No Page class configured for path: ControlListenerType1Page.htm

        2) I use Tomcat 6.0.20, so bug is still here.

        3) my debug:
        org.apache.click.service.XmlConfigService
        public Class<? extends Page> getPageClass(String path) {
        ...
        URL resource = servletContext.getResource(path);//ControlListenerType1Page.htm
        returns jndi:/localhost/clickDemo/ControlListenerType1Page.htm

        but this resource value is just checked for != null.

        I think Click can:

        • require leading / in createPage == same behavior in all modes
        • convert those relative paths to absolute paths (using path from current Context.Request). May fall in production...
        Show
        Andrew Fink added a comment - 1) click.xml MODE must be development, debug or trace. In production/profile mode all works fine (throwing exception): java.lang.IllegalArgumentException: No Page class configured for path: ControlListenerType1Page.htm 2) I use Tomcat 6.0.20, so bug is still here. 3) my debug: org.apache.click.service.XmlConfigService public Class<? extends Page> getPageClass(String path) { ... URL resource = servletContext.getResource(path);//ControlListenerType1Page.htm returns jndi:/localhost/clickDemo/ControlListenerType1Page.htm but this resource value is just checked for != null. I think Click can: require leading / in createPage == same behavior in all modes convert those relative paths to absolute paths (using path from current Context.Request). May fall in production...
        Hide
        Andrew Fink added a comment -

        >- require leading / in createPage == same behavior in all modes

        I don't know, should all paths start with leading /. If not then of course It isn't solution.

        Show
        Andrew Fink added a comment - >- require leading / in createPage == same behavior in all modes I don't know, should all paths start with leading /. If not then of course It isn't solution.
        Hide
        Md. Jahid Shohel added a comment -

        ok, i will check again in development mode

        Show
        Md. Jahid Shohel added a comment - ok, i will check again in development mode
        Hide
        Md. Jahid Shohel added a comment - - edited

        Ok, I was investigating the issue. First of all the problem does not happen on jetty, so I was not getting any error.

        Now for "servletContext.getResource(path)" Jetty returns null, and Tomcat returns non null value (even if the pat does not start with /).

        The Servlet specification says -

        "The path must begin with a / and is interpreted as relative to the current context root"

        Which means, this is a bug on Tomcat.

        We can solve the issue but checking if the path starts with "/", and if not then we add a "/" before processing. But I do not think that we should do that. But instead we should follow the Servlet specification. In our code we have clear path defined for null as return value. Which is throwing IllegalArgumentException for null values.

        Show
        Md. Jahid Shohel added a comment - - edited Ok, I was investigating the issue. First of all the problem does not happen on jetty, so I was not getting any error. Now for "servletContext.getResource(path)" Jetty returns null, and Tomcat returns non null value (even if the pat does not start with /). The Servlet specification says - "The path must begin with a / and is interpreted as relative to the current context root" Which means, this is a bug on Tomcat. We can solve the issue but checking if the path starts with "/", and if not then we add a "/" before processing. But I do not think that we should do that. But instead we should follow the Servlet specification. In our code we have clear path defined for null as return value. Which is throwing IllegalArgumentException for null values.
        Hide
        Bob Schellink added a comment -

        I agree, we should adhere to the spec on this and fail fast if the path does not start with a '/'. We can add the check to ClickServlet#createPage and update the javadoc of Context#createPage and ClickServlet#createPage to mention this.

        Show
        Bob Schellink added a comment - I agree, we should adhere to the spec on this and fail fast if the path does not start with a '/'. We can add the check to ClickServlet#createPage and update the javadoc of Context#createPage and ClickServlet#createPage to mention this.
        Hide
        Md. Jahid Shohel added a comment -

        Added condition to fail fast if the path does not start with /

        Show
        Md. Jahid Shohel added a comment - Added condition to fail fast if the path does not start with /
        Hide
        Bob Schellink added a comment -

        fixed in trunk. I only applied to change to Context.createPage. XmlConfigService shouldn't concern itself with this since Context.createPage(String) is only rarely used.

        Show
        Bob Schellink added a comment - fixed in trunk. I only applied to change to Context.createPage. XmlConfigService shouldn't concern itself with this since Context.createPage(String) is only rarely used.

          People

          • Assignee:
            Bob Schellink
            Reporter:
            Andrew Fink
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development