Rajiv,
here is my first impression feedback.
+ Good call to hide the NIO APIs. The functionality you are targeting
looks pretty good. However I guess some might still want the
ability to do IO with Buffers and Channels?
+ NIO is a really silly name. Can we try to avoid calling things
NIOXxx and instead use AsyncIOXxx. Specially as we are not actually
exposing any NIO classes and implementations might use NIO2 etc.
+ Why create new methods ServletRequest.getNIOInputStream and
ServletResponse.getNIOOutputStream? The current getInputStream and
getOutputStream already return ServletInputStream and
ServletOutputStream abstract classes, so we could just add the methods
from the OutputSink and InputSource interfaces to those classes.
This would avoid adding methods to interfaces and breaking wrappers
and other extensions.
+ The addReadListener and addWriteListener methods should just be
called addListener and the type of the listener passed used to
determine if IAE should be thrown or not. This would be more in line
with other addListeners in the API.
+ Can you explain more about the life cycle of the listeners? Are
these intended to work only with Async requests, or will they work for
any request? eg if I call response.addListener(myWriteListener),
could it be called back immediately while I'm still dispatched in the
servlet? or will any call back only occur if I call startAsync and
return from the dispatch?
cheers
On 13 September 2011 02:52, Rajiv Mordani <rajiv.mordani_at_oracle.com> wrote:
> Hi All,
> Please review and provide input on the initial draft proposal - It is
> similar to what is there in Grizzly and also Tomcat AIO. It does not expose
> any of the NIO constructs per say but I think that we don't necessarily need
> to expose them. Please let me know what you'll think.
>
> - Rajiv
>
> We will introduce new classes for readers, writers, input and out streams
> for NIO. These would be exposed from ServletRequest and ServletResponse.
>
> ReadListener: The listeners will be called back asynchronously.
>
> - Rajiv
>
> package javax.servlet;
>
> import java.util.EventListener;
>
> /**
> * @since Servlet 3.1
> */
>
> /**
> * <p>
> * This class represents a call-back mechanism that will notify
> implementations
> * as HTTP request data becomes available to read without blocking.
> * </p>
> *
>
> */
> public interface ReadListener extends EventListener {
>
> /**
> * <p>
> * Invoked when data is available to be read without blocking.
> *
> */
> public void onDataAvailable(ServletRequest request);
>
> /**
> * <p>
> * Invoked when all data for the current request has been read.
> * </p>
> *
> */
>
> public void onAllDataRead(ServletRequest request);
>
> /**
> * <p>
> * Invoked when an error occurs processing the request.
> * </p>
> */
> public void onError(Throwable t);
>
>
> }
>
> NIOInputSource
>
> package javax.servlet;
>
> /**
> * <p>
> * This interface defines methods to allow an {_at_link NIOInputStream} or
> * {_at_link NIOReader} to notify the developer <em>when</em> and <em>how
> much</em>
> * data is ready to be read without blocking.
> * </p>
> *
> * @since Servlet 3.1
> */
>
> public interface NIOInputSource {
>
> /**
> * @return the number of bytes (or characters) that may be obtained
> * without blocking.
> */
> public int dataAvailable();
>
> /**
> * @return <code>true</code> when all data for this particular request
> * has been read, otherwise returns <code>false</code>.
> */
> public boolean isFinished();
>
> /**
> * @return <code>true</code> if data can be obtained without blocking,
> * otherwise returns <code>false</code>.
> */
> public boolean isReady();
> }
>
> NIOInputStream
>
> package javax.servlet;
>
> import java.io.InputStream;
>
> /**
> * @since Servlet 3.1
> */
>
> public abstract class NIOInputStream extends InputStream implements
> NIOInputSource {
> }
>
> NIOReader
>
> package javax.servlet;
>
> import java.io.Reader;
>
> /**
> * @since Servlet 3.1
> */
>
> public abstract class NIOReader extends Reader implements NIOInputSource {
> }
>
> WriteListener
>
> package javax.servlet;
>
> import java.util.EventListener;
>
> /**
> *
> * Callback notification mechanism that signals to the developer it's
> possible
> * to write content.
> *
> * @since Servlet 3.1
> */
> public interface WriteListener extends EventListener {
>
> /**
> * This callback will be invoked when data can be written.
> *
> *
> * @throws Exception, {_at_link Exception} might be thrown by the custom
> * handler code. This exception will be delegated for processing to
> * {_at_link #onError(java.lang.Throwable)}.
> */
> public void onWritePossible(ServletResponse response);
>
> /**
> * <p>
> * Invoked when an error occurs processing the request asynchronously.
> * </p>
> */
> public void onError(final Throwable t);
>
> /**
> * Get the ServletResponse associated
> * @return
> */
> }
>
> NIOOutputSink
>
> package javax.servlet;
>
> /**
> * <p>
> * This interface defines methods to allow an {_at_link
> javax.servlet.NIOOutputStream} or
> * {_at_link javax.servlet.NIOWriter} to allow the developer to check with the
> runtime
> * whether or not it's possible to write data, or if it's not possible, to
> * be notified when it is.
> * </p>
> *
> * @since Servlet 3.1
> */
>
> public interface NIOOutputSink {
>
>
> /**
> *
> * @return <code>true</code> if a write to this
> <code>NIOOutputSink</code>
> * will succeed, otherwise returns <code>false</code>.
> */
> public boolean canWrite(int size);
>
> public void complete();
>
> }
>
> NIOOutputStream
>
> package javax.servlet;
>
> import java.io.OutputStream;
>
> /**
> * @since Servlet 3.1
> */
>
> public abstract class NIOOutputStream extends OutputStream implements
> NIOOutputSink {
> }
>
> NIOWriter
>
> package javax.servlet;
>
> import java.io.Writer;
>
> /**
> * @since Servlet 3.1
> */
>
> public abstract class NIOWriter extends Writer implements NIOOutputSink {
> }
>
> ServletRequest
>
> /**
> * Retrieves the body of the request as character data using
> * a <code>BufferedReader</code>. The reader translates the character
> * data according to the character encoding used on the body.
> * Either this method or {_at_link #getNIOInputStream} may be called to
> read the
> * body, not both.
> *
> * @return a <code>NIOReader</code> containing the body of the request
> *
> *
> * @exception IllegalStateException if {_at_link #getNIOInputStream} method
> * has been called on this request
> *
> *
> * @see #getNIOInputStream
> *
> * @since Servlet 3.1
> *
> */
>
> public NIOReader getNIOReader();
>
> /**
> * Retrieves the body of the request as binary data using
> * a {_at_link NIOInputStream}. Either this method or
> * {_at_link #getNIOReader} may be called to read the body in
> * a non-blocking way but, not both.
> *
> * @return a {_at_link javax.servlet.NIOInputStream} object containing
> * the body of the request
> *
> * @exception IllegalStateException if the {_at_link #getNIOReader} method
> * has already been called for this request
> *
> * @since Servlet 3.1
> */
>
> public NIOInputStream getNIOInputStream();
>
> /**
> * Instructs the <code>ServletRequest</code> to invoke the provided
> * {_at_link ReadListener} when it is possible to write
> *
> * @param listener the {_at_link ReadListener} that should be notified
> * when it's possible to read.
> *
> */
>
> public void addReadListener(ReadListener listener);
>
> ServletResponse
>
> /**
> * Returns a {_at_link NIOOutputStream} suitable for writing binary
> * data in the response.
> *
> * @return a {_at_link NIOOutputStream} for writing binary data
> *
> * @exception IllegalStateException if the <code>getNIOWriter</code>
> method
> * has been called on this response
> *
> * @see #getNIOWriter
> *
> */
> public NIOOutputStream getNIOOutputStream();
>
> /**
> * Returns a <code>NIOWriter</code> object that
> * can send character text to the client.
> *
> *
> * @return a <code>NIOWriter</code> object that
> * can return character data to the client
> *
> *
> * @see #getNIOOutputStream
> *
> */
> public NIOWriter getNIOWriter();
>
> /**
> * Instructs the <code>ServletResponse</code> to invoke the provided
> * {_at_link WriteListener} when it is possible to write
> *
> *
> * @param listener the {_at_link WriteListener} that should be notified
> * when it's possible to write.
> *
> */
>
> public void addWriteListener(WriteListener listener);
>
> Sample utilizing the API
>
> package servlet.samples.nio;
>
>
> import javax.servlet.*;
> import javax.servlet.http.HttpServlet;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
> import java.io.IOException;
>
> public class NIOServletSample extends HttpServlet {
> private byte[] b = new byte[100];
> public void doGet(HttpServletRequest request, HttpServletResponse
> response) {
> request.addReadListener(new ReadListener() {
> public void onDataAvailable(ServletRequest request) {
> NIOInputStream nis = request.getNIOInputStream();
> try {
> nis.read(new byte[nis.dataAvailable()]);
> } catch (IOException e) {
> e.printStackTrace();
> }
> }
>
> public void onAllDataRead(ServletRequest request) {
> try {
> request.getNIOInputStream().close();
> } catch (IOException e) {
> e.printStackTrace();
> }
>
> }
>
> public void onError(Throwable t) {
>
> }
> });
> response.addWriteListener(new WriteListener() {
> public void onWritePossible(ServletResponse response) {
> NIOOutputStream nos = response.getNIOOutputStream();
> try {
> nos.write(b);
> nos.complete();
> } catch (IOException e) {
> e.printStackTrace();
> }
>
> }
>
> public void onError(Throwable t) {
>
> }
>
> });
>
> }
> }
>
>