[
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.