title: java.io.IOException: Broken pipe within an Apache Tomcat valve
body: <p>I am working on a SAML 2.0 based single-sign-on, Apache Tomcat valve. When testing my implementation I cam across the following set of errors which seem to occur intermittently to certain requests passed through the valve.</p>
  
  <pre><code>28-Apr-2016 23:29:50.798 SEVERE [http-nio-8080-exec-1] org.wso2.appserver.webapp.security.saml.SAMLSingleSignOn.invoke An error has occurred when processing the request
   org.wso2.appserver.webapp.security.utils.SSOException: Error occurred while writing to HttpServletResponse
      at org.wso2.appserver.webapp.security.saml.SAMLSSOManager.sendCharacterData(SAMLSSOManager.java:299)
      at org.wso2.appserver.webapp.security.saml.SAMLSingleSignOn.handleUnauthenticatedRequest(SAMLSingleSignOn.java:212)
      at org.wso2.appserver.webapp.security.saml.SAMLSingleSignOn.invoke(SAMLSingleSignOn.java:127)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
      at java.lang.Thread.run(Thread.java:745)
  Caused by: org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe
      at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:393)
      at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:426)
      at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:342)
      at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:317)
      at org.apache.catalina.connector.Response.flushBuffer(Response.java:510)
      at org.wso2.appserver.webapp.security.saml.SAMLSSOManager.sendCharacterData(SAMLSSOManager.java:296)
      ... 12 more
  Caused by: java.io.IOException: Broken pipe
      at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
      at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
      at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
      at sun.nio.ch.IOUtil.write(IOUtil.java:65)
      at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
      at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:124)
      at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101)
      at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:172)
      at org.apache.coyote.http11.InternalNioOutputBuffer.writeToSocket(InternalNioOutputBuffer.java:139)
      at org.apache.coyote.http11.InternalNioOutputBuffer.addToBB(InternalNioOutputBuffer.java:197)
      at org.apache.coyote.http11.InternalNioOutputBuffer.access$000(InternalNioOutputBuffer.java:41)
      at org.apache.coyote.http11.InternalNioOutputBuffer$SocketOutputBuffer.doWrite(InternalNioOutputBuffer.java:320)
      at org.apache.coyote.http11.filters.ChunkedOutputFilter.doWrite(ChunkedOutputFilter.java:116)
      at org.apache.coyote.http11.AbstractOutputBuffer.doWrite(AbstractOutputBuffer.java:256)
      at org.apache.coyote.Response.doWrite(Response.java:501)
      at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:388)
      ... 17 more 
  </code></pre>
  
  <p>This seems to occur when I write the HTML payload, which contains the SAML 2.0 request content to be sent. The code used for the above case is as follows:</p>
  
  <pre><code>private void handleUnauthenticatedRequest(Request request, Response response,
              SSOAgentRequestResolver requestResolver) throws SSOException {
          SAMLSSOManager manager = new SAMLSSOManager(agentConfiguration);
  
          //  handle the generation of the SAML 2.0 RelayState
          String relayStateId = SSOUtils.createID();
          RelayState relayState = SSOUtils.generateRelayState(request);
          if (agentConfiguration != null) {
              agentConfiguration.getSAML2().setRelayState(relayStateId);
          }
          Optional.ofNullable(request.getSession(false))
                  .ifPresent(httpSession -&gt; httpSession.setAttribute(relayStateId, relayState));
  
          //  TODO: check if the isPassive option of wso2as-web.xml can be removed since this is overridden here + usage
          Optional.ofNullable(agentConfiguration)
                  .ifPresent(agent -&gt; agent.getSAML2().enablePassiveAuthenticationEnabled(false));
          if (requestResolver.isHttpPOSTBinding()) {
              containerLog.info("Handling the SAML 2.0 Authentication Request for HTTP-POST binding...");
              String htmlPayload = manager.handleAuthnRequestForPOSTBinding(request);
              manager.sendCharacterData(response, htmlPayload);
          } else {
              containerLog.info("Handling the SAML 2.0 Authentication Request for " +
                      agentConfiguration.getSAML2().getHttpBinding() + "...");
              try {
                  response.sendRedirect(manager.handleAuthnRequestForRedirectBinding(request));
              } catch (IOException e) {
                  throw new SSOException("Error when handling SAML 2.0 HTTP-Redirect binding", e);
              }
          }
      }
  </code></pre>
  
  <p>The method sendCharacterData writes the payload to the response body.</p>
  
  <pre><code>protected void sendCharacterData(HttpServletResponse response, String htmlPayload) throws SSOException {
      try {
          Writer writer = response.getWriter();
          writer.write(htmlPayload);
          response.flushBuffer();
          //  not closing the Writer instance, as its creator is the HttpServletResponse
      } catch (IOException e) {
          throw new SSOException("Error occurred while writing to HttpServletResponse", e);
      }
  }
  </code></pre>
  
  <p>The solutions provided in most resources do not seem to provide any help. Any help with this scenario will be highly appreciated.</p>