我在GlassFish 3.1.1上使用EclipseLink,我正在尝试理解这个异常:
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)
请注意,堆栈跟踪表明在Netbeans生成的AbstractFacade.getEntityManager方法中触发了问题。
知道发生了什么事或者有任何排查提示吗?我猜测,当发生这种情况时,EJB中的事务或缓存状态都很奇怪,因为有时调用edit方法可以正常工作。我从Servlet调用EJB方法。尝试将更改保存到实体时会发生异常。
答案 0 :(得分:30)
您最有可能发生的错误表明您的代码正在尝试调用受保护的方法。 EJB上的无接口视图不允许这样做。您只能调用 public 方法。
普通Java类规则和EJB规则之间存在一些小的不匹配。对于无接口视图,基于原始类类型(通常是其动态子类)创建代理。这意味着对于同一个包中的代码,protected和package私有方法是可见的,就Java编译器而言,允许您的代码调用它们。
但如上所述,EJB规则不允许这样做,因此抛出异常。
您可以通过注入以下bean来轻松复制:
@Stateless
public class FooBean {
public void callMe() {
}
protected void doNotCallMe() {
}
}
将其注入某处(例如同一包中的Servlet)并尝试调用doNotCallMe()
。你会看到同样的例外。致电callMe()
,一切都会好的。
答案 1 :(得分:4)
我想我可能已经找到了解决方案,可能还有第三方软件中的错误。看起来GlassFish 3.1.1 / EJB 3.1 / EclipseLink无法正确处理方法重载。我在我的EJB命名编辑中定义了一个方法,它从父抽象类重载(而不是覆盖)该方法。在EJB的抽象父级中有一个名为edit的方法,它采用泛型类型,然后我在EJB中有一个名为edit的方法,它接受一个List。如果我将方法重命名为其他方法以使其不再重载,那么异常就会消失!
代码:
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) {
...
注意:我注意到如果我将getEntityManager方法设为public而不是protected,我将获得TransactionRequiredException而不是EJBException。
答案 2 :(得分:0)
奇怪的是,我在EJB的内部类中遇到了同样的问题。 在尝试调用父项的私有方法或在注入的EJB上访问时,我遇到了一些问题。 我对大多数事情都有所了解,但最后却出现了问题,事情出了问题。
最后,我决定通过JNDI检索我的父类,因此我可以毫无困难地调用公共方法。与此同时,我可以在父母班上打电话给私人方法,我仍然要记住它会失败。