0

I have simple jsf app with servlet for dynamic images and filter setting utf8 encoding. From time to time (1/10 requests) I get very strange error:

WARNING: StandardWrapperValve[com.webapp.servlet.ImageServlet]: PWC1406: Servlet.service() for servlet com.webapp.servlet.ImageServlet threw exception
java.lang.NullPointerException
    at com.sun.enterprise.v3.services.impl.monitor.MonitorableSelectionKeyHandler$CloseHandler.notifyClosed(MonitorableSelectionKeyHandler.java:94)
    at com.sun.enterprise.v3.services.impl.monitor.MonitorableSelectionKeyHandler$CloseHandler.remotlyClosed(MonitorableSelectionKeyHandler.java:90)
    at com.sun.grizzly.BaseSelectionKeyHandler.notifyRemotlyClose(BaseSelectionKeyHandler.java:233)
    at com.sun.grizzly.util.OutputWriter.notifyRemotelyClosed(OutputWriter.java:353)
    at com.sun.grizzly.util.OutputWriter.flushChannel(OutputWriter.java:148)
    at com.sun.grizzly.util.OutputWriter.flushChannel(OutputWriter.java:76)
    at com.sun.grizzly.http.SocketChannelOutputBuffer.flushChannel(SocketChannelOutputBuffer.java:326)
    at com.sun.grizzly.http.SocketChannelOutputBuffer.flushBuffer(SocketChannelOutputBuffer.java:398)
    at com.sun.grizzly.http.SocketChannelOutputBuffer.flush(SocketChannelOutputBuffer.java:376)
    at com.sun.grizzly.http.ProcessorTask.action(ProcessorTask.java:1247)
    at com.sun.grizzly.tcp.Response.action(Response.java:268)
    at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:380)
    at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:353)
    at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:175)
*   at com.webapp.servlet.ImageServlet.doGet(ImageServlet.java:35)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
    at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:118)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
*   at com.webapp.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:32)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:174)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:722)

Here's my servlet and filter, I marked with asterisks lines referencing to stacktrace:

@WebServlet(urlPatterns = "/images/*")
public class ImageServlet extends HttpServlet {

  @Inject
  private FileService fileService;

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
      byte[] img = fileService.getImage(request.getPathInfo());
      if (img != null) {
        response.setContentType("image/png");
        response.addHeader("Content-Length", String.valueOf(img.length));
        ServletOutputStream os = response.getOutputStream();
          os.write(img);
*         os.flush();
          os.close();
      } else {
        response.sendRedirect(request.getContextPath() + "/error");
      }
  }
}


@WebFilter(urlPatterns = "/*")
public class CharacterEncodingFilter implements Filter {

  @Override
  public void init(FilterConfig filterConfig) {
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    request.setCharacterEncoding("UTF-8");
    response.setCharacterEncoding("UTF-8");
*   chain.doFilter(request, response);
  }

  @Override
  public void destroy() {
  }
}

I have completely no idea what's going on... I'm using Glassfish 3.1.1 web profile with jdk7

karolkpl
  • 2,189
  • 10
  • 39
  • 60

2 Answers2

2

Flushing is already implicitly done when you close the stream. Closing is already implicitly done by the container itself. You actually do not need to do it yourself. However, most servlet developers do it to have early feedback for the case they overlooked that something else further in the request-response chain is writing to the output stream, e.g. a buggy filter or response wrapper or something. This would then result in an IOException on every call because the stream is closed.

In any case, you have 2 options to treat the flush() and close():

  1. Put them in a try-catch wherein you ignore the exception.
  2. Remove those 2 lines. The container does that for you anyway. It will also just ignore the exception.

This exception is just a sign that the client aborted the connection. E.g. pressed [Esc] or closed the window/tab or navigated away to a different page while the image is still streaming.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks, I'll see next week if it's working. "Remove those 2 lines." you mean `os.flush();os.close();`? – karolkpl Sep 30 '11 at 17:59
  • Yes, just remove them. It's not really interesting to know whenever a client aborted the connection. You can't do anything against it from the server side on anyway. – BalusC Sep 30 '11 at 18:02
0
at com.sun.grizzly.util.OutputWriter.notifyRemotelyClosed()

Somehow this looks to me as if the connection you are flushing the stream of has intermediately been closed by the remote peer (a web browser?).

Can you try response.flushBuffer() instead. Does this also throw the exception?

Gandalf
  • 2,350
  • 20
  • 28