2011-01-24 36 views
6

我正在編寫一個企業Java應用程序,它使用異步EJB 3.1方法並行執行多個任務。爲了支持取消長時間運行的任務,我一直在嘗試使用Future界面。取消@Asynchronous EJB調用

不幸的是,從客戶端應用程序調用future.cancel(true)似乎對執行任務的bean的會話上下文沒有影響,儘管取消調用返回true

我有一個簡單的界面:

public interface AsyncInterface 
{ 
    Future<Integer> run() throws Exception; 
} 

有了一個bean實現如下:

@Stateless 
@Remote(AsyncInterface.class) 
public class AsyncBean 
{ 
    @Resource SessionContext myContext; 

    @Asynchronous 
    public Future<Integer> run() throws Exception 
    { 
     Integer result = 0; 

     System.out.println("Running AsyncBean"); 

     while(myContext.wasCancelCalled() == false) 
     { 
      Thread.sleep(2000); 
      System.out.println("Working"); 
     }  

     System.out.println("AsyncBean cancelled"); 

     return new AsyncResult<Integer>(result); 
    } 
} 

客戶端代碼是直截了當:

InitialContext ctx = new InitialContext(); 
AsyncInterface async = (AsyncInterface)ctx.lookup("AsyncBean/remote"); 
Future<Integer> future = async.run(); 

if(future.cancel(true)) 
{ 
    System.out.println("future.cancel() returned true"); 
} 
else 
{ 
    System.out.println("future.cancel() returned false"); 
} 

從bean輸出是「工作」的層出不窮的流;它從未檢測到取消。

如果相關,我在JBoss Application Server 6.0.0上運行應用程序。我沒有使用Future界面的取消功能找到很多示例代碼,所以我想知道我是否正確使用Future。這個用法看起來是否正確?取消異步EJB方法調用是否有更好的選擇?

+0

這是一個奇怪的行爲,因爲如果cancel方法返回true,則表明您的會話bean方法不會被調用(原因是當您調用cancel時,該方法可能已經在運行)。您可以在EJB 3.1規範的3.4.8.1.1節中查看更多相關信息。 – 2011-02-11 05:07:17

+0

將此鏈接連接到類似的問題,但對於glassfish http://stackoverflow.com/q/16493381/3701228 – Gas 2014-11-19 23:42:16

回答

2

您必須return a Future類型的對象,而不是null。順便說一下,你沒有得到NPE嗎?我希望有一個,你的代碼有問題。

此外,不應調用cancel()See the docs here。順便說一下,根據docs,不應該調用不應該調用的cancel()方法,也不應調用實例方法。這引出了一個問題,爲什麼到時候方法應該返回AsyncResult。我根本不知道,可能是它的未來使用。但是class level comments暗示所有的方法都是爲了方便將結果提供給容器。

因此,我不確定是否可以取消異步EJB調用。

試試這個實現[一個小小的研究後編輯],

@Stateless 
@Remote(AsyncInterface.class) 
public class AsyncBean 
{ 
    @Resource SessionContext myContext; 

    @Asynchronous 
    public Integer run() throws Exception 
    { 
     Integer result = 0; 

     System.out.println("Running AsyncBean"); 

     while(myContext.wasCancelCalled() == false) 
     { 
      Thread.sleep(2000); 
      System.out.println("Working"); 
     }  

     System.out.println("AsyncBean cancelled"); 

     return result; 
    } 
} 
3

回答我的問題 - 我發現,異步請求的cancallation在JBoss中不支持AS 6.0 0.0。

作爲替代方案,我重構了使用JMS請求/響應式消息傳遞的代碼。

消息驅動bean用於執行異步操作。消息驅動bean創建一個臨時隊列,並通過JMS將隊列返回給調用者。這是通過利用JMS消息的replyTo字段來實現的。

消息驅動bean然後定期檢查臨時隊列中的取消消息。

這比@Asynchronous版本更復雜,但它適用於JBoss AS 6.0.0。