Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javax.ejb.EJBException: Illegal non-business method access on no-interface view

I'm using EclipseLink on GlassFish 3.1.1 and I'm trying to understand this exception:

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)

Notice that the stack trace indicates that the problem is triggered in the Netbeans generated AbstractFacade.getEntityManager method.

Any idea what the heck is going on or any tips to troubleshoot? I'm guessing that either the transaction or caching state in the EJB is weird when this happens because sometimes calling the edit method works fine. I'm calling the EJB methods from a Servlet. The exception occurs when trying to save changes to an entity.

like image 334
Ryan Avatar asked Jan 02 '12 19:01

Ryan


2 Answers

The error you get most likely indicates that your code is trying to call the protected method anyway. This is not allowed for no-interface views on an EJB. You are only allowed to call public methods.

There's a small mismatch here between the normal Java class rules and the EJB rules. For a no-interface view, a proxy is created based on the original class type (typically a dynamic sub-class of it). This thus means that protected and package private methods are visible for code in the same package, and as far as the Java compiler is concerned, your code is allowed to call those.

But as mentioned, this is not allowed by the EJB rules, and thus an exception is thrown.

You can reproduce this easily by injection a bean like the following:

@Stateless
public class FooBean {

    public void callMe() {
    }

    protected void doNotCallMe() {
    }
}

Inject this somewhere (e.g. Servlet in same package) and try to call doNotCallMe(). You'll see the same exception. Call callMe() and everything will be fine.

like image 67
Arjan Tijms Avatar answered Nov 13 '22 09:11

Arjan Tijms


I think I may have found a solution and possibly a bug in third party software. It seems like GlassFish 3.1.1 / EJB 3.1 / EclipseLink can't handle method overloading correctly. I've got a method defined in my EJB named edit that overloads (not overrides) the method from the parent abstract class. There is a method named edit in the abstract parent of the EJB that takes a generic type and then I've got a method named edit in the EJB which takes a List. If I rename the method to something else so that it is no longer overloading then the exception goes away!

Code:

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

and

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

Note: I noticed if I make the getEntityManager method public instead of protected I'll get a TransactionRequiredException instead of an EJBException.

like image 4
Ryan Avatar answered Nov 13 '22 08:11

Ryan