javax.ejb.EJBException:在非接口视图上非法的非业务方法访问

时间:2012-01-02 19:01:47

标签: servlets jpa ejb eclipselink

我在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方法。尝试将更改保存到实体时会发生异常。

3 个答案:

答案 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检索我的父类,因此我可以毫无困难地调用公共方法。与此同时,我可以在父母班上打电话给私人方法,我仍然要记住它会失败。