HttpServlet30Dispatcher is also configured as default servlet dispatcher in Servlet 3.0 containers via the ServletContainerInitializer if there is no resteasy servlet or filter is defined in web.xml.
Filter30Dispatcher and HttpServlet30Dispatcher can all be set to process @Suspend.  But as old FilterDispatcher, it can delegate back to the base servlet container to resolve URLs if
a JAX-RS resource is not found.


On 10/13/2016 12:24 AM, Rebecca Searls wrote:
Resteasy is using org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher in processing @Suspended.
We use it in test cases here, ./testsuite/integration-tests/src/test/resources/org/jboss/resteasy/test/asynch


----- Original Message -----
From: "Steven Schlansker" <sschlansker@opentable.com>
To: resteasy-dev@lists.jboss.org
Sent: Tuesday, October 11, 2016 7:16:29 PM
Subject: Re: [resteasy-dev] RESTEasy asynchronous processing with @Suspended -- actually synchronous?

Hi again,

I was somewhat disappointed to not get an answer here, but I did a fair
amount more digging,
and managed to find Filter30Dispatcher (which just moved recently for
upcoming 3.1.0)

Unfortunately then I found that the documentation does not mention this
class at all, but at least it exists!
(at least not on
http://docs.jboss.org/resteasy/docs/3.0.19.Final/userguide/html_single/index.html
)

So far it seems to work well.  Better than FilterDispatcher, at least :)
Let me know if there's any gotchas or other bits that I've missed.

Best,
Steven

On Oct 7, 2016, at 1:21 PM, Steven Schlansker <sschlansker@opentable.com>
wrote:

[ apologies for the rampant cross-posting, it looks like I might have been
sending this to old mailing lists, and getting lost in the void? ]

Hello resteasy-dev,

I am trying to use the new JAX-RS 2.0 @Suspended AsyncResponse mechanism to
write
a service that expects many idling connections (awaiting an event via
long-poll),
and therefore seems like a good candidate for asynchronous responses, so as
not
to use a large number of waiting threads.

The resource code is very simple:

 @GET
 @Produces(MediaType.APPLICATION_JSON)
 public void watchForChanges(
         @Suspended AsyncResponse asyncResponse,
         @QueryParam("since") long since)
 {
     controller.watchForChanges(since, asyncResponse::resume);
 }

The intent is that watchForChanges places the (inferred)
Consumer<ResponseObject> on a queue,
and returns immediately.  Later on a background thread comes by and
completes the request.

However, when testing with say 20 clients, it sure looks like the end
result is still a
thread per request model:


"qtp1718322084-43" - Thread t@43
java.lang.Thread.State: WAITING
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for <3537ebd5> (a
	java.util.concurrent.CountDownLatch$Sync)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at
	java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
	at
	java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997)
	at
	java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)
	at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231)
	at
	org.jboss.resteasy.core.SynchronousExecutionContext$SynchronousAsynchronousResponse.initialRequestThreadFinished(SynchronousExecutionContext.java:127)
	at
	org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:411)
	at
	org.jboss.resteasy.core.SynchronousDispatcher.invokePropagateNotFound(SynchronousDispatcher.java:247)
	at
	org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:225)
	at
	org.jboss.resteasy.plugins.server.servlet.FilterDispatcher.doFilter(FilterDispatcher.java:62)
	at
	org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
<snip Jetty handler / filter chain>
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
	at
	org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
	at
	org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
	at
	org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
	at
	org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
	at
	org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
	at
	org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
	at
	org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
	at
	org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
	at java.lang.Thread.run(Thread.java:745)



The concept of a "SynchronousAsynchronousResponse" and implementation of in
particular SynchronousDispatcher#invoke seem to be totally not what I
want:
         /**
          * Callback by the initial calling thread.  This callback will
          probably do nothing in an asynchronous environment
          * but will be used to simulate AsynchronousResponse in vanilla
          Servlet containers that do not support
          * asychronous HTTP.
          *
          */
         request.getAsyncContext().getAsyncResponse().initialRequestThreadFinished();


What am I doing wrong?  How do I get truly asynchronous processing?

This is with RESTEasy 3.0.18 running on Jetty 9.3.11

Thanks for any advice,
Steven

_______________________________________________
resteasy-dev mailing list
resteasy-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/resteasy-dev

_______________________________________________
resteasy-dev mailing list
resteasy-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/resteasy-dev