<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!DOCTYPE document [
  <!ENTITY project SYSTEM "project.xml">
]>
<document url="aio.html">

    &project;

  <properties>
    <title>Advanced IO and Tomcat</title>
    <author>Remy Maucherat</author>
  </properties>

<body>

<section name="Table of Contents">
<toc/>
</section>

  <section name="Introduction">

  <p>
    With usage of APR or NIO APIs as the basis of its connectors, Tomcat is
    able to provide a number of extensions over the regular blocking IO
    as provided with support for the Servlet API.
  </p>

  <p>
    <b>IMPORTANT NOTE: Usage of these features requires using the APR or NIO
    HTTP connectors. The classic java.io HTTP connector and the AJP connectors
    do not support them.</b>
  </p>

  </section>

  <section name="Comet support">

  <p>
    Comet support allows a servlet to process IO asynchronously, receiving
    events when data is available for reading on the connection (rather than
    always using a blocking read), and writing data back on connections
    asynchronously (most likely responding to some event raised from some
    other source).
  </p>

  <subsection name="CometEvent">

  <p>
    Servlets which implement the <code>org.apache.catalina.comet.CometProcessor</code>
    interface will have their event method invoked rather than the usual service
    method, according to the event which occurred. The event object gives
    access to the usual request and response objects, which may be used in the
    usual way. The main difference is that those objects remain valid and fully
    functional at any time between processing of the BEGIN event until processing
    an END or ERROR event.
    The following event types exist:
  </p>

  <ul>
  <li>EventType.BEGIN: will be called at the beginning
     of the processing of the connection. It can be used to initialize any relevant
     fields using the request and response objects. Between the end of the processing
     of this event, and the beginning of the processing of the end or error events,
     it is possible to use the response object to write data on the open connection.
     Note that the response object and dependent OutputStream and Writer are still
     not synchronized, so when they are accessed by multiple threads,
     synchronization is mandatory. After processing the initial event, the request
     is considered to be committed.</li>
  <li>EventType.READ: This indicates that input data is available, and that one read can be made
       without blocking. The available and ready methods of the InputStream or
       Reader may be used to determine if there is a risk of blocking: the servlet
       should read while data is reported available. When encountering a read error,
       the servlet should report it by propagating the exception properly. Throwing
       an exception will cause the error event to be invoked, and the connection
       will be closed.
       Alternately, it is also possible to catch any exception, perform clean up
       on any data structure the servlet may be using, and using the close method
       of the event. It is not allowed to attempt reading data from the request
       object outside of the execution of this method.<br/>
       On some platforms, like Windows, a client disconnect is indicated by a READ event.
       Reading from the stream may result in -1, an IOException or an EOFException.
       Make sure you properly handle all these three cases.
       If you don't catch the IOException, Tomcat will instantly invoke your event chain with an ERROR as
       it catches the error for you, and you will be notified of the error at that time.
  </li>
  <li>EventType.END: End may be called to end the processing of the request. Fields that have
     been initialized in the begin method should be reset. After this event has
     been processed, the request and response objects, as well as all their dependent
     objects will be recycled and used to process other requests. End will also be
     called when data is available and the end of file is reached on the request input
     (this usually indicates the client has pipelined a request).</li>
  <li>EventType.ERROR: Error will be called by the container in the case where an IO exception
     or a similar unrecoverable error occurs on the connection. Fields that have
     been initialized in the begin method should be reset. After this event has
     been processed, the request and response objects, as well as all their dependent
     objects will be recycled and used to process other requests.</li>
  </ul>

  <p>
    There are some event subtypes which allow finer processing of events (note: some of these
    events require usage of the org.apache.catalina.valves.CometConnectionManagerValve valve):
  </p>

  <ul>
  <li>EventSubType.TIMEOUT: The connection timed out (sub type of ERROR); note that this ERROR
    type is not fatal, and the connection will not be closed unless the servlet uses the close
    method of the event.
  </li>
  <li>EventSubType.CLIENT_DISCONNECT: The client connection was closed (sub type of ERROR).
  </li>
  <li>EventSubType.IOEXCEPTION: An IO exception occurred, such as invalid content, for example,
    an invalid chunk block (sub type of ERROR).
  </li>
  <li>EventSubType.WEBAPP_RELOAD: The web application is being reloaded (sub type of END).
  </li>
  <li>EventSubType.SESSION_END: The servlet ended the session (sub type of END).
  </li>
  </ul>

  <p>
    As described above, the typical lifecycle of a Comet request will consist in a series of
    events such as: BEGIN -> READ -> READ -> READ -> ERROR/TIMEOUT. At any time, the servlet
    may end processing of the request by using the close method of the event object.
  </p>

  </subsection>

  <subsection name="CometFilter">

  <p>
    Similar to regular filters, a filter chain is invoked when comet events are processed.
    These filters should implement the CometFilter interface (which works in the same way as
    the regular Filter interface), and should be declared and mapped in the deployment
    descriptor in the same way as a regular filter. The filter chain when processing an event
    will only include filters which match all the usual mapping rules, and also implement
    the CometFiler interface.
  </p>

  </subsection>

  <subsection name="Example code">

  <p>
    The following pseudo code servlet implements asynchronous chat functionality using the API
    described above:
  </p>

  <source><![CDATA[public class ChatServlet
    extends HttpServlet implements CometProcessor {

    protected ArrayList<HttpServletResponse> connections =
        new ArrayList<HttpServletResponse>();
    protected MessageSender messageSender = null;

    public void init() throws ServletException {
        messageSender = new MessageSender();
        Thread messageSenderThread =
            new Thread(messageSender, "MessageSender[" + getServletContext().getContextPath() + "]");
        messageSenderThread.setDaemon(true);
        messageSenderThread.start();
    }

    public void destroy() {
        connections.clear();
        messageSender.stop();
        messageSender = null;
    }

    /**
     * Process the given Comet event.
     *
     * @param event The Comet event that will be processed
     * @throws IOException
     * @throws ServletException
     */
    public void event(CometEvent event)
        throws IOException, ServletException {
        HttpServletRequest request = event.getHttpServletRequest();
        HttpServletResponse response = event.getHttpServletResponse();
        if (event.getEventType() == CometEvent.EventType.BEGIN) {
            log("Begin for session: " + request.getSession(true).getId());
            PrintWriter writer = response.getWriter();
            writer.println("<!DOCTYPE html>");
            writer.println("<head><title>JSP Chat</title></head><body>");
            writer.flush();
            synchronized(connections) {
                connections.add(response);
            }
        } else if (event.getEventType() == CometEvent.EventType.ERROR) {
            log("Error for session: " + request.getSession(true).getId());
            synchronized(connections) {
                connections.remove(response);
            }
            event.close();
        } else if (event.getEventType() == CometEvent.EventType.END) {
            log("End for session: " + request.getSession(true).getId());
            synchronized(connections) {
                connections.remove(response);
            }
            PrintWriter writer = response.getWriter();
            writer.println("</body></html>");
            event.close();
        } else if (event.getEventType() == CometEvent.EventType.READ) {
            InputStream is = request.getInputStream();
            byte[] buf = new byte[512];
            do {
                int n = is.read(buf); //can throw an IOException
                if (n > 0) {
                    log("Read " + n + " bytes: " + new String(buf, 0, n)
                            + " for session: " + request.getSession(true).getId());
                } else if (n < 0) {
                    error(event, request, response);
                    return;
                }
            } while (is.available() > 0);
        }
    }

    public class MessageSender implements Runnable {

        protected boolean running = true;
        protected ArrayList<String> messages = new ArrayList<String>();

        public MessageSender() {
        }

        public void stop() {
            running = false;
        }

        /**
         * Add message for sending.
         */
        public void send(String user, String message) {
            synchronized (messages) {
                messages.add("[" + user + "]: " + message);
                messages.notify();
            }
        }

        public void run() {

            while (running) {

                if (messages.size() == 0) {
                    try {
                        synchronized (messages) {
                            messages.wait();
                        }
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }

                synchronized (connections) {
                    String[] pendingMessages = null;
                    synchronized (messages) {
                        pendingMessages = messages.toArray(new String[0]);
                        messages.clear();
                    }
                    // Send any pending message on all the open connections
                    for (int i = 0; i < connections.size(); i++) {
                        try {
                            PrintWriter writer = connections.get(i).getWriter();
                            for (int j = 0; j < pendingMessages.length; j++) {
                                writer.println(pendingMessages[j] + "<br>");
                            }
                            writer.flush();
                        } catch (IOException e) {
                            log("IOExeption sending message", e);
                        }
                    }
                }

            }

        }

    }

}]]></source>

  </subsection>
  <subsection name="Comet timeouts">
    <p>If you are using the NIO connector, you can set individual timeouts for your different comet connections.
       To set a timeout, simply set a request attribute like the following code shows:</p>
    <source>CometEvent event.... event.setTimeout(30*1000);</source>
    <p>or</p>
    <source>event.getHttpServletRequest().setAttribute("org.apache.tomcat.comet.timeout", new Integer(30 * 1000));</source>
    <p>
       This sets the timeout to 30 seconds.
       Important note: in order to set this timeout, it has to be done on the <code>BEGIN</code> event.
       The default value is <code>soTimeout</code>
    </p>
    <p>If you are using the APR connector, all Comet connections will have the same timeout value. It is <code>soTimeout*50</code>
    </p>
  </subsection>

  </section>

  <section name="Asynchronous writes">

  <p>
    When APR or NIO is enabled, Tomcat supports using sendfile to send large static files.
    These writes, as soon as the system load increases, will be performed
    asynchronously in the most efficient way. Instead of sending a large response using
    blocking writes, it is possible to write content to a static file, and write it
    using a sendfile code. A caching valve could take advantage of this to cache the
    response data in a file rather than store it in memory. Sendfile support is
    available if the request attribute <code>org.apache.tomcat.sendfile.support</code>
    is set to <code>Boolean.TRUE</code>.
  </p>

  <p>
    Any servlet can instruct Tomcat to perform a sendfile call by setting the appropriate
    request attributes. It is also necessary to correctly set the content length
    for the response. When using sendfile, it is best to ensure that neither the
    request or response have been wrapped, since as the response body will be sent later
    by the connector itself, it cannot be filtered. Other than setting the 3 needed
    request attributes, the servlet should not send any response data, but it may use
    any method which will result in modifying the response header (like setting cookies).
  </p>

  <ul>
  <li><code>org.apache.tomcat.sendfile.filename</code>: Canonical filename of the file which will be sent as
      a String</li>
  <li><code>org.apache.tomcat.sendfile.start</code>: Start offset as a Long</li>
  <li><code>org.apache.tomcat.sendfile.end</code>: End offset as a Long</li>
  </ul>
  <p>
    In addition to setting these parameters it is necessary to set the content-length header.
    Tomcat will not do that for you, since you may have already written data to the output stream.
  </p>

  <p>
    Note that the use of sendfile will disable any compression that Tomcat may
    otherwise have performed on the response.
  </p>

  </section>

</body>
</document>
