[英]How to properly interrupt JAX-RS AJAX request
I have a Java EE application deployed to JBoss 7.1.1.Final. 我有一个部署到JBoss 7.1.1.Final的Java EE应用程序。 The application makes use of JAX-RS to provide REST services to clients.
该应用程序利用JAX-RS为客户端提供REST服务。 One of the services holds the client connection until the response object is received via a
BlockingQueue
. 其中一个服务保持客户端连接,直到通过
BlockingQueue
接收响应对象。 That seems to work fine so far. 到目前为止,这似乎工作正常。 However, the connection is kept open even if the application deployment is removed / the application is shutdown.
但是,即使删除了应用程序部署/关闭了应用程序,连接也会保持打开状态。 It even prevents JBoss from shutting down.
它甚至可以阻止JBoss关闭。
So I was trying to perform a clean shutdown by interrupting the waiting thread via a @PreDestroy
callback. 所以我试图通过
@PreDestroy
回调中断等待线程来执行干净关闭。 The service looks like this: 该服务看起来像这样:
@Path("/mypath")
@SessionScoped
public class MyResource implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private EntityManager em;
private Thread thread = null;
@GET
@Path("/{id:[0-9][0-9]*}")
@Produces({
MediaType.TEXT_PLAIN,
MediaType.TEXT_XML
})
public Response getObjects(@PathParam("id") long id) {
MyGroup group = this.em.find(MyGroup.class, id);
if (group == null) {
return Response.status(Status.NOT_FOUND)
.entity("Group not found\n")
.build();
}
if (group.isEmpty()) {
return Response.status(Status.PRECONDITION_FAILED)
.entity("Group is empty\n")
.build();
}
BlockingQueue<?> queue = ... // Get queue for group
this.thread = Thread.currentThread();
try {
MyObject object = queue.take();
} catch (InterruptedException e) {
return Response.noContent().build();
}
return Response.ok(object)
.type(MediaType.TEXT_XML)
.build();
}
@PreDestroy
public void shutdown() {
if (this.thread != null) {
this.thread.interrupt();
}
}
}
It seems to work, sort of... The client receives the expected response. 它似乎有效,有点......客户收到预期的响应。 However, JBoss prints this exception:
但是,JBoss打印此异常:
13:38:44,489 ERROR [org.jboss.as.txn] JBAS010151: Unable to get transaction state: java.lang.IllegalStateException
at org.jboss.msc.value.InjectedValue.getValue(InjectedValue.java:47)
at org.jboss.as.txn.deployment.TransactionRollbackSetupAction.teardown(TransactionRollbackSetupAction.java:43)
at org.jboss.as.web.ThreadSetupBindingListener.unbind(ThreadSetupBindingListener.java:61) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:195) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
at java.lang.Thread.run(Thread.java:636) [rt.jar:1.6.0_18]
13:38:44,492 ERROR [org.apache.catalina.connector.CoyoteAdapter] An exception or error occurred in the container during the request processing: java.lang.RuntimeException: java.lang.IllegalStateException
at org.jboss.as.web.ThreadSetupBindingListener.unbind(ThreadSetupBindingListener.java:67) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:195) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
at java.lang.Thread.run(Thread.java:636) [rt.jar:1.6.0_18]
Caused by: java.lang.IllegalStateException
at org.jboss.msc.value.InjectedValue.getValue(InjectedValue.java:47)
at org.jboss.as.connector.deployers.processors.CachedConnectionManagerSetupProcessor$CachedConnectionManagerSetupAction.teardown(CachedConnectionManagerSetupProcessor.java:83)
at org.jboss.as.web.ThreadSetupBindingListener.unbind(ThreadSetupBindingListener.java:61) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
... 8 more
That just doesn't feel right. 那感觉不对劲。 What is the proper way to interrupt such a waiting request?
中断这种等待请求的正确方法是什么?
You are interrupting a thread that was created by the container, hence the container fails to finish the thread itself. 您正在中断由容器创建的线程,因此容器无法完成线程本身。 Instead of interrupting you could use a state variable to check if the thread should end, eg (interpret it as pseudo-code):
您可以使用状态变量来检查线程是否应该结束,而不是中断,例如(将其解释为伪代码):
while( ! stopped ) {
MyObject object = queue.poll(25, TimeUnit.MILLISECONDS);
return Response.ok(object)
.type(MediaType.TEXT_XML)
.build();
}
return Response.noContent().build();
and set stopped to true
in the @PreDestroy
. 并在
@PreDestroy
中将stopped设置为true
。 Also there is the AsyncResponse feature. 还有AsyncResponse功能。 Where you could store all open requests in a list and then cancel them at
@PreDestroy
. 您可以将所有打开的请求存储在列表中,然后在
@PreDestroy
取消它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.