Tapestry
  1. Tapestry
  2. TAPESTRY-970

AssetEncoder fails to encode properly if path does not start with /

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 4.0.1
    • Fix Version/s: 4.1.1
    • Component/s: Framework
    • Labels:
      None
    • Environment:
      JDK 1.5.0_06, Tomcat 5.5.16, Linux 2.6

      Description

      Assets, which do not start with a /, are not properly encoded with the AssetEncoder when using Friendly URL's.

      When injecting a script, inside of the Classpath via the @InjectScript, we are seeing that the path is a relative path. IE, "com/company/components/ColorPicker.script". There is no / like on the Form component for its external script injections. In the asset encoder.

      The asset encoder assumes that the path starts with a /. You will then get the digest and the path collide because there is no seperator. There needs to be a check somewhere for this.

      AssetEncoder.java, Line 49

      // _path ends with a slash, path starts with one.

      // simple workaround, aviods copying path and uses literals
      String pathSeperator = "";
      if (!path.startsWith("/")) pathSeperator = "/";

      String fullPath = _path + "/" + digest + pathSeperator + path;

        Activity

        Hide
        Curtis Paris added a comment -

        If you are experiencing this problem, I have two work arounds for now.

        #1 is to stop using the asset encoder. Just remove the "asset-encoder" from your hivemodule.xml.

        #2 is to create your own encoder, and register it in your HiveModule.xml. Here is everything you should need:

        package com.company.tapestry;

        import org.apache.tapestry.Tapestry;
        import org.apache.tapestry.asset.AssetService;
        import org.apache.tapestry.engine.ServiceEncoding;
        import org.apache.tapestry.engine.encoders.AssetEncoder;
        import org.apache.tapestry.services.ServiceConstants;

        /**

        • Overloads the Tapestry 4.0 AssetEncoder to ensure that the path starts with a /
          */
          public class MyAssetEncoder extends AssetEncoder
          {
          public void encode(ServiceEncoding encoding) { if (!encoding.getParameterValue(ServiceConstants.SERVICE).equals(Tapestry.ASSET_SERVICE)) return; String path = encoding.getParameterValue(AssetService.PATH); if ((path != null) && (!path.startsWith("/"))) encoding.setParameterValue(AssetService.PATH, "/" + path); super.encode(encoding); }

          }

        hivemodule.xml changes:

        <!-- Workaround for Tapestry-970 Bug -->
        <service-point id="MyAssetEncoder" interface="org.apache.tapestry.engine.ServiceEncoder">
        <invoke-factory service-id="hivemind.BuilderFactory" model="singleton">
        <construct class="com.company.tapestry.MyAssetEncoder">
        <set property="path" value="/assets"/>
        </construct>
        </invoke-factory>
        </service-point>

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

        Show
        Curtis Paris added a comment - If you are experiencing this problem, I have two work arounds for now. #1 is to stop using the asset encoder. Just remove the "asset-encoder" from your hivemodule.xml. #2 is to create your own encoder, and register it in your HiveModule.xml. Here is everything you should need: package com.company.tapestry; import org.apache.tapestry.Tapestry; import org.apache.tapestry.asset.AssetService; import org.apache.tapestry.engine.ServiceEncoding; import org.apache.tapestry.engine.encoders.AssetEncoder; import org.apache.tapestry.services.ServiceConstants; /** Overloads the Tapestry 4.0 AssetEncoder to ensure that the path starts with a / */ public class MyAssetEncoder extends AssetEncoder { public void encode(ServiceEncoding encoding) { if (!encoding.getParameterValue(ServiceConstants.SERVICE).equals(Tapestry.ASSET_SERVICE)) return; String path = encoding.getParameterValue(AssetService.PATH); if ((path != null) && (!path.startsWith("/"))) encoding.setParameterValue(AssetService.PATH, "/" + path); super.encode(encoding); } } hivemodule.xml changes: <!-- Workaround for Tapestry-970 Bug --> <service-point id="MyAssetEncoder" interface="org.apache.tapestry.engine.ServiceEncoder"> <invoke-factory service-id="hivemind.BuilderFactory" model="singleton"> <construct class="com.company.tapestry.MyAssetEncoder"> <set property="path" value="/assets"/> </construct> </invoke-factory> </service-point> <contribution configuration-id="tapestry.url.ServiceEncoders"> <encoder id="asset" object="service:MyAssetEncoder"/> </contribution>
        Hide
        Curtis Paris added a comment -

        In my little code change, I forgot to show the null pointer check on the path.startsWith line. (I did a different work around for now and was just showing the example there).
        if ((path != null) && (!path.startsWith("/"))) pathSeperator = "/";

        Show
        Curtis Paris added a comment - In my little code change, I forgot to show the null pointer check on the path.startsWith line. (I did a different work around for now and was just showing the example there). if ((path != null) && (!path.startsWith("/"))) pathSeperator = "/";

          People

          • Assignee:
            Unassigned
            Reporter:
            Curtis Paris
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development