2012-01-02 31 views
10

Tôi đang sử dụng EclipseLink trên GlassFish 3.1.1 và tôi đang cố gắng để hiểu được ngoại lệ này:javax.ejb.EJBException: bất hợp pháp truy cập phương pháp phi kinh doanh trên không giao diện xem

javax.ejb.EJBException: Illegal non-business method access on no-interface view 
    at org.mycompany.myproject.session.__EJB31_Generated__MyBeanFacade__Intf____Bean__.getEntityManager(Unknown Source) 
    at org.mycompany.myproject.session.AbstractFacade.edit(AbstractFacade.java:28) 
    at org.mycompany.myproject.controller.EditMyBeanServlet.doPost(EditMyBeanServlet.java:199) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) 

Chú ý rằng stack trace chỉ ra rằng vấn đề được kích hoạt trong phương thức AbstractFacade.getEntityManager của Netbeans.

Bất kỳ ý tưởng nào về sự cố xảy ra hoặc bất kỳ mẹo nào để khắc phục sự cố? Tôi đoán rằng hoặc giao dịch hoặc trạng thái bộ nhớ đệm trong EJB là lạ khi điều này xảy ra bởi vì đôi khi gọi phương thức chỉnh sửa hoạt động tốt. Tôi đang gọi các phương thức EJB từ Servlet. Ngoại lệ xảy ra khi cố lưu các thay đổi đối với một thực thể.

Trả lời

3

Tôi nghĩ rằng tôi có thể đã tìm thấy giải pháp và có thể là lỗi trong phần mềm của bên thứ ba. Có vẻ như GlassFish 3.1.1/EJB 3.1/EclipseLink không thể xử lý chính xác quá tải phương thức. Tôi đã có một phương thức được định nghĩa trong EJB của tôi có tên là chỉnh sửa quá tải (không ghi đè) phương thức từ lớp trừu tượng gốc. Có một phương thức được đặt tên là chỉnh sửa trong phần tử trừu tượng của EJB có một kiểu generic và sau đó tôi đã có một phương thức có tên là edit trong EJB có một List. Nếu tôi đổi tên phương thức thành một thứ khác để nó không còn quá tải thì ngoại lệ sẽ biến mất!

Code:

public abstract class AbstractFacade<T> { 
protected abstract EntityManager getEntityManager(); 
public void edit(T entity) { 
... 

@Stateless 
public class MyEntityFacade extends AbstractFacade<MyEntity> { 
protected EntityManager getEntityManager() { return em;) 
public void edit(List<MyEntity> entities) { 
... 

Lưu ý: Tôi nhận thấy nếu tôi có phương pháp nào getEntityManager thay vì bảo vệ tôi sẽ nhận được một TransactionRequiredException thay vì một EJBException.

+0

Nói cách khác: nó xuất hiện EclipseLink không thể xử lý quá tải các phương pháp kế thừa trong một EJB – Ryan

+3

Có liên quan đến vấn đề này không? http://java.net/jira/browse/GLASSFISH-17235 –

+0

@ piotr-nowicki - Bingo, tôi nghĩ bạn đã tìm thấy báo cáo vấn đề về sự cố. Cảm ơn. Buồn cười rằng ai đó đã bình chọn câu trả lời này! – Ryan

27

Lỗi bạn có nhiều khả năng nhất là mã của bạn đang cố gắng gọi phương thức được bảo vệ. Điều này không được phép cho các giao diện không có giao diện trên EJB. Bạn chỉ được phép gọi phương thức công khai.

Có sự không phù hợp nhỏ ở đây giữa các quy tắc lớp Java thông thường và các quy tắc EJB. Đối với chế độ xem không có giao diện, proxy được tạo dựa trên loại lớp gốc (thường là lớp con động của nó). Điều này có nghĩa là các phương thức riêng tư được bảo vệ và gói được hiển thị cho mã trong cùng một gói và theo như trình biên dịch Java có liên quan, mã của bạn được phép gọi chúng.

Nhưng như đã đề cập, điều này không được phép theo quy tắc EJB, và do đó ngoại lệ được ném.

Bạn có thể tái sản xuất này một cách dễ dàng bằng cách tiêm một bean như sau:

@Stateless 
public class FooBean { 

    public void callMe() { 
    } 

    protected void doNotCallMe() { 
    } 
} 

Tiêm một nơi nào đó (ví dụ Servlet trong cùng một gói) và cố gắng gọi doNotCallMe(). Bạn sẽ thấy cùng một ngoại lệ. Gọi callMe() và mọi thứ sẽ ổn.

+0

Có, tôi hiểu rằng chỉ có các phương thức công khai là một phần của giao diện EJB. Tuy nhiên tôi đang thực sự gọi một phương thức công khai có tên là chỉnh sửa từ servlet (mã được cung cấp trong câu trả lời của tôi). Dường như có lỗi với các phương thức quá tải nhất định. – Ryan

+1

Ok, đó cũng có thể là trường hợp. Nếu không có mã servlet thực tế thì cuộc gọi này khó nói. Câu trả lời của tôi do đó không thực sự áp dụng cho vấn đề của bạn, mặc dù tôi hy vọng mọi người tìm kiếm các ngoại lệ trong tiêu đề của bạn tìm thấy lời giải thích hữu ích anyway. Tôi sẽ upvote câu trả lời của bạn;) –

+0

cảm ơn đã dành thời gian để trả lời câu hỏi của tôi. Tôi nghĩ rằng câu trả lời của bạn là hữu ích (upvoted nó ngày hôm qua). Tôi nên cung cấp thêm mã. Tôi nghĩ rằng câu trả lời của bạn không bao gồm những gì ngoại lệ thường có nghĩa là. – Ryan

0

Điều kỳ lạ là tôi đã có cùng một problme với trên lớp bên trong của EJB của tôi. Trong khi cố gắng gọi phương thức riêng của cha mẹ hoặc truy cập vào EJB được tiêm, tôi gặp phải một số vấn đề. Tôi có khả năng hiển thị trên hầu hết mọi thứ nhưng cuối cùng là một người dì, mọi thứ trở nên sai.

Cuối cùng, tôi quyết định truy xuất lớp cha mẹ của tôi qua JNDI, do đó tôi có thể gọi phương thức công khai mà không gặp sự cố. Trong khi đó tôi có thể gọi phương pháp riêng tư trên lớp cha mẹ của tôi, tôi vẫn phải nhớ rằng nó sẽ thất bại.

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