You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@struts.apache.org by "Jasper Rosenberg (JIRA)" <ji...@apache.org> on 2009/07/17 21:03:00 UTC

[jira] Created: (WW-3195) When FreemarkerResult isn't writing directly to Response, s.action tag is broken

When FreemarkerResult isn't writing directly to Response, s.action tag is broken
--------------------------------------------------------------------------------

                 Key: WW-3195
                 URL: https://issues.apache.org/struts/browse/WW-3195
             Project: Struts 2
          Issue Type: Bug
    Affects Versions: 2.1.7
            Reporter: Jasper Rosenberg
             Fix For: 2.1.8


In https://issues.apache.org/struts/browse/WW-1808, the FreemarkerResult was improved to support not writing to the response until it had completed processing.

Unfortunately, if you are using an s.action tag, then that means the s.action output ends up before the main template output rather than inline.

One way to fix this (which I did locally) is to add a thread local that keeps track of the "parent" writer such that if there is one present the child writes to that at the end rather than the response's writer.

Something like:

    /** Thread local for the current writer. */
    private static final ThreadLocal<CharArrayWriter> WRITER_THREAD_LOCAL 
        = new ThreadLocal<CharArrayWriter>();

...
   // Inside the case where we are writing upon completion

            CharArrayWriter parentCharArrayWriter = WRITER_THREAD_LOCAL.get();
            try {
                // Process the template with the normal writer since it was available
                // But delay writing in case exception
                CharArrayWriter charArrayWriter = new CharArrayWriter(1024);
                
                if (parentCharArrayWriter == null) {
                    WRITER_THREAD_LOCAL.set(charArrayWriter);
                }
                
                template.process(model, charArrayWriter);

                charArrayWriter.flush();

                // Only the template that created the writer can actually write
                // to the response.  This is necessary to support the s.action tag.
                if (parentCharArrayWriter == null) {
                    charArrayWriter.writeTo(writer);  // Write to the response writer
                } else {
                    // Copying to parent enmass so don't get partially rendered s.actions
                    charArrayWriter.writeTo(parentCharArrayWriter);
                }
            } finally {
                if (parentCharArrayWriter == null) {
                    WRITER_THREAD_LOCAL.remove();
                }
            }




-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (WW-3195) When FreemarkerResult isn't writing directly to Response, s.action tag is broken

Posted by "Jasper Rosenberg (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/struts/browse/WW-3195?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=46671#action_46671 ] 

Jasper Rosenberg commented on WW-3195:
--------------------------------------

I think this change is less scary than you may have originally read it.

A. It only effects FreemarkerResult
B. Is only for the case: if (isWriteIfCompleted() || configuration.getTemplateExceptionHandler() == TemplateExceptionHandler.RETHROW_HANDLER) 
Which was only introduced at the begining of this year in the 2.1 tree.




> When FreemarkerResult isn't writing directly to Response, s.action tag is broken
> --------------------------------------------------------------------------------
>
>                 Key: WW-3195
>                 URL: https://issues.apache.org/struts/browse/WW-3195
>             Project: Struts 2
>          Issue Type: Bug
>    Affects Versions: 2.1.7
>            Reporter: Jasper Rosenberg
>             Fix For: 2.1.9
>
>
> In https://issues.apache.org/struts/browse/WW-1808, the FreemarkerResult was improved to support not writing to the response until it had completed processing.
> Unfortunately, if you are using an s.action tag, then that means the s.action output ends up before the main template output rather than inline.
> One way to fix this (which I did locally) is to add a thread local that keeps track of the "parent" writer such that if there is one present the child writes to that at the end rather than the response's writer.
> Something like:
>     /** Thread local for the current writer. */
>     private static final ThreadLocal<CharArrayWriter> WRITER_THREAD_LOCAL 
>         = new ThreadLocal<CharArrayWriter>();
> ...
>    // Inside the case where we are writing upon completion
>             CharArrayWriter parentCharArrayWriter = WRITER_THREAD_LOCAL.get();
>             try {
>                 // Process the template with the normal writer since it was available
>                 // But delay writing in case exception
>                 CharArrayWriter charArrayWriter = new CharArrayWriter(1024);
>                 
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.set(charArrayWriter);
>                 }
>                 
>                 template.process(model, charArrayWriter);
>                 charArrayWriter.flush();
>                 // Only the template that created the writer can actually write
>                 // to the response.  This is necessary to support the s.action tag.
>                 if (parentCharArrayWriter == null) {
>                     charArrayWriter.writeTo(writer);  // Write to the response writer
>                 } else {
>                     // Copying to parent enmass so don't get partially rendered s.actions
>                     charArrayWriter.writeTo(parentCharArrayWriter);
>                 }
>             } finally {
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.remove();
>                 }
>             }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (WW-3195) When FreemarkerResult isn't writing directly to Response, s.action tag is broken

Posted by "Musachy Barroso (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/struts/browse/WW-3195?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Musachy Barroso updated WW-3195:
--------------------------------

    Fix Version/s:     (was: 2.1.8)
                   2.1.9

> When FreemarkerResult isn't writing directly to Response, s.action tag is broken
> --------------------------------------------------------------------------------
>
>                 Key: WW-3195
>                 URL: https://issues.apache.org/struts/browse/WW-3195
>             Project: Struts 2
>          Issue Type: Bug
>    Affects Versions: 2.1.7
>            Reporter: Jasper Rosenberg
>             Fix For: 2.1.9
>
>
> In https://issues.apache.org/struts/browse/WW-1808, the FreemarkerResult was improved to support not writing to the response until it had completed processing.
> Unfortunately, if you are using an s.action tag, then that means the s.action output ends up before the main template output rather than inline.
> One way to fix this (which I did locally) is to add a thread local that keeps track of the "parent" writer such that if there is one present the child writes to that at the end rather than the response's writer.
> Something like:
>     /** Thread local for the current writer. */
>     private static final ThreadLocal<CharArrayWriter> WRITER_THREAD_LOCAL 
>         = new ThreadLocal<CharArrayWriter>();
> ...
>    // Inside the case where we are writing upon completion
>             CharArrayWriter parentCharArrayWriter = WRITER_THREAD_LOCAL.get();
>             try {
>                 // Process the template with the normal writer since it was available
>                 // But delay writing in case exception
>                 CharArrayWriter charArrayWriter = new CharArrayWriter(1024);
>                 
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.set(charArrayWriter);
>                 }
>                 
>                 template.process(model, charArrayWriter);
>                 charArrayWriter.flush();
>                 // Only the template that created the writer can actually write
>                 // to the response.  This is necessary to support the s.action tag.
>                 if (parentCharArrayWriter == null) {
>                     charArrayWriter.writeTo(writer);  // Write to the response writer
>                 } else {
>                     // Copying to parent enmass so don't get partially rendered s.actions
>                     charArrayWriter.writeTo(parentCharArrayWriter);
>                 }
>             } finally {
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.remove();
>                 }
>             }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (WW-3195) When FreemarkerResult isn't writing directly to Response, s.action tag is broken

Posted by "Jasper Rosenberg (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/struts/browse/WW-3195?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=46499#action_46499 ] 

Jasper Rosenberg commented on WW-3195:
--------------------------------------

Just discovered the code above doesn't work when s.actions are nested 2 deep.   Can't have the template.process write to a temporary buffer as it is the same problem then as the original :)  The code below will work better.

CharArrayWriter parentCharArrayWriter = WRITER_THREAD_LOCAL.get();
            try {
                // Process the template with the normal writer since it was available
                // But delay writing in case exception
                CharArrayWriter charArrayWriter;
                if (parentCharArrayWriter == null) {
                    charArrayWriter = new CharArrayWriter(1024);
                    WRITER_THREAD_LOCAL.set(charArrayWriter);
                } else {
                    charArrayWriter = parentCharArrayWriter;
                }
                
                template.process(model, charArrayWriter);

                // Only the template that created the writer can actually write
                // to the response.  This is necessary to support the s.action tag.
                if (parentCharArrayWriter == null) {
                    // Process the template
                    Writer writer = getWriter();
    
                    charArrayWriter.flush();
                    charArrayWriter.writeTo(writer);
                }
            } finally {
                if (parentCharArrayWriter == null) {
                    WRITER_THREAD_LOCAL.remove();
                }
            }

> When FreemarkerResult isn't writing directly to Response, s.action tag is broken
> --------------------------------------------------------------------------------
>
>                 Key: WW-3195
>                 URL: https://issues.apache.org/struts/browse/WW-3195
>             Project: Struts 2
>          Issue Type: Bug
>    Affects Versions: 2.1.7
>            Reporter: Jasper Rosenberg
>             Fix For: 2.1.8
>
>
> In https://issues.apache.org/struts/browse/WW-1808, the FreemarkerResult was improved to support not writing to the response until it had completed processing.
> Unfortunately, if you are using an s.action tag, then that means the s.action output ends up before the main template output rather than inline.
> One way to fix this (which I did locally) is to add a thread local that keeps track of the "parent" writer such that if there is one present the child writes to that at the end rather than the response's writer.
> Something like:
>     /** Thread local for the current writer. */
>     private static final ThreadLocal<CharArrayWriter> WRITER_THREAD_LOCAL 
>         = new ThreadLocal<CharArrayWriter>();
> ...
>    // Inside the case where we are writing upon completion
>             CharArrayWriter parentCharArrayWriter = WRITER_THREAD_LOCAL.get();
>             try {
>                 // Process the template with the normal writer since it was available
>                 // But delay writing in case exception
>                 CharArrayWriter charArrayWriter = new CharArrayWriter(1024);
>                 
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.set(charArrayWriter);
>                 }
>                 
>                 template.process(model, charArrayWriter);
>                 charArrayWriter.flush();
>                 // Only the template that created the writer can actually write
>                 // to the response.  This is necessary to support the s.action tag.
>                 if (parentCharArrayWriter == null) {
>                     charArrayWriter.writeTo(writer);  // Write to the response writer
>                 } else {
>                     // Copying to parent enmass so don't get partially rendered s.actions
>                     charArrayWriter.writeTo(parentCharArrayWriter);
>                 }
>             } finally {
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.remove();
>                 }
>             }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (WW-3195) When FreemarkerResult isn't writing directly to Response, s.action tag is broken

Posted by "Musachy Barroso (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/struts/browse/WW-3195?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=46618#action_46618 ] 

Musachy Barroso commented on WW-3195:
-------------------------------------

I am very uncomfortable making this change and risking breaking normal results just to fix the "action" tag when using freemarker, I will move this

> When FreemarkerResult isn't writing directly to Response, s.action tag is broken
> --------------------------------------------------------------------------------
>
>                 Key: WW-3195
>                 URL: https://issues.apache.org/struts/browse/WW-3195
>             Project: Struts 2
>          Issue Type: Bug
>    Affects Versions: 2.1.7
>            Reporter: Jasper Rosenberg
>             Fix For: 2.1.9
>
>
> In https://issues.apache.org/struts/browse/WW-1808, the FreemarkerResult was improved to support not writing to the response until it had completed processing.
> Unfortunately, if you are using an s.action tag, then that means the s.action output ends up before the main template output rather than inline.
> One way to fix this (which I did locally) is to add a thread local that keeps track of the "parent" writer such that if there is one present the child writes to that at the end rather than the response's writer.
> Something like:
>     /** Thread local for the current writer. */
>     private static final ThreadLocal<CharArrayWriter> WRITER_THREAD_LOCAL 
>         = new ThreadLocal<CharArrayWriter>();
> ...
>    // Inside the case where we are writing upon completion
>             CharArrayWriter parentCharArrayWriter = WRITER_THREAD_LOCAL.get();
>             try {
>                 // Process the template with the normal writer since it was available
>                 // But delay writing in case exception
>                 CharArrayWriter charArrayWriter = new CharArrayWriter(1024);
>                 
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.set(charArrayWriter);
>                 }
>                 
>                 template.process(model, charArrayWriter);
>                 charArrayWriter.flush();
>                 // Only the template that created the writer can actually write
>                 // to the response.  This is necessary to support the s.action tag.
>                 if (parentCharArrayWriter == null) {
>                     charArrayWriter.writeTo(writer);  // Write to the response writer
>                 } else {
>                     // Copying to parent enmass so don't get partially rendered s.actions
>                     charArrayWriter.writeTo(parentCharArrayWriter);
>                 }
>             } finally {
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.remove();
>                 }
>             }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (WW-3195) When FreemarkerResult isn't writing directly to Response, s.action tag is broken

Posted by "Dushyant Pandya (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/struts/browse/WW-3195?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=46979#action_46979 ] 

Dushyant Pandya commented on WW-3195:
-------------------------------------

Is there any plan to fix this defect? 

> When FreemarkerResult isn't writing directly to Response, s.action tag is broken
> --------------------------------------------------------------------------------
>
>                 Key: WW-3195
>                 URL: https://issues.apache.org/struts/browse/WW-3195
>             Project: Struts 2
>          Issue Type: Bug
>    Affects Versions: 2.1.8
>            Reporter: Jasper Rosenberg
>             Fix For: 2.2.0
>
>
> In https://issues.apache.org/struts/browse/WW-1808, the FreemarkerResult was improved to support not writing to the response until it had completed processing.
> Unfortunately, if you are using an s.action tag, then that means the s.action output ends up before the main template output rather than inline.
> One way to fix this (which I did locally) is to add a thread local that keeps track of the "parent" writer such that if there is one present the child writes to that at the end rather than the response's writer.
> Something like:
>     /** Thread local for the current writer. */
>     private static final ThreadLocal<CharArrayWriter> WRITER_THREAD_LOCAL 
>         = new ThreadLocal<CharArrayWriter>();
> ...
>    // Inside the case where we are writing upon completion
>             CharArrayWriter parentCharArrayWriter = WRITER_THREAD_LOCAL.get();
>             try {
>                 // Process the template with the normal writer since it was available
>                 // But delay writing in case exception
>                 CharArrayWriter charArrayWriter = new CharArrayWriter(1024);
>                 
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.set(charArrayWriter);
>                 }
>                 
>                 template.process(model, charArrayWriter);
>                 charArrayWriter.flush();
>                 // Only the template that created the writer can actually write
>                 // to the response.  This is necessary to support the s.action tag.
>                 if (parentCharArrayWriter == null) {
>                     charArrayWriter.writeTo(writer);  // Write to the response writer
>                 } else {
>                     // Copying to parent enmass so don't get partially rendered s.actions
>                     charArrayWriter.writeTo(parentCharArrayWriter);
>                 }
>             } finally {
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.remove();
>                 }
>             }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (WW-3195) When FreemarkerResult isn't writing directly to Response, s.action tag is broken

Posted by "Musachy Barroso (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/struts/browse/WW-3195?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Musachy Barroso updated WW-3195:
--------------------------------

    Fix Version/s:     (was: 2.1.9)
                   2.2.0

> When FreemarkerResult isn't writing directly to Response, s.action tag is broken
> --------------------------------------------------------------------------------
>
>                 Key: WW-3195
>                 URL: https://issues.apache.org/struts/browse/WW-3195
>             Project: Struts 2
>          Issue Type: Bug
>    Affects Versions: 2.1.8
>            Reporter: Jasper Rosenberg
>             Fix For: 2.2.0
>
>
> In https://issues.apache.org/struts/browse/WW-1808, the FreemarkerResult was improved to support not writing to the response until it had completed processing.
> Unfortunately, if you are using an s.action tag, then that means the s.action output ends up before the main template output rather than inline.
> One way to fix this (which I did locally) is to add a thread local that keeps track of the "parent" writer such that if there is one present the child writes to that at the end rather than the response's writer.
> Something like:
>     /** Thread local for the current writer. */
>     private static final ThreadLocal<CharArrayWriter> WRITER_THREAD_LOCAL 
>         = new ThreadLocal<CharArrayWriter>();
> ...
>    // Inside the case where we are writing upon completion
>             CharArrayWriter parentCharArrayWriter = WRITER_THREAD_LOCAL.get();
>             try {
>                 // Process the template with the normal writer since it was available
>                 // But delay writing in case exception
>                 CharArrayWriter charArrayWriter = new CharArrayWriter(1024);
>                 
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.set(charArrayWriter);
>                 }
>                 
>                 template.process(model, charArrayWriter);
>                 charArrayWriter.flush();
>                 // Only the template that created the writer can actually write
>                 // to the response.  This is necessary to support the s.action tag.
>                 if (parentCharArrayWriter == null) {
>                     charArrayWriter.writeTo(writer);  // Write to the response writer
>                 } else {
>                     // Copying to parent enmass so don't get partially rendered s.actions
>                     charArrayWriter.writeTo(parentCharArrayWriter);
>                 }
>             } finally {
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.remove();
>                 }
>             }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


Re: WW-3291. What should I do to help move this issue forward.

Posted by Lukasz Lenart <lu...@googlemail.com>.
2009/10/27 Musachy Barroso <mu...@gmail.com>:
> usually just wait until one of those lazy struts committers merge the
> patch :). I can take a look at it and merge it into trunk on the
> weekend.

Lazy? I'm still a bit afraid to make a change into Struts2 code base ;-)


Regards
-- 
Lukasz
http://www.lenart.org.pl/
http://dailylog.lenart.org.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


Re: WW-3291. What should I do to help move this issue forward.

Posted by Musachy Barroso <mu...@gmail.com>.
usually just wait until one of those lazy struts committers merge the
patch :). I can take a look at it and merge it into trunk on the
weekend.

On a separate note, now that Sitemesh is more modular and reusable, is
it possible to write some tests for it?

musachy

On Tue, Oct 27, 2009 at 10:13 AM, Christian Stone <xt...@stonescape.net> wrote:
> I am asking simply because I have other bug fixes in the same codebase, and
> I want to resolve one before I complete and build a patch for the other.
>  However, I do not have a possibility of marking the bug resolved or to
> actually apply the patch to the codebase (I have not checked but I doubt I
> have write access to the struts source base).  So what should I do now?
>  What is the process?  I reread the docs and there is nothing discussing on
> what to do after submitting a patch for an issue.
>
> Thanks much!
>
> -- Christian
>
> P.S.  The new freemarker/velocity code is working great.  I moved it to a
> production server to test and it has no problem mixing freemarker decorators
> on velocity/jsp results, vice versa... and handles both freemarker and
> velocity decorators just like SiteMesh intended.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
> For additional commands, e-mail: dev-help@struts.apache.org
>
>



-- 
Screw John Galt, who is Martin Gainty?

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


Re: WW-3291. What should I do to help move this issue forward.

Posted by Christian Stone <xt...@stonescape.net>.
I am asking simply because I have other bug fixes in the same  
codebase, and I want to resolve one before I complete and build a  
patch for the other.  However, I do not have a possibility of marking  
the bug resolved or to actually apply the patch to the codebase (I  
have not checked but I doubt I have write access to the struts source  
base).  So what should I do now?  What is the process?  I reread the  
docs and there is nothing discussing on what to do after submitting a  
patch for an issue.

Thanks much!

-- Christian

P.S.  The new freemarker/velocity code is working great.  I moved it  
to a production server to test and it has no problem mixing freemarker  
decorators on velocity/jsp results, vice versa... and handles both  
freemarker and velocity decorators just like SiteMesh intended.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


[jira] Resolved: (WW-3195) When FreemarkerResult isn't writing directly to Response, s.action tag is broken

Posted by "Musachy Barroso (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/struts/browse/WW-3195?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Musachy Barroso resolved WW-3195.
---------------------------------

    Resolution: Fixed

Fixed in trunk. Tests added as well. Please give it a try and let me know

> When FreemarkerResult isn't writing directly to Response, s.action tag is broken
> --------------------------------------------------------------------------------
>
>                 Key: WW-3195
>                 URL: https://issues.apache.org/struts/browse/WW-3195
>             Project: Struts 2
>          Issue Type: Bug
>    Affects Versions: 2.1.8
>            Reporter: Jasper Rosenberg
>             Fix For: 2.2.0
>
>
> In https://issues.apache.org/struts/browse/WW-1808, the FreemarkerResult was improved to support not writing to the response until it had completed processing.
> Unfortunately, if you are using an s.action tag, then that means the s.action output ends up before the main template output rather than inline.
> One way to fix this (which I did locally) is to add a thread local that keeps track of the "parent" writer such that if there is one present the child writes to that at the end rather than the response's writer.
> Something like:
>     /** Thread local for the current writer. */
>     private static final ThreadLocal<CharArrayWriter> WRITER_THREAD_LOCAL 
>         = new ThreadLocal<CharArrayWriter>();
> ...
>    // Inside the case where we are writing upon completion
>             CharArrayWriter parentCharArrayWriter = WRITER_THREAD_LOCAL.get();
>             try {
>                 // Process the template with the normal writer since it was available
>                 // But delay writing in case exception
>                 CharArrayWriter charArrayWriter = new CharArrayWriter(1024);
>                 
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.set(charArrayWriter);
>                 }
>                 
>                 template.process(model, charArrayWriter);
>                 charArrayWriter.flush();
>                 // Only the template that created the writer can actually write
>                 // to the response.  This is necessary to support the s.action tag.
>                 if (parentCharArrayWriter == null) {
>                     charArrayWriter.writeTo(writer);  // Write to the response writer
>                 } else {
>                     // Copying to parent enmass so don't get partially rendered s.actions
>                     charArrayWriter.writeTo(parentCharArrayWriter);
>                 }
>             } finally {
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.remove();
>                 }
>             }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (WW-3195) When FreemarkerResult isn't writing directly to Response, s.action tag is broken

Posted by "Musachy Barroso (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/struts/browse/WW-3195?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=46980#action_46980 ] 

Musachy Barroso commented on WW-3195:
-------------------------------------

I am looking at it, I got a junit test case to reproduce it.

> When FreemarkerResult isn't writing directly to Response, s.action tag is broken
> --------------------------------------------------------------------------------
>
>                 Key: WW-3195
>                 URL: https://issues.apache.org/struts/browse/WW-3195
>             Project: Struts 2
>          Issue Type: Bug
>    Affects Versions: 2.1.8
>            Reporter: Jasper Rosenberg
>             Fix For: 2.2.0
>
>
> In https://issues.apache.org/struts/browse/WW-1808, the FreemarkerResult was improved to support not writing to the response until it had completed processing.
> Unfortunately, if you are using an s.action tag, then that means the s.action output ends up before the main template output rather than inline.
> One way to fix this (which I did locally) is to add a thread local that keeps track of the "parent" writer such that if there is one present the child writes to that at the end rather than the response's writer.
> Something like:
>     /** Thread local for the current writer. */
>     private static final ThreadLocal<CharArrayWriter> WRITER_THREAD_LOCAL 
>         = new ThreadLocal<CharArrayWriter>();
> ...
>    // Inside the case where we are writing upon completion
>             CharArrayWriter parentCharArrayWriter = WRITER_THREAD_LOCAL.get();
>             try {
>                 // Process the template with the normal writer since it was available
>                 // But delay writing in case exception
>                 CharArrayWriter charArrayWriter = new CharArrayWriter(1024);
>                 
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.set(charArrayWriter);
>                 }
>                 
>                 template.process(model, charArrayWriter);
>                 charArrayWriter.flush();
>                 // Only the template that created the writer can actually write
>                 // to the response.  This is necessary to support the s.action tag.
>                 if (parentCharArrayWriter == null) {
>                     charArrayWriter.writeTo(writer);  // Write to the response writer
>                 } else {
>                     // Copying to parent enmass so don't get partially rendered s.actions
>                     charArrayWriter.writeTo(parentCharArrayWriter);
>                 }
>             } finally {
>                 if (parentCharArrayWriter == null) {
>                     WRITER_THREAD_LOCAL.remove();
>                 }
>             }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.