Tapestry
  1. Tapestry
  2. TAPESTRY-2177

Conversion of context parameters to server-side objects uses the TypeCoercer rather than the correct ValueEncoder

    Details

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

      Description

      TAPESTRY-2112 resulted in ValueEncoders being used to convert context parameters into strings for client-side representation.
      However, for form contexts, the strings are converted back into values via type coercion, rather than via ValueEncoder.

        Activity

        Hide
        Robert Zeigler added a comment -

        Sample stack trace (Exception is an "illegal argument exception": Could not find a coercion from String to xxx"):

        o org.apache.tapestry.ioc.internal.services.TypeCoercerImpl.findOrCreateCoercion(TypeCoercerImpl.java:246)
        o org.apache.tapestry.ioc.internal.services.TypeCoercerImpl.findCoercion(TypeCoercerImpl.java:168)
        o org.apache.tapestry.ioc.internal.services.TypeCoercerImpl.coerce(TypeCoercerImpl.java:120)
        o org.apache.tapestry.internal.structure.PageResourcesImpl.coerce(PageResourcesImpl.java:55)
        o org.apache.tapestry.internal.structure.ComponentPageElementImpl$14.get(ComponentPageElementImpl.java:951)
        o org.apache.tapestry.internal.services.ComponentEventImpl.coerceContext(ComponentEventImpl.java:67)
        o org.edkey.attendance.components.AttendanceEditor.dispatchComponentEvent(AttendanceEditor.java)
        o org.apache.tapestry.internal.structure.ComponentPageElementImpl.dispatchEvent(ComponentPageElementImpl.java:843)
        o org.apache.tapestry.internal.structure.ComponentPageElementImpl.triggerContextEvent(ComponentPageElementImpl.java:1004)
        o org.apache.tapestry.internal.structure.ComponentPageElementImpl.triggerEvent(ComponentPageElementImpl.java:934)
        o org.apache.tapestry.internal.structure.InternalComponentResourcesImpl.triggerEvent(InternalComponentResourcesImpl.java:154)
        o org.apache.tapestry.corelib.components.Form.onAction(Form.java:314)
        o org.apache.tapestry.corelib.components.Form.dispatchComponentEvent(Form.java)
        o org.apache.tapestry.internal.structure.ComponentPageElementImpl.dispatchEvent(ComponentPageElementImpl.java:851)
        o org.apache.tapestry.internal.structure.ComponentPageElementImpl.triggerContextEvent(ComponentPageElementImpl.java:1004)
        o org.apache.tapestry.internal.services.ComponentEventRequestHandlerImpl.handle(ComponentEventRequestHandlerImpl.java:62)
        o org.apache.tapestry.internal.services.ImmediateActionRenderResponseFilter.handle(ImmediateActionRenderResponseFilter.java:42)
        o org.apache.tapestry.internal.services.AjaxFilter.handle(AjaxFilter.java:42)
        o org.apache.tapestry.services.TapestryModule$39.handle(TapestryModule.java:2073)
        o org.apache.tapestry.internal.services.ComponentEventDispatcher.dispatch(ComponentEventDispatcher.java:131)
        o org.apache.tapestry.services.TapestryModule$13.service(TapestryModule.java:911)
        o org.edkey.attendance.services.AppModule$3.service(AppModule.java:295)
        o org.apache.tapestry.internal.services.LocalizationFilter.service(LocalizationFilter.java:43)
        o org.apache.tapestry.services.TapestryModule$3.service(TapestryModule.java:529)
        o org.apache.tapestry.services.TapestryModule$2.service(TapestryModule.java:504)
        o org.apache.tapestry.internal.services.StaticFilesFilter.service(StaticFilesFilter.java:79)
        o org.apache.tapestry.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:93)
        o org.apache.tapestry.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:84)
        o org.apache.tapestry.ioc.internal.util.ConcurrentBarrier.withRead(ConcurrentBarrier.java:77)
        o org.apache.tapestry.internal.services.CheckForUpdatesFilter.service(CheckForUpdatesFilter.java:106)
        o org.apache.tapestry.services.TapestryModule$12.service(TapestryModule.java:891)
        o org.apache.tapestry.upload.internal.services.MultipartServletRequestFilter.service(MultipartServletRequestFilter.java:43)
        o org.apache.tapestry.internal.services.IgnoredPathsFilter.service(IgnoredPathsFilter.java:62)
        o org.apache.tapestry.TapestryFilter.doFilter(TapestryFilter.java:164)
        o org.mortbay.jetty.servlet.WebApplicationHandler$CachedChain.doFilter(WebApplicationHandler.java:821)
        o org.edkey.attendance.servlet.CayenneFilter.doFilter(CayenneFilter.java:86)
        o org.mortbay.jetty.servlet.WebApplicationHandler$CachedChain.doFilter(WebApplicationHandler.java:821)
        o org.mortbay.jetty.servlet.WebApplicationHandler.dispatch(WebApplicationHandler.java:471)
        o org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:568)
        o org.mortbay.http.HttpContext.handle(HttpContext.java:1530)
        o org.mortbay.jetty.servlet.WebApplicationContext.handle(WebApplicationContext.java:633)
        o org.mortbay.http.HttpContext.handle(HttpContext.java:1482)
        o org.mortbay.http.HttpServer.service(HttpServer.java:909)
        o org.mortbay.http.HttpConnection.service(HttpConnection.java:820)
        o org.mortbay.http.HttpConnection.handleNext(HttpConnection.java:986)
        o org.mortbay.http.HttpConnection.handle(HttpConnection.java:837)
        o org.mortbay.http.SocketListener.handleConnection(SocketListener.java:245)
        o org.mortbay.util.ThreadedServer.handle(ThreadedServer.java:357)
        o org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:534)

        Show
        Robert Zeigler added a comment - Sample stack trace (Exception is an "illegal argument exception": Could not find a coercion from String to xxx"): o org.apache.tapestry.ioc.internal.services.TypeCoercerImpl.findOrCreateCoercion(TypeCoercerImpl.java:246) o org.apache.tapestry.ioc.internal.services.TypeCoercerImpl.findCoercion(TypeCoercerImpl.java:168) o org.apache.tapestry.ioc.internal.services.TypeCoercerImpl.coerce(TypeCoercerImpl.java:120) o org.apache.tapestry.internal.structure.PageResourcesImpl.coerce(PageResourcesImpl.java:55) o org.apache.tapestry.internal.structure.ComponentPageElementImpl$14.get(ComponentPageElementImpl.java:951) o org.apache.tapestry.internal.services.ComponentEventImpl.coerceContext(ComponentEventImpl.java:67) o org.edkey.attendance.components.AttendanceEditor.dispatchComponentEvent(AttendanceEditor.java) o org.apache.tapestry.internal.structure.ComponentPageElementImpl.dispatchEvent(ComponentPageElementImpl.java:843) o org.apache.tapestry.internal.structure.ComponentPageElementImpl.triggerContextEvent(ComponentPageElementImpl.java:1004) o org.apache.tapestry.internal.structure.ComponentPageElementImpl.triggerEvent(ComponentPageElementImpl.java:934) o org.apache.tapestry.internal.structure.InternalComponentResourcesImpl.triggerEvent(InternalComponentResourcesImpl.java:154) o org.apache.tapestry.corelib.components.Form.onAction(Form.java:314) o org.apache.tapestry.corelib.components.Form.dispatchComponentEvent(Form.java) o org.apache.tapestry.internal.structure.ComponentPageElementImpl.dispatchEvent(ComponentPageElementImpl.java:851) o org.apache.tapestry.internal.structure.ComponentPageElementImpl.triggerContextEvent(ComponentPageElementImpl.java:1004) o org.apache.tapestry.internal.services.ComponentEventRequestHandlerImpl.handle(ComponentEventRequestHandlerImpl.java:62) o org.apache.tapestry.internal.services.ImmediateActionRenderResponseFilter.handle(ImmediateActionRenderResponseFilter.java:42) o org.apache.tapestry.internal.services.AjaxFilter.handle(AjaxFilter.java:42) o org.apache.tapestry.services.TapestryModule$39.handle(TapestryModule.java:2073) o org.apache.tapestry.internal.services.ComponentEventDispatcher.dispatch(ComponentEventDispatcher.java:131) o org.apache.tapestry.services.TapestryModule$13.service(TapestryModule.java:911) o org.edkey.attendance.services.AppModule$3.service(AppModule.java:295) o org.apache.tapestry.internal.services.LocalizationFilter.service(LocalizationFilter.java:43) o org.apache.tapestry.services.TapestryModule$3.service(TapestryModule.java:529) o org.apache.tapestry.services.TapestryModule$2.service(TapestryModule.java:504) o org.apache.tapestry.internal.services.StaticFilesFilter.service(StaticFilesFilter.java:79) o org.apache.tapestry.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:93) o org.apache.tapestry.internal.services.CheckForUpdatesFilter$2.invoke(CheckForUpdatesFilter.java:84) o org.apache.tapestry.ioc.internal.util.ConcurrentBarrier.withRead(ConcurrentBarrier.java:77) o org.apache.tapestry.internal.services.CheckForUpdatesFilter.service(CheckForUpdatesFilter.java:106) o org.apache.tapestry.services.TapestryModule$12.service(TapestryModule.java:891) o org.apache.tapestry.upload.internal.services.MultipartServletRequestFilter.service(MultipartServletRequestFilter.java:43) o org.apache.tapestry.internal.services.IgnoredPathsFilter.service(IgnoredPathsFilter.java:62) o org.apache.tapestry.TapestryFilter.doFilter(TapestryFilter.java:164) o org.mortbay.jetty.servlet.WebApplicationHandler$CachedChain.doFilter(WebApplicationHandler.java:821) o org.edkey.attendance.servlet.CayenneFilter.doFilter(CayenneFilter.java:86) o org.mortbay.jetty.servlet.WebApplicationHandler$CachedChain.doFilter(WebApplicationHandler.java:821) o org.mortbay.jetty.servlet.WebApplicationHandler.dispatch(WebApplicationHandler.java:471) o org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:568) o org.mortbay.http.HttpContext.handle(HttpContext.java:1530) o org.mortbay.jetty.servlet.WebApplicationContext.handle(WebApplicationContext.java:633) o org.mortbay.http.HttpContext.handle(HttpContext.java:1482) o org.mortbay.http.HttpServer.service(HttpServer.java:909) o org.mortbay.http.HttpConnection.service(HttpConnection.java:820) o org.mortbay.http.HttpConnection.handleNext(HttpConnection.java:986) o org.mortbay.http.HttpConnection.handle(HttpConnection.java:837) o org.mortbay.http.SocketListener.handleConnection(SocketListener.java:245) o org.mortbay.util.ThreadedServer.handle(ThreadedServer.java:357) o org.mortbay.util.ThreadPool$PoolThread.run(ThreadPool.java:534)
        Hide
        Howard M. Lewis Ship added a comment -

        Ah, generally, when a component triggers and event, it is correct to use TypeCoercer and not ValueEncoder. ValueEncoder is only intended for the case where the values are starting as strings in the URL or form submission, not when they start as arbitrary objects.

        However, the point here is that the Form is triggering a new event with the same values, and its still an array of Strings.

        Let me see what I can do; I think the right option is to expose the EventContext.

        Show
        Howard M. Lewis Ship added a comment - Ah, generally, when a component triggers and event, it is correct to use TypeCoercer and not ValueEncoder. ValueEncoder is only intended for the case where the values are starting as strings in the URL or form submission, not when they start as arbitrary objects. However, the point here is that the Form is triggering a new event with the same values, and its still an array of Strings. Let me see what I can do; I think the right option is to expose the EventContext.
        Hide
        Robert Zeigler added a comment -

        Currently working on a test case to illustrate the issue.

        IN terms of the strings from a url, that's exactly what's going on, but it's not going through the URLEventContext. It's going through an anonymous class in the PageResourcesImpl.

        So you have a situation such as:

        <form t:id="form">
        ...
        </form>

        And in the .java:

        @Component(parameters="context=formContext")
        private Form _form;

        public List<?> getFormContext()

        { return Arrays.asList(property1,property2); }

        Those values are then encoded into the submission url for the form, so the final html looks like:

        <form action="/app/page.form/valueEncodedProperty1/valueEncodedProperty2">
        ...
        </form>

        So then if you have something like:

        onPrepareForSubmitFromForm(MyType1 property1, MyType2 property2) {
        }

        You'll hit the above mentioned stack trace, because the values from the form context were encoded to string (using value encoders), but the decoding is done via type coercion directly.

        Hopefully that makes more sense now.
        Again, working on a test case for this now.

        Show
        Robert Zeigler added a comment - Currently working on a test case to illustrate the issue. IN terms of the strings from a url, that's exactly what's going on, but it's not going through the URLEventContext. It's going through an anonymous class in the PageResourcesImpl. So you have a situation such as: <form t:id="form"> ... </form> And in the .java: @Component(parameters="context=formContext") private Form _form; public List<?> getFormContext() { return Arrays.asList(property1,property2); } Those values are then encoded into the submission url for the form, so the final html looks like: <form action="/app/page.form/valueEncodedProperty1/valueEncodedProperty2"> ... </form> So then if you have something like: onPrepareForSubmitFromForm(MyType1 property1, MyType2 property2) { } You'll hit the above mentioned stack trace, because the values from the form context were encoded to string (using value encoders), but the decoding is done via type coercion directly. Hopefully that makes more sense now. Again, working on a test case for this now.
        Hide
        Robert Zeigler added a comment -

        You want the test I wrote, since you've already closed this? (I didn't see any tests in the corresponding svn commit; I have run the test against these changes and it passes now).

        Show
        Robert Zeigler added a comment - You want the test I wrote, since you've already closed this? (I didn't see any tests in the corresponding svn commit; I have run the test against these changes and it passes now).

          People

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

            Dates

            • Created:
              Updated:
              Resolved:

              Development