jsr340-experts@servlet-spec.java.net

[jsr340-experts] Initial draft of NIO proposal

From: Rajiv Mordani <rajiv.mordani_at_oracle.com>
Date: Mon, 12 Sep 2011 09:52:11 -0700

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 ReadListenerextends EventListener {

     /**
      *<p>
      * Invoked when data is available to be read without blocking.
      *
      */
     public void onDataAvailable(ServletRequest request);

     /**
      *<p>
      * Invoked when all datafor 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>
  * Thisinterface 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 datafor 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 NIOInputStreamextends InputStreamimplements NIOInputSource {
}

NIOReader

package javax.servlet;

import java.io.Reader;

/**
  * @since Servlet 3.1
  */

public abstract class NIOReaderextends Readerimplements 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 WriteListenerextends 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 delegatedfor 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>
  * Thisinterface 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, orif 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 tothis <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 NIOOutputStreamextends OutputStreamimplements NIOOutputSink {
}

NIOWriter

package javax.servlet;

import java.io.Writer;

/**
  * @since Servlet 3.1
  */

public abstract class NIOWriterextends Writerimplements 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.
      * Eitherthis 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 IllegalStateExceptionif {_at_link #getNIOInputStream} method
      * has been called onthis request
      *
      *
      * @see #getNIOInputStream
      *
      * @since Servlet 3.1
      *
      */

     public NIOReader getNIOReader();

     /**
      * Retrieves the body of the request as binary data using
      * a {_at_link NIOInputStream}. Eitherthis 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 IllegalStateExceptionif the {_at_link #getNIOReader} method
      * has already been calledfor 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} suitablefor writing binary
        * data in the response.
        *
        * @return a {_at_link NIOOutputStream}for writing binary data
        *
        * @exception IllegalStateExceptionif the<code>getNIOWriter</code> method
        * has been called onthis 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
          * canreturn 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 NIOServletSampleextends 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) {

              }

          });

     }
}