Hi guys, I'm trying to write a very simple servlet container which uses NIO. I've got a Response class which receives in its constructor a SocketChannel is non blocking mode. This class implements javax.servlet.ServletResponse and I implemented the getWriter() method as follows (writer is of type PrintWriter, client is of type SocketChannel):
In my servlet I've got the following:
I got the following exception:
Before returning the PrintWriter from getWriter I checked the channel which is is non-blocking state and open. In the servlet, after getWriter the 'out' object is actually of type PrintWriter (not null) but when I first write something, I get this exception.
I found the solution. The problem was indeed the blocking state of the SocketChannel. Even if I tried to set the blocking mode to true, the AbstractSelectableChannel was throwing the IllegalBlockingException. I had a look at the source, and this happened because the SocketChannel had a valid key associated with it. This is true, because I registered each SocketChannel client with a Selector, in order to be notified of bytes available on the client's input stream. I had code like the following:
Then I had a closer look at my Nio book and actually to remove a key from service we need to invoke key.cancel() method.
So I replaced the above with the following:
If you use key.cancel(), this removes the relationship between a selector and a channel, and therefore you can change the blocking mode as many times as you like. For instance, you may decide for non-blocking mode if you have to serve static content (because a FileChannel can transfer directly to a SocketChannel), or for blocking mode if you need to operate with Streams (like in the case where you are implementing the javax.servlet.ServletResponse interface and the getWriter() method needs to return a PrintWriter.
The rule is: blocking with blocking, non-blocking with non-blocking. [ November 14, 2004: Message edited by: Marco Tedone ]