Reputation: 11707
I'm trying to use long polling with JAX-RS (Jersey implementation) and it doesn't work as I expect. Maybe I'm misunderstanding something. I would appreciate any advice.
Please note that using a reverse connection (something like Atmosphere, Comet, etc) is not a option for security reason. Not that I'm currently developing with Tomcat 7.
The following method is invoked from a JQuery Ajax call (using $.ajax
).
@Path("/poll")
@GET
public void poll(@Suspended final AsyncResponse asyncResponse)
throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
this.asyncResponse = asyncResponse;
// wait max. 30 seconds using a CountDownLatch
latch.await(getTimeout(), TimeUnit.SECONDS);
}
}).start();
}
The other method is invoked from my application (after a JMS call):
@POST
@Path("/printed")
public Response printCallback() {
// ...
// I expect the /poll call to be ended here from the client perspective but that is not the case
asyncResponse.resume("UPDATE");
latch.countDown();
return Response.ok().build();
}
If I remove the Thread creation in the poll
method. Then it works, but the problem is that a Thread is busy. If I use the Thread creation, then the method is returning directly and the browser is not detecting the end of the long polling.
What am I doing wrong?
Upvotes: 4
Views: 6990
Reputation: 11707
I found the solution of my problem. The problem was in the configuration. We must specify that the Jersey servlet supports async
and then it works fine:
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<async-supported>true</async-supported>
...
</servlet>
Please note that if you have Servlet filters, they also need to be async-supported
to true.
This was also not necessary to create a thread. Jersey does it for me:
@Path("/poll")
@GET
public void poll(@Suspended final AsyncResponse asyncResponse)
throws InterruptedException {
asyncResponse.setTimeout(30, TimeUnit.SECONDS);
this.asyncResponse = asyncResponse;
}
@POST
@Path("/printed")
public Response printCallback(String barcode) throws IOException {
// ...
this.asyncResponse.resume("MESSAGE");
return Response.ok().build();
}
When calling poll
the browser waits until receiving MESSAGE
or receiving a HTTP status 503 if the timeout is elapsed. In the server, the request thread is not blocked until the timeout but released directly. In the client side, I have a JavaScript which is calling the method again if the timeout occurs, otherwise I process something in the page.
Upvotes: 4