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

Nick Veenhof commented on SOLR-2878:
------------------------------------

After loads of research and figuring out why it happened I found a 
CharResponseWrapper that worked for getOutputStream also.
For archiving purposes I'd like to put the full class here :

With this class it all seems to work as it did before. Thanks for the pointer 
on the CharResponseWrapper, I was not deep enough in the java servlets world to 
understand that this CharResponseWrapper could have such an impact on the 
response.

{code}
/**
 * 
 */
package clime.messadmin.filter;

import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

/**
 * @author Cédrik LIME
 */
class CharResponseWrapper extends HttpServletResponseWrapper {
        protected CharArrayWriter output;
        protected ServletOutputStream stream = null;
        protected PrintWriter writer = null;

        static class CharOutputStream extends ServletOutputStream {
                CharArrayWriter outstream;

                public CharOutputStream(CharArrayWriter out) {
                        outstream = out;
                }

                /** {@inheritDoc} */
//        @Override
                public void write(int b) {
                        outstream.write(b);
                }
                public void write(String str) throws IOException {
                        outstream.write(str);
                }
        }

        /** {@inheritDoc} */
//  @Override
        public String toString() {
                return output.toString();
        }

        public char[] toCharArray() {
                return (output.toCharArray());
        }

        public CharResponseWrapper(HttpServletResponse response) {
                super(response);
                output = new CharArrayWriter();
        }

        /** {@inheritDoc} */
//  @Override
        public synchronized PrintWriter getWriter() {
                if (stream != null) {
                        throw new IllegalStateException("getOutputStream() has 
already been called for this response");
                }
                if (writer == null) {
                        writer = new PrintWriter(output);
                }
                return writer;
        }

        /** {@inheritDoc} */
//  @Override
        public synchronized ServletOutputStream getOutputStream() {
                if (writer != null) {
                        throw new IllegalStateException("getWriter() has 
already been called for this response");
                }
                if (stream == null) {
                        stream = new CharOutputStream(output);
                }
                return stream;
        }

}
{code}
                
> Regression in SolrDispatchFilter.java concerning the getOutputStream vs 
> getWriter
> ---------------------------------------------------------------------------------
>
>                 Key: SOLR-2878
>                 URL: https://issues.apache.org/jira/browse/SOLR-2878
>             Project: Solr
>          Issue Type: Bug
>          Components: Build, Response Writers
>    Affects Versions: 3.4
>         Environment: Any unix system, it's a  global problem
>            Reporter: Nick Veenhof
>              Labels: filter, getOutputStream, getWriter, regression
>             Fix For: 3.5, 4.0
>
>
> In solr 1.4 we used getWriter in the writeResponse for 
> solrDispatchFilter::doFilter which invoked writeResponse.
> This code looked in summary like this :
> {code:title=solrDispatchFilter.java|borderStyle=solid}
> private void writeResponse(SolrQueryResponse solrRsp, ServletResponse 
> response, 
>    QueryResponseWriter responseWriter, SolrQueryRequest solrReq, Method 
> reqMethod) 
>    throws IOException {
> ...
>  PrintWriter out = response.getWriter();
>  responseWriter.write(out, solrReq, solrRsp);
> ...
> {code}
> In solr 3.x this has changed to something like this 
> {code:title=solrDispatchFilter.java|borderStyle=solid}
> private void writeResponse(SolrQueryResponse solrRsp, ServletResponse 
> response,
>   QueryResponseWriter responseWriter, SolrQueryRequest solrReq, Method 
> reqMethod) 
>   throws IOException {
> ...
> String charset = ContentStreamBase.getCharsetFromContentType(ct);
> Writer out = (charset == null || charset.equalsIgnoreCase("UTF-8"))
>   ? new OutputStreamWriter(response.getOutputStream(), UTF8)
>   : new OutputStreamWriter(response.getOutputStream(), charset);
> out = new FastWriter(out);
> responseWriter.write(out, solrReq, solrRsp);
> out.flush();
> ...
> {code}
> Now, when we add another filter that tries to modify the output it is being 
> blocked by the out.flush(). 
> flush() is telling our outputstream that it can write directly to the 
> destination (similar to the out.close()), since this normally happens 
> automatically there shouldn't be a need to execute this flush.
> In our case this secondary filter is trying to add headers to the response 
> object. When we were using getwriter() it was not closing the writer so we 
> could still modify this output. Since the flush happens now we are no longer 
> able to modify the headers accordingly. 
> It would be an easy fix if the flush could be commented out and everything 
> would work but that is not the case. The headers are working when this 
> happens but there is no more output.
> When I modify both classes to use getWriter() everything is working as 
> expected.
> This is a severe regression for our use of solr.
> Our code that is used in the filter
> {code:title=solrCustomFilter.java|borderStyle=solid}
> public void doFilter(ServletRequest req, ServletResponse res,FilterChain 
> chain) 
>   throws IOException, ServletException {
> ...
> Writer out = new OutputStreamWriter(response.getOutputStream(), "UTF8"); 
> //auto flush
> out = new FastWriter(out);
> // convert to a chartext
> CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse) 
> response);
> chain.doFilter(request, wrapper);
> String responseBody = wrapper.toString();
> //write the outgoing header. Only succeeds when flush of solrDispatchFilter 
> is commented out
> response.addHeader("pragma", "somevalue;");
> out.write(responseBody);
> ...
> {code}
> Sources :
> {quote}
> SRV.5.5 Closure of Response Object
> When a response is closed, the container must immediately flush all remaining 
> content in the response buffer to the client. The following events indicate 
> that the servlet has satisfied the request and that the response object is to 
> be closed:
> • The termination of the service method of the servlet. 
> • The amount of content specified in the setContentLength method of the 
> response has been written to the response. 
> • The sendError method is called. 
> • The sendRedirect method is called.
> {quote}
> Solr 1.4 
> https://svn.apache.org/repos/asf/lucene/solr/branches/branch-1.4/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java
> Solr 3.4 
> https://svn.apache.org/repos/asf/lucene/dev/branches/lucene_solr_3_4/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to