[ 
https://issues.apache.org/jira/browse/WICKET-6823?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17187604#comment-17187604
 ] 

Martin Tzvetanov Grigorov commented on WICKET-6823:
---------------------------------------------------

The discussion whether to change the order of the execution of the behaviors' 
afterRender() should be moved now to dev@.

IMO it is too risky and we should leave it for Wicket 10 to experiment more 
with it.

> Two instances of AbstractTransformerBehavior on the same component results in 
> incomplete output.
> ------------------------------------------------------------------------------------------------
>
>                 Key: WICKET-6823
>                 URL: https://issues.apache.org/jira/browse/WICKET-6823
>             Project: Wicket
>          Issue Type: Bug
>          Components: wicket-core
>    Affects Versions: 8.9.0
>            Reporter: Thorsten Schöning
>            Assignee: Sven Meier
>            Priority: Major
>         Attachments: multiple_abstract_transformer_behavior.zip
>
>
> I'm using Wicket as a renderer for HTML-reports WITHOUT browser, web server 
> or requests, only by using ComponentRenderer. There are two implementations 
> of AbstractTransformerBehavior to update "colspan" attributes of table cells 
> and IDs of arbitrary HTML nodes. Both are used on the same component:
> {noformat}
> resultsCont.add(new DvResultsCont.ColSpanUpdater());
> resultsCont.add(new MkIdReplacer
> (
>   "th", "id", "td", "headers",
>   String.format("%d.%s", itemIdx, kindOfDetail)
> ));
> {noformat}
> When only ONE of both behaviours is used, the page renders successfully and 
> it doesn't make any difference which one is used. If both of those are used 
> OTOH, the page seems to be rendered at all as well, but some rendered content 
> is simply missing in the overall output in the end. My component 
> "resultsCont" renders to a table, so the last markup I have is the following:
> {noformat}
> <table class="detailsMeters ui-expandable ui-expandable-collapsed missing">
> [...]
> </table>
> {noformat}
> In theory, after that table there should be additional content like foots, 
> closing elements for HTML itself etc. So the current rendering is invalid. 
> It's important to note, though, that I don't get any exception, the output 
> simply seems to not contain all data. When enabling DEBUG logging during 
> rendering, the logs make pretty much clear that Wicket really tries to 
> continue rendering, but the output is simply missing.
> As no exceptions are thrown and output seems to simply be ignored at some 
> point, I have the feeling the problem is in handling the response objects in 
> "AbstractTransformerBehavior". All of those assigned transformers to some 
> component are called before actually rendering anything and change the 
> response. "Component.java" contains the following code:
> {noformat}
> /**
>  * {@link Behavior#beforeRender(Component)} Notify all behaviors that are 
> assigned to this
>  * component that the component is about to be rendered.
>  */
> private void notifyBehaviorsComponentBeforeRender()
> {
>       for (Behavior behavior : getBehaviors())
>       {
>               if (isBehaviorAccepted(behavior))
>               {
>                       behavior.beforeRender(this);
>               }
>       }
> }
> {noformat}
> Each call to "beforeRender" changes the response and all those changes are 
> done one after another. This means that the current request to render two 
> will be that one of the LAST applied transformer only.
> {noformat}
> @Override
> public void beforeRender(Component component)
> {
>       super.beforeRender(component);
>       final RequestCycle requestCycle = RequestCycle.get();
>       // Temporarily replace the web response with a String response
>       originalResponse = requestCycle.getResponse();
>       WebResponse origResponse = (WebResponse)((originalResponse instanceof 
> WebResponse)
>               ? originalResponse : null);
>       BufferedWebResponse tempResponse = newResponse(origResponse);
>       // temporarily set StringResponse to collect the transformed output
>       requestCycle.setResponse(tempResponse);
> }
> {noformat}
> Only after all those changes to the current request, content is rendered and 
> transformed, using the current request AND changing it back to what each 
> individual transformer believes to be the original request.
> {noformat}
> @Override
> public void afterRender(final Component component)
> {
>       final RequestCycle requestCycle = RequestCycle.get();
>       try
>       {
>               BufferedWebResponse tempResponse = 
> (BufferedWebResponse)requestCycle.getResponse();
>               if (component instanceof Page && originalResponse instanceof 
> WebResponse)
>               {
>                       tempResponse.writeMetaData((WebResponse) 
> originalResponse);
>               }
>               // Transform the data
>               CharSequence output = transform(component, 
> tempResponse.getText());
>               originalResponse.write(output);
>       }
>       catch (Exception ex)
>       {
>               throw new WicketRuntimeException("Error while transforming the 
> output of component: " +
>                       component, ex);
>       }
>       finally
>       {
>               // Restore the original response object
>               requestCycle.setResponse(originalResponse);
>       }
> }
> {noformat}
> Because all transformers are executed in order at this stage, the FIRST 
> executed transformer works on the content of the request of the LAST one 
> which put requests into place. After applying its own transformation, it puts 
> its own original request in place and the next transformer works on that and 
> puts its own request into place etc.
> So the problem seems to be that AFTER the first transformer executed 
> "afterReder", all subsequent ones are rendering into temporary responses of 
> former transformers and those results are never written to the original 
> response. It can't be, because only the first transformer has access to that 
> response at all, but is unaware of the results of later transformers.
> So it needs to be decided if multiple transformers should be supported at all 
> and if so, how to do it best with proper chaining of results. In my opinion 
> it should be supported, as I have a valid use case and I couldn't find any 
> docs that multiple of those transformers don't work. It simply seems the 
> current implementation is too limited.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to