2013-01-15 18 views
6

Java EEアプリケーションをJBoss 7.1.1.Finalにデプロイしました。このアプリケーションは、JAX-RSを使用してクライアントにRESTサービスを提供します。応答オブジェクトがBlockingQueueを介して受信されるまで、サービスの1つはクライアント接続を保持します。それはこれまでのところうまくいくようです。ただし、アプリケーションのデプロイメントが削除されても、アプリケーションがシャットダウンされても、接続は開いたままです。 JBossのシャットダウンも防止します。JAX-RS AJAXリクエストを正しく中断する方法

私は@PreDestroyコールバックで待機中のスレッドを中断してクリーンシャットダウンを実行しようとしていました。サービスは次のようになります。

@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(); 
    } 
    } 
} 

クライアントは期待される応答を受け取ります。しかし、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 

これはちょうどいい気分ではありません。このような待機要求を中断する適切な方法は何ですか?

+5

コールバックトークンを使用してすぐに202ステータスをクライアントに返すことができない理由はありますか?それはよりRESTfulになります。いずれにしても、即座に1つの変更を行うことができます。 – Perception

+0

リクエストをイベントのライブフィードと考えてください。アプリケーションは、そのようなイベントがいつ、いつ発生するかを判断することはできません。即時の202応答は、利益のための負荷を生成するだけでしょうか?また、ループでのタイムアウトのポーリングがどのように状況を改善するのに役立つかはわかりません。説明してください。 – riha

+4

あなたのユースケースに合わせてCometフレームワークを使用する方が良いかもしれません。理由は、Webアプリケーションサーバーが着信要求を処理するためにスレッドプールを使用しているため、かなり長い時間(おそらく)スレッドを保持しているからです。 – Perception

答えて

0

コンテナによって作成されたスレッドを中断しているため、コンテナはスレッド自体を終了できません。中断するのではなく、状態変数を使用して、スレッドが終了するかどうかを確認することができます。 (擬似コードとしてそれを解釈):

while(! stopped) { 
    MyObject object = queue.poll(25, TimeUnit.MILLISECONDS); 

    return Response.ok(object) 
     .type(MediaType.TEXT_XML) 
     .build(); 
} 

return Response.noContent().build(); 

@PreDestroytrueに停止セット。また、AsyncResponse機能もあります。開いているすべてのリクエストをリストに保存してから、@PreDestroyでキャンセルすることができます。

関連する問題