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.addH开发者_开发知识库eader("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
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()
:
- Put them in a
try-catch
wherein you ignore the exception. - 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:
- Should I close the servlet outputstream?
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?
精彩评论