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

Nick Veenhof edited comment on SOLR-2878 at 11/5/11 11:24 AM:
--------------------------------------------------------------

Changed my wrapper to something like this to support the ByteArrayOutputStream. 
This looks more correct to you?
{code}
class CharResponseWrapper extends HttpServletResponseWrapper {
        protected ByteArrayOutputStream output;
        protected ServletOutputStream stream = null;
        protected PrintWriter writer = null;

  /** {@inheritDoc} */
  //  @Override
  public String toString() {
    return new String(getBytes());
  }

  public byte[] getBytes(){
    return output.toByteArray();
  }

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

  /** {@inheritDoc} */
  // @Override
  public 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 ServletOutputStream getOutputStream() {
    return new ServletOutputStream() {
        @Override
        public void write(int b) throws IOException {
           output.write(b);
        }
    };
  }
}
{code}

When used with :

{code}
      response.setCharacterEncoding("UTF-8");
      Writer out = new OutputStreamWriter(response.getOutputStream(), "UTF-8"); 
//auto flush
      CharResponseWrapper wrapper = new 
CharResponseWrapper((HttpServletResponse) response);
      // CharResponseWrapper is responsable for the getWriter and
      // getOutputStream support.
      chain.doFilter(request, wrapper);
      String responseBody = wrapper.toString();
      response.addHeader("pragma", "hash of responsebody");
      out.write(responseBody);
      out.flush();
{code}
                
      was (Author: nick.veenhof):
    Changed my wrapper to something like this :
{code}
class CharResponseWrapper extends HttpServletResponseWrapper {
        protected ByteArrayOutputStream output;
        protected ServletOutputStream stream = null;
        protected PrintWriter writer = null;

  /** {@inheritDoc} */
  //  @Override
  public String toString() {
    return new String(getBytes());
  }

  public byte[] getBytes(){
    return output.toByteArray();
  }

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

  /** {@inheritDoc} */
  // @Override
  public 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 ServletOutputStream getOutputStream() {
    return new ServletOutputStream() {
        @Override
        public void write(int b) throws IOException {
           output.write(b);
        }
    };
  }
}
{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
>
> 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