2012-01-03 18 views
8

Tôi có một hạt CDI @RequestScoped mà tôi muốn biến thành một EJB để nhận các giao dịch khai báo. (Tôi đang sử dụng EJB 3.1, Java EE 6)Chuyển trạng thái giữa các phương thức EJB/@RequestScoped và @Stateless

Hiện tại, tôi đang chuyển trạng thái giữa các chương trình con, theo giả định rằng cá thể chỉ được sử dụng trong một yêu cầu duy nhất. Nếu tôi thêm @Stateless thì giả định đó sẽ thay đổi.

Ví dụ, tôi muốn làm một cái gì đó giống như

@Stateless 
@Named 
@RequestScoped 
public class Foo { 
    private String var1; // can't use instance vars in @Stateless? 
    private String var2; 

    public void transactionForRequest() { 
    var1 = value; 
    var2 = value; 
    .... 
    subroutine(); 
    } 
} 

tôi giả định trên không work- đó là chính xác?

Tôi đang suy ngẫm về hai lựa chọn:

  • Sử dụng @Stateful thay vì @Stateless, cùng với @Named và @RequestScoped.
  • Giữ @Stateless và sử dụng EJBContext.getContextData bản đồ để thay thế các biến mẫu.

Điều nào tốt hơn? Và có một số thay thế khác mà tôi không nghĩ đến? (Bên cạnh việc chờ Java EE 7 hoặc chuyển sang Spring. :-))

+0

Sử dụng '@ Stateful' có thể là một kỹ năng quá mức. Bạn đã cân nhắc sử dụng bean không bình thường và '@ ConversationScoped' được quản lý để vượt qua các tiểu bang? –

+0

cách thức hoạt động - bạn có thể tạo EJB '@ Stateless' sau đó' @ Tiêm' một hạt CDI không? Đậu CDI này có thể là '@ RequestScoped' không? – wrschneider

+0

Tôi sẽ giữ bean là '@ Stateless' và sử dụng' @ ConversationScoped' bean để chuyển các biến từ trang này sang trang khác. Hãy xem [bài viết] này (http://blog.goyello.com/2011/06/08/jee6-cdi-and-conversation-scope/) về cách tạo thuật sĩ. –

Trả lời

12

Trong khi @Stateless, @Singleton@MessageDriven tài liệu tham khảo có thể đã scoped tiêm qua @Inject, họ không có thể@RequestScoped hoặc bất kỳ phạm vi nào khác. Chỉ có mô hình @Stateful đủ linh hoạt để hỗ trợ phạm vi. Nói cách khác, bạn có thể chú thích các lớp @Stateful đậu chính nó như là @RequestScoped, @SessionScoped, vv ..

Trong thuật ngữ đơn giản @Stateless, @Singleton đã cố định "phạm vi" rồi. @Singleton về cơ bản là @ApplicationScoped@Stateless có lẽ sẽ là một số phạm vi được thiết lập như @InvocationScoped, nếu tồn tại. Vòng đời của một hạt @MessageDriven hoàn toàn phụ thuộc vào Trình kết nối ổ đĩa và do đó cũng không được phép có phạm vi do người dùng xác định.

Xem thêm https://stackoverflow.com/a/8720148/190816

+0

David, chỉ để chắc chắn - Nếu tôi có tham chiếu '@ RequestScoped' đến' @ Stateless' EJB - nó mua cho tôi cái gì? Tôi sẽ nhận được cùng một tham chiếu trong toàn bộ yêu cầu, nhưng nó vẫn (có thể) là một tham chiếu đến proxy, vì vậy mỗi khi tôi sử dụng tham chiếu này, tôi có thể kết thúc trong trường hợp EJB khác nhau. Điều này có đúng không? –

+0

Chính xác. Để đưa nó vào quan điểm, trong OpenEJB chúng tôi chỉ tạo một proxy cho mỗi bean không trạng thái và chia sẻ với toàn bộ ứng dụng. Tương tự cho Singleton. Trong trường hợp đặt RequestScoped (hoặc phạm vi khác) trên một Stateless hoặc Singleton, nó sẽ được coi là một lỗi khi triển khai. Tôi phải kiểm tra kỹ spec và TCK về điều đó, nhưng đó chắc chắn là cách tôi làm. Bất cứ điều gì khác chỉ là gây hiểu lầm. –

+0

Cảm ơn vì đã làm rõ David. Nó chỉ là một thời gian khi kết nối giữa EJB và CDI có thể mất phương hướng ... –

1

Nếu bạn đang sử dụng bean không quốc tịch, bạn chịu trách nhiệm quản lý nhà nước và thường làm điều này trong lớp ứng dụng web bằng HttpSessions. Và có, bạn không thể sử dụng các biến mẫu như các bean không trạng thái được gộp chung.

3

Tôi sẽ đi với SFSB thay vì SLSB. Bạn muốn giữ một trạng thái, vì vậy đối với tôi đây là thông tin quan trọng nhất - đây là một công việc cho Stateful EJB.

Ngoài ra tôi không nghĩ rằng EJBContext#getContextData() sẽ giúp bạn. Theo tôi nhớ, nó chỉ hợp lệ trong một thời gian của một cuộc gọi. Do đó, mỗi lời gọi của một phương pháp trên EJB của bạn sẽ tạo mới dữ liệu bản đồ ngữ cảnh (ít nhất đó là những gì tôi mong đợi.)

+0

Rất vui khi nghe @Stateful + @RequestScoped sẽ hoạt động - vì bất kỳ lý do gì, "bean phiên trạng thái" vẫn giống như một từ bẩn nhưng "bean phiên yêu cầu" có vẻ tốt hơn nhiều. Ngoài ra - 'EJBContext # getContextData()' hoạt động tốt cho tôi trong tình huống này vì chương trình con là một cuộc gọi phương thức cục bộ ('this.subroutine()') chứ không phải là một lời gọi EJB. – wrschneider

+0

Bạn nói đúng - nếu cuộc gọi nội hạt của nó hơn là dữ liệu ngữ cảnh thì tốt. Tôi nghĩ bạn đã tiêm EJB của bạn ('@ EJB' hoặc' @ Inject') và gọi một số phương thức trên cá thể proxy. –

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