Tapestry
  1. Tapestry
  2. TAPESTRY-796

page-service-encoder for external service no longer working

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 4.0
    • Fix Version/s: 4.1.5
    • Component/s: Framework
    • Labels:
      None
    • Environment:
      4.0rc1, Tomcat 5.5.9, OS X 10.4.3

      Description

      Using the page-service-encoder to map a file extension to the external page service no longer works.

      If I create these three files, the Home page correctly links to Page 2:

      Home.html:

      <html>
      <body>
      <h1>Home Page</h1>
      <a href="#" jwcid="@ExternalLink" page="Page2">Page 2</a>
      </html>

      Page2.html:

      <html>
      <body>
      <h1>Page 2</h1>
      </html>

      Page2.java:

      // insert default page package and imports here
      public class Page2 extends BasePage implements IExternalPage {
      public void activateExternalPage(Object[] x, IRequestCycle y) { }
      }

      However, if I add this single configuration to my Hivemodule:

      <contribution configuration-id="tapestry.url.ServiceEncoders">
      <page-service-encoder id="external" extension="html" service="external" />
      </contribution>

      ...then every link goes to the home page. The link on Home correctly gets encoded as /myapp/Page2.html, but that request just brings up the Home page again.

      No errors appear in the log file.

      The Tapestry servlet is mapped in web.xml as follows:

      <servlet>
      <servlet-name>tapestry</servlet-name>
      <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
      <servlet-name>tapestry</servlet-name> <url-pattern>/*</url-pattern>
      </servlet-mapping>

      This didn't get a response on the user mailing list, so I'm presuming it's a legitimate bug.

      This worked in Tapestry 4.0b6, but broken when I upgraded to rc1.

        Activity

        Hide
        Howard M. Lewis Ship added a comment -

        Where are your extension mappings in web.xml? For each extension you map in hivemodule.xml, you must (alas) make a corresponding addition to web.xml. Please check the documentation.

        Show
        Howard M. Lewis Ship added a comment - Where are your extension mappings in web.xml? For each extension you map in hivemodule.xml, you must (alas) make a corresponding addition to web.xml. Please check the documentation.
        Hide
        Paul Cantrell added a comment -

        I am aware of the need for mapping in web.xml; I have it mapped as follows:

        <servlet>
        <servlet-name>tapestry</servlet-name>
        <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
        <servlet-name>tapestry</servlet-name> <url-pattern>/*</url-pattern>
        </servlet-mapping>

        Two factors suggest that web.xml is irrelevant:

        (1) If you read the statement of the problem carefully, you'll see that requests are making to Tapestry. The problem is not that the links give an error; instead they show the Tapestry app's home page. But the home page does show up, and Tapestry is generating. So the mapping is correct.

        (2) This worked until I upgraded Tapestry. Nothing in web.xml changed.

        Show
        Paul Cantrell added a comment - I am aware of the need for mapping in web.xml; I have it mapped as follows: <servlet> <servlet-name>tapestry</servlet-name> <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>tapestry</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> Two factors suggest that web.xml is irrelevant: (1) If you read the statement of the problem carefully, you'll see that requests are making to Tapestry. The problem is not that the links give an error; instead they show the Tapestry app's home page. But the home page does show up, and Tapestry is generating. So the mapping is correct. (2) This worked until I upgraded Tapestry. Nothing in web.xml changed.
        Hide
        Paul Cantrell added a comment -

        Just to be sure, I commented out all servlet filters and made the mapping above the only config in my web.xml. The problem remained.

        Show
        Paul Cantrell added a comment - Just to be sure, I commented out all servlet filters and made the mapping above the only config in my web.xml. The problem remained.
        Hide
        Howard M. Lewis Ship added a comment -

        I'm very glad that you were able to get Tapestry to work in your environment using incorrect and invalid configuration. It is not a bug that your configuration, which does not match the documentation, no longer works in a later release (due to a real bug fix).

        Show
        Howard M. Lewis Ship added a comment - I'm very glad that you were able to get Tapestry to work in your environment using incorrect and invalid configuration. It is not a bug that your configuration, which does not match the documentation, no longer works in a later release (due to a real bug fix).
        Hide
        Paul Cantrell added a comment -

        Howard, please, there's no need to be so snotty. I floated my problem on the user list (without a response), did in fact check the documentation, and decided that the behavior I was seeing was genuinely incorrect. I submitted this bug in good faith; I meant no disrespect by it.

        So yes, it seems that mapping all my URL patterns individually does fix the problem:

        <servlet-mapping>
        <servlet-name>tapestry</servlet-name>
        <url-pattern>*.html</url-pattern>
        </servlet-mapping>

        ...but because I make extensive use of custom URL encodings, my app is going to end up having an awful wad of these mappings. And because every URL in the app is meant to go through Tapestry, it seemed simpler just to use a single /* mapping. (If I really enjoyed having scads of XML configuration, I'd be using Struts!)

        Yes, I'm not copying the documentation verbatim, but as far as I can tell, this is a perfectly reasonable approach based on what documentation says. I'm afraid I presumed it would not be an issue – if the request makes it to Tapestry, then Tapestry can parse it all by itself, right?

        Well, wrong, obviously. However, I can't find anything in the documentation that explains why, or warns against this.

        If this is not a "real" bug, it is at least a "real" undesired behavior. At the very least, the documentation should explicitly state what kinds of mappings are permissible. At best, Tapestry should deal with any URL that comes its way, and give developers the flexibility to fight configuration sprawl.

        Again, please, I mean no disrespect to the excellent work of the Tapestry team. I simply think that what I'm trying to do is reasonable, and Tapestry should either support it, or explain clearly why it cannot work. That's all. Hang in there, Howard; your users are your friends.

        Cheers,

        Paul

        Show
        Paul Cantrell added a comment - Howard, please, there's no need to be so snotty. I floated my problem on the user list (without a response), did in fact check the documentation, and decided that the behavior I was seeing was genuinely incorrect. I submitted this bug in good faith; I meant no disrespect by it. So yes, it seems that mapping all my URL patterns individually does fix the problem: <servlet-mapping> <servlet-name>tapestry</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> ...but because I make extensive use of custom URL encodings, my app is going to end up having an awful wad of these mappings. And because every URL in the app is meant to go through Tapestry, it seemed simpler just to use a single /* mapping. (If I really enjoyed having scads of XML configuration, I'd be using Struts!) Yes, I'm not copying the documentation verbatim, but as far as I can tell, this is a perfectly reasonable approach based on what documentation says. I'm afraid I presumed it would not be an issue – if the request makes it to Tapestry, then Tapestry can parse it all by itself, right? Well, wrong, obviously. However, I can't find anything in the documentation that explains why, or warns against this. If this is not a "real" bug, it is at least a "real" undesired behavior. At the very least, the documentation should explicitly state what kinds of mappings are permissible. At best, Tapestry should deal with any URL that comes its way, and give developers the flexibility to fight configuration sprawl. Again, please, I mean no disrespect to the excellent work of the Tapestry team. I simply think that what I'm trying to do is reasonable, and Tapestry should either support it, or explain clearly why it cannot work. That's all. Hang in there, Howard; your users are your friends. Cheers, Paul
        Hide
        Michael Frericks added a comment -

        had to face the problem, too. My application uses a different servlet-path for each user.
        I solved this problem by contributing an own org.apache.tapestry.engine.ServiceEncoder:

        public class ServletPathEncoder implements ServiceEncoder
        {
        private String _extension;
        private String _servletPath;

        public void decode(ServiceEncoding encoding)
        {
        if (!encoding.getServletPath().endsWith(_extension))

        { return; }

        _servletPath = encoding.getServletPath();
        }

        public void encode(ServiceEncoding encoding)

        { encoding.setServletPath(_servletPath); }

        public void setExtension(String string)

        { _extension = string; }

        }

        <service-point
        id="ServletPathEncoder"
        interface="org.apache.tapestry.engine.ServiceEncoder">

        <invoke-factory service-id="hivemind.BuilderFactory" model="threaded">
        <construct class="ServletPathEncoder" >
        <set
        property="extension"
        value="yourExtension" />
        </construct>
        </invoke-factory>
        </service-point>

        <contribution configuration-id="tapestry.url.ServiceEncoders">
        <encoder id="servletPathEncoder" object="service:ServletPathEncoder"/>
        </contribution>

        Show
        Michael Frericks added a comment - had to face the problem, too. My application uses a different servlet-path for each user. I solved this problem by contributing an own org.apache.tapestry.engine.ServiceEncoder: public class ServletPathEncoder implements ServiceEncoder { private String _extension; private String _servletPath; public void decode(ServiceEncoding encoding) { if (!encoding.getServletPath().endsWith(_extension)) { return; } _servletPath = encoding.getServletPath(); } public void encode(ServiceEncoding encoding) { encoding.setServletPath(_servletPath); } public void setExtension(String string) { _extension = string; } } <service-point id="ServletPathEncoder" interface="org.apache.tapestry.engine.ServiceEncoder"> <invoke-factory service-id="hivemind.BuilderFactory" model="threaded"> <construct class="ServletPathEncoder" > <set property="extension" value="yourExtension" /> </construct> </invoke-factory> </service-point> <contribution configuration-id="tapestry.url.ServiceEncoders"> <encoder id="servletPathEncoder" object="service:ServletPathEncoder"/> </contribution>
        Hide
        Andreas Andreou added a comment -

        Dont think we should carry this along any more.

        Show
        Andreas Andreou added a comment - Dont think we should carry this along any more.

          People

          • Assignee:
            Unassigned
            Reporter:
            Paul Cantrell
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development