I'm trying to genericize my error handling for HTTP requests, and always respond with an actual error HTTP code and relevant message.
Here is my issue: in my Handler which extends SimpleChannelUpstreamHandler, exceptionCaught is fired when an exception is thrown anywhere in the stack. That's good. The bad part is that when I try to write out a response to the client with an appropriate HTTP code and response, the write causes an exception, and then the program goes into an infinite loop with calling exceptionCaught over and over again.
This has to be a commonly done task. How can I do it correctly?
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent event)
throws Exception {
try{
logger.error("Error in handling call: ", event.getCause());
HttpResponse httpResponse = buildHttpResponseObject(UNAUTHORIZED, new StringBuilder("Test"), false, null);
// Write the response.
// for some reason calling this next line causes an infinite loop of exceptionCaught, even with the
// catch below. No idea why. Still investigating. In the meantime, we don't have custom error code responses.
ChannelFuture future = event.getChannel().write(httpResponse);
// Close the connection after the write operation is done, even if it's a keep-alive.
future.addListener(ChannelFutureListener.CLOSE);
}
catch(Exception t){
logger.error("Unable to customize error response. ", t);
event.getChannel().close();
}
}
Here are the exceptions:
38161 [New I/O server worker #1-1] ERROR nettytests.http.snoop.HttpSnoopServerHandler - Error in handling call:
javax.net.ssl.SSLHandshakeException: null cert chain
at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1364)
at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:513)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:790)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:758)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:931)
at org.jboss.netty.handler.ssl.SslHandler.decode(SslHandler.java:649)
at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:288)
at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:207)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:343)
at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:274)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:194)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.net.ssl.SSLHandshakeException: null cert chain
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1639)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:278)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:266)
at sun.security.ssl.ServerHandshaker.clientCertificate(ServerHandshaker.java:1627)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:176)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
at sun.security.ssl.Handshaker$1.run(Handshaker.java:808)
at sun.security.ssl.Handshaker$1.run(Handshaker.java:806)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1301)
at org.jboss.netty.handler.ssl.SslHandler$3.run(SslHandler.java:1060)
at org.jboss.netty.handler.ssl.ImmediateExecutor.execute(ImmediateExecutor.java:31)
at org.jboss.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1057)
at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:947)
... 11 more
38177 [New I/O server worker #1-1] ERROR nettytests.http.snoop.HttpSnoopServerHandler - Error in handling call:
java.lang.IllegalStateException: cannot send more responses than requests
at org.jboss.netty.handler.codec.http.HttpContentEncoder.writeRequested(HttpContentEncoder.java:104)
at org.jboss.netty.channel.Channels.write(Channels.java:605)
at org.jboss.netty.channel.Channels.write(Channels.java:572)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:343)
at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:274)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:194)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
38177 [New I/O server worker #1-1] ERROR nettytests.http.snoop.HttpSnoopServerHandler - Error in handling call:
java.lang.IllegalStateException: cannot send more responses than requests
at org.jboss.netty.handler.codec.http.HttpContentEncoder.writeRequested(HttpContentEncoder.java:104)
at org.jboss.netty.channel.Channels.write(Channels.java:605)
at org.jboss.netty.channel.Channels.write(Channels.java:572)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
at org.jboss.netty.channel.Channels.write(Channels.java:605)
at org.jboss.netty.channel.Channels.write(Channels.java:572)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:343)
at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:274)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:194)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
38224 [New I/O server worker #1-1] ERROR nettytests.http.snoop.HttpSnoopServerHandler - Error in handling call:
java.lang.IllegalStateException: cannot send more responses than requests
at org.jboss.netty.handler.codec.http.HttpContentEncoder.writeRequested(HttpContentEncoder.java:104)
at org.jboss.netty.channel.Channels.write(Channels.java:605)
at org.jboss.netty.channel.Channels.write(Channels.java:572)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
at org.jboss.netty.channel.Channels.write(Channels.java:605)
at org.jboss.netty.channel.Channels.write(Channels.java:572)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
at org.jboss.netty.channel.Channels.write(Channels.java:605)
at org.jboss.netty.channel.Channels.write(Channels.java:572)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:343)
at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:274)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:194)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
38255 [New I/O server worker #1-1] ERROR nettytests.http.snoop.HttpSnoopServerHandler - Error in handling call:
java.lang.IllegalStateException: cannot send more responses than requests
at org.jboss.netty.handler.codec.http.HttpContentEncoder.writeRequested(HttpContentEncoder.java:104)
at org.jboss.netty.channel.Channels.write(Channels.java:605)
at org.jboss.netty.channel.Channels.write(Channels.java:572)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
at org.jboss.netty.channel.Channels.write(Channels.java:605)
at org.jboss.netty.channel.Channels.write(Channels.java:572)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
at org.jboss.netty.channel.Channels.write(Channels.java:605)
at org.jboss.netty.channel.Channels.write(Channels.java:572)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
at org.jboss.netty.channel.Channels.write(Channels.java:605)
at org.jboss.netty.channel.Channels.write(Channels.java:572)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:343)
at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:274)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:194)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
... repeat ad infinitum.