2011-01-24 63 views
6

Tôi đang viết một ứng dụng Java dành cho doanh nghiệp sử dụng các phương thức EJB 3.1 không đồng bộ để thực hiện một số tác vụ song song. Để hỗ trợ hủy một tác vụ chạy dài, tôi đã cố gắng sử dụng giao diện Tương lai.Hủy cuộc gọi EJB không đồng bộ @

Thật không may khi gọi future.cancel(true) từ ứng dụng khách sẽ không ảnh hưởng đến ngữ cảnh phiên của bean thực hiện tác vụ, mặc dù thực tế lệnh hủy đang trả về true.

Tôi có một giao diện đơn giản:

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

Với cài đặt bean như sau:

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

Mã khách hàng là thẳng về phía trước:

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"); 
} 

Sản lượng từ đậu là một luồng vô tận của "Làm việc"; nó không bao giờ phát hiện việc hủy bỏ.

Trong trường hợp có liên quan, tôi đang chạy ứng dụng trên Máy chủ ứng dụng JBoss 6.0.0. Tôi đã không đặt nhiều mẫu mã bằng cách sử dụng tính năng hủy bỏ của giao diện tương lai, vì vậy tôi tự hỏi nếu tôi đang sử dụng tương lai một cách chính xác. Việc sử dụng này có chính xác không? Có các tùy chọn tốt hơn để hủy cuộc gọi phương thức EJB không đồng bộ không?

+0

Đó là một hành vi kỳ quặc vì nếu phương thức hủy trả về true, cho biết phương thức bean phiên của bạn sẽ không được gọi (lý do là vì khi bạn gọi hủy, phương thức có thể đang chạy). Bạn có thể kiểm tra thêm thông tin về điều này trong phần 3.4.8.1.1 của đặc tả EJB 3.1. –

+0

Liên kết câu hỏi này với câu hỏi tương tự, nhưng đối với glassfish http://stackoverflow.com/q/16493381/3701228 – Gas

Trả lời

2

Bạn phải return một loại đối tượng, thay vì null. Nhân tiện, bạn không nhận được NPE? Tôi mong đợi một, với mã của bạn trong câu hỏi.

Hơn nữa, không được gọi cancel(). See the docs here. Nhân tiện, nó không chỉ được gọi là phương pháp cancel() mà không nên gọi, không có phương pháp thể hiện nào được gọi, theo số docs. Mà đặt ra câu hỏi rằng tại sao heck sau đó một phương pháp nên trả lại AsyncResult. Tôi chỉ đơn giản là không có ý tưởng, có thể là của nó để sử dụng trong tương lai. Tuy nhiên, class level comments đang gợi ý rằng tất cả các phương pháp đều có để thuận tiện cho việc cung cấp kết quả cho vùng chứa.

Do đó, tôi không chắc chắn liệu việc hủy cuộc gọi EJB không đồng bộ có thể thực hiện được hay không.

[Sửa sau khi một nghiên cứu nhỏ]

Hãy thử thực hiện này,

@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; 
    } 
} 
+0

Có, tôi phải trả về Tương lai thay vì null. Tôi đã thay đổi mã để trả lại một AsyncResult thay thế (một thực hiện tương lai). Nó không gây ra Null Pointer Exception vì mã không bao giờ vượt qua vòng lặp while. Kết quả đã không thay đổi mặc dù, hủy bỏ vẫn không được phát hiện. – malloc

+0

@malloc: Bạn đã thử in một cái gì đó trước 'future.cancel (true)'? Chỉ để xem liệu dòng đó có được thực thi hay không. –

+0

@Adeel: Có, 'future.cancel (true)' đang thực hiện và trả về 'true'. Tôi đã chỉnh sửa mã trong câu hỏi ban đầu để bao gồm các thay đổi. – malloc

3

Trả lời câu hỏi của riêng tôi - Tôi đã phát hiện ra rằng cancallation yêu cầu không đồng bộ không được hỗ trợ trong JBoss AS 6.0 .0.

Thay vào đó, tôi đã tái cấu trúc mã để sử dụng tính năng nhắn tin kiểu yêu cầu/phản hồi JMS.

Đậu điều khiển thông điệp được sử dụng để thực thi thao tác không đồng bộ. Bean điều khiển thông điệp tạo ra một hàng đợi tạm thời và trả về hàng đợi cho người gọi qua JMS. Điều này đạt được bằng cách sử dụng trường replyTo của các tin nhắn JMS.

Hạt điều khiển thông báo sau đó định kỳ kiểm tra hàng đợi tạm thời cho thông báo hủy.

Điều này phức tạp hơn phiên bản @Asynchronous nhưng nó hoạt động trên JBoss AS 6.0.0.

Các vấn đề liên quan