<chapter id="Asynchronous_HTTP_Request_Processing">
   <title>Asynchronous HTTP Request Processing</title>
   <para>
      Asynchronous HTTP Request Processing is a relatively new technique that allows the processing of a single HTTP
      request using non-blocking I/O and, if desired in separate threads. Some refer to it as COMET capabilities.
      The primary use case for Asynchronous HTTP is
      in the case where the client is polling the server for a delayed response. The usual example is an AJAX chat
      client where you want to push/pull from both the client and the server. These scenarios have the client blocking
      a long time on the server’s socket waiting for a new message. In synchronous HTTP where the server is
      blocking on incoming and outgoing I/O is that you have a thread consumed per client connection.
      This eats up memory and valuable thread resources. Not such a big deal in 90% of applications (in fact using
      asynchronous processing may actually hurt performance in most common scenarios), but when there are
      a lot of concurrent clients that are blocking like this, there is a lot of wasted resources and the
      server does not scale that well.
   </para>
   <sect1>
      <title>Using the <code>@Suspended</code> annotation</title>
      <para>
         The &REST-API; specification includes asynchronous HTTP support via two classes. The <code>@Suspended</code> annotation,
         and AsyncResponse interface.
      </para>
      <para>
          Injecting an AsyncResponse as a parameter to a &REST-API; methods tells RESTEasy that the HTTP request/response should be detached from the currently
         executing thread and that the current thread should not try to automatically process the response.
      </para>
      <para>
         The AsyncResponse is the callback object.
         The act of calling one of the resume() methods will cause a response to be sent back to the client and will also terminate the
         HTTP request. Here is an example of asynchronous processing:
      </para>
   
      <programlisting>
import jakarta.ws.rs.Suspend;
import jakarta.ws.rs.container.AsyncResponse;

@Path("/")
public class SimpleResource
{

   @GET
   @Path("basic")
   @Produces("text/plain")
   public void getBasic(@Suspended final AsyncResponse response) throws Exception
   {
      Thread t = new Thread()
      {
         @Override
         public void run()
         {
            try
            {
               Response jaxrs = Response.ok("basic").type(MediaType.TEXT_PLAIN).build();
               response.resume(jaxrs);
            }
            catch (Exception e)
            {
               response.resume(e);
            }
         }
      };
      t.start();
   }
}
      </programlisting>
      <para>
         AsyncResponse also has other methods to cancel the execution.  See javadoc for more details.
      </para>
      <para>
         <emphasis role="bold">NOTE:</emphasis>
         In RESTEasy version 4.0.0.Final proprietary annotation
         <code>org.jboss.resteasy.annotations.Suspend</code> was removed
         and replaced by <code>jakarta.ws.rs.container.Suspended</code> and class
         <code>org.jboss.resteasy.spi.AsynchronousResponse</code> was removed and replaced by
         <code>jakarta.ws.rs.container.AsyncResponse</code>.
      </para>
      <para>
         <code>jakarta.ws.rs.container.Suspended</code> replaces <code>javax.ws.rs.container.Suspended</code>.
          Note that @Suspended does not have a value field,
         which represented a timeout limit. Instead, <methodname>AsyncResponse.setTimeout()</methodname> may be called.
      </para>
   </sect1>
   <sect1>
      <title>Using Reactive return types</title>
      <para id="CompletionStage">
          The &REST-API; 2.1 specification adds support for declaring asynchronous resource methods by
          returning a <code>CompletionStage</code> instead of using the <code>@Suspended</code>
          annotation.
      </para>
      <para>
          Whenever a resource method returns a <code>CompletionStage</code>, it will be subscribed to,
          the request will be suspended, and only resumed when the <code>CompletionStage</code> is
          resolved either to a value (which is then treated as the return value for the method), or
          as an error case, in which case the exception will be processed as if it were thrown by the
          resource method.
      </para>
      <para>
          Here is an example of asynchronous processing using <code>CompletionStage</code>:
      </para>
      <programlisting>
import jakarta.ws.rs.Suspend;
import jakarta.ws.rs.container.AsyncResponse;

@Path("/")
public class SimpleResource
{

   @GET
   @Path("basic")
   @Produces("text/plain")
   public CompletionStage&lt;Response&gt; getBasic() throws Exception
   {
      final CompletableFuture&lt;Response&gt; response = new CompletableFuture&lt;&gt;();
      Thread t = new Thread()
      {
         @Override
         public void run()
         {
            try
            {
               Response jaxrs = Response.ok("basic").type(MediaType.TEXT_PLAIN).build();
               response.complete(jaxrs);
            }
            catch (Exception e)
            {
               response.completeExceptionally(e);
            }
         }
      };
      t.start();
      return response;
   }
}
     </programlisting>
     <note>
        <para>
           RESTEasy <link linkend="Reactive">supports more reactive types for asynchronous programming</link>.
        </para>
     </note>
   </sect1>
   <sect1>
      <title>Asynchronous filters</title>
      <para>
         It is possible to write <link linkend="Asynchronous_Filter">filters that also make the request asynchronous</link>.
         Whether filters make the request asynchronous
         before execution of a method makes absolutely no difference to a method: it does not need to be declared asynchronous in
         order to function as specified. Synchronous methods and asynchronous methods will work as specified by the spec.
      </para>
    </sect1>
   <sect1 id="Asynchronous_IO">
      <title>Asynchronous IO</title>
      <para>
         Some backends support asynchronous IO operations (Servlet, Undertow, Vert.x, Quarkus, Netty), which are exposed using the
         <code>AsyncOutputStream</code> subtype of <code>OutputStream</code>. It includes async variants for writing and flushing
         the stream.
      </para>
      <para>
         Some backends have what is called an "Event Loop Thread", which is a thread responsible for doing all IO operations. Those
         backends require the Event Loop Thread to never be blocked, because it does IO for every other thread. Those backends
         typically require &REST-API; endpoints to be invoked on worker threads, to make sure they never block the Event Loop Thread.
      </para>
      <para>
         Sometimes, with Async programming, it is possible for asynchronous &REST-API; requests to be resumed from the Event Loop Thread.
         As a result, &REST-API; will attempt to serialise the response and send it to the client. But &REST-API; is written using "Blocking IO"
         mechanics, such as <code>OutputStream</code> (used by <code>MessageBodyWriter</code> and <code>WriterInterceptor</code>), which
         means that sending the response will block the current thread until the response is received. This would work on a worker thread,
         but if it happens on the Event Loop Thread it will block it and prevent it from sending the response, resulting in a deadlock.
      </para>
      <para>
         As a result, we've decided to support and expose Async IO interfaces in the form of <code>AsyncOutputStream</code>,
         <code>AsyncMessageBodyWriter</code> and <code>AsyncWriterInterceptor</code>, to allow users to write Async IO applications
         in RESTEasy.
      </para>
      <para>
         Most built-in <code>MessageBodyWriter</code> and <code>WriterInterceptor</code> support Async IO, with the notable exceptions of:
      </para>
      <itemizedlist>
        <listitem><para><code>HtmlRenderableWriter</code>, which is tied to servlet APIs</para></listitem>
        <listitem><para><code>ReaderProvider</code></para></listitem>
        <listitem><para><code>StreamingOutputProvider</code>: use <code>AsyncStreamingOutput</code> instead</para></listitem>
      </itemizedlist>
      <para>
         Async IO will be preferred if the following conditions are met:
      </para>
      <itemizedlist>
        <listitem><para>The backend supports it</para></listitem>
        <listitem><para>The writer supports it</para></listitem>
        <listitem><para>All writer interceptors support it</para></listitem>
      </itemizedlist>
      <para>
         If those conditions are not met, and you attempt to use Blocking IO on an Event Loop Thread (as determined by the
         backend), then an exception will be thrown.
      </para>
    </sect1>
</chapter>