【问题标题】:javax.ejb.EJBException: Illegal non-business method access on no-interface viewjavax.ejb.EJBException:非接口视图上的非法非业务方法访问
【发布时间】:2012-02-01 00:36:02
【问题描述】:

我在 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 中的事务或缓存状态很奇怪,因为有时调用编辑方法可以正常工作。我正在从 Servlet 调用 EJB 方法。尝试将更改保存到实体时发生异常。

【问题讨论】:

    标签: servlets jpa ejb eclipselink


    【解决方案1】:

    您得到的错误很可能表明您的代码无论如何都试图调用受保护的方法。对于 EJB 上的无接口视图,这是不允许的。您只能调用 public 方法。

    普通的 Java 类规则和 EJB 规则之间有一点不匹配。对于无接口视图,基于原始类类型(通常是它的动态子类)创建代理。因此,这意味着 protected 和 package 私有方法对于同一包中的代码是可见的,并且就 Java 编译器而言,您的代码可以调用它们。

    但如前所述,这在 EJB 规则中是不允许的,因此会引发异常。

    您可以通过注入如下 bean 来轻松重现此情况:

    @Stateless
    public class FooBean {
    
        public void callMe() {
        }
    
        protected void doNotCallMe() {
        }
    }
    

    在某处注入它(例如,同一个包中的 Servlet)并尝试调用 doNotCallMe()。你会看到同样的异常。拨打callMe(),一切都会好起来的。

    【讨论】:

    • 是的,我知道只有公共方法是 EJB 接口的一部分。但是,我实际上是从 servlet 调用一个名为 edit 的公共方法(我的答案中提供了代码)。某些重载方法似乎存在错误。
    • 好的,很可能就是这样。如果没有执行调用的实际 servlet 代码,这很难说。因此,我的回答并不真正适用于您的问题,尽管我希望在您的标题中搜索例外的人会发现该解释仍然有用。我会赞成你的回答;)
    • 感谢您花时间回答我的问题。我认为您的回答很有帮助(昨天赞成)。我应该提供更多的代码。我认为您的回答确实涵盖了异常通常意味着什么。
    • @ArjanTijms,不仅解决了我的问题,还提供了有关为什么需要公共访问修改器的信息
    【解决方案2】:

    我想我可能找到了解决方案,也可能是第三方软件中的错误。 GlassFish 3.1.1 / EJB 3.1 / EclipseLink 似乎无法正确处理方法重载。我在我的 EJB 中定义了一个名为 edit 的方法,它重载(而不是覆盖)父抽象类的方法。在 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。

    【讨论】:

    • 换句话说:EclipseLink 似乎无法处理 EJB 中的重载继承方法
    • @piotr-nowicki - Bingo,我想你找到了问题的问题报告。谢谢。有趣的是有人否决了这个答案!
    • 我遇到了同样的错误,所以我将它报告给 GlassFish JIRA。等到它修复:-)
    • 似乎引用的 JIRA 已经修复了一段时间,但该版本尚未发布。所以问题是泛型参数的重载没有作为 EJB 方法调用。因此,此方法在非 EJB 上下文中运行(在代理内部,这很奇怪,但这就是错误所在)。从这个上下文中,受保护的方法被调用,它被注册为 EJB 方法,只是没有一个客户端可以调用,因此是异常。我只是对 TransactionRequiredException 有点困惑...
    • 附注> EclipseLink 似乎无法处理 EJB 中的重载继承方法——我认为 EclipseLink 与此无关。这似乎纯粹是关于 GlassFish EJB 实现中的动态代理生成代码。
    【解决方案3】:

    奇怪的是我在 EJB 的内部类中遇到了同样的问题。 在尝试调用父级的私有方法或访问注入的 EJB 时,我遇到了一些问题。 我对大多数事情都有了解,但最后还是一个小问题,事情出了问题。

    最后,我决定通过 JNDI 检索我的父类,这样我就可以毫无问题地调用公共方法。同时我可以在我的父母类上调用私有方法,但我仍然必须记住它会失败。

    【讨论】:

      猜你喜欢
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-24
      • 2019-01-08
      • 2015-03-09
      • 2015-10-03
      • 1970-01-01
      相关资源
      最近更新 更多