javax.ejb.EJBException: Незаконный доступ к не-бизнес-методам в режиме без интерфейса

Я использую EclipseLink на GlassFish 3.1.1, и я пытаюсь понять это исключение:

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)

Обратите внимание, что трассировка стека указывает на то, что проблема вызвана в методе AbstractFacade.getEntityManager, созданном Netbeans.

Любая идея, что происходит, или какие-либо советы по устранению неполадок? Я предполагаю, что состояние транзакции или кэширования в EJB странно, когда это происходит, потому что иногда вызов метода редактирования работает нормально. Я вызываю методы EJB из сервлета. Исключение возникает при попытке сохранить изменения в сущности.

Ответ 1

Думаю, я нашел решение и, возможно, ошибку в стороннем программном обеспечении. Похоже, что GlassFish 3.1.1/EJB 3.1/EclipseLink не может правильно обрабатывать методы. У меня есть метод, определенный в моем EJB с именем edit, который перегружает (не переопределяет) метод из родительского абстрактного класса. Существует метод с именем edit в абстрактном родителе EJB, который принимает общий тип, а затем у меня есть метод с именем edit в EJB, который принимает список. Если я переименую метод на что-то еще, чтобы он больше не перегружал, исключение исчезнет!

Код:

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 общедоступным, а не защищенным, я получу исключение TransactionRequiredException вместо исключения EJBException.

Ответ 2

Наиболее вероятная ошибка указывает на то, что ваш код пытается вызвать защищенный метод в любом случае. Это не допускается для представлений без интерфейса в EJB. Вы можете разрешать публичные методы.

Там небольшое несоответствие между нормальными правилами класса Java и правилами EJB. Для представления без интерфейса прокси создается на основе исходного типа класса (обычно это динамический подкласс). Это означает, что защищенные и закрытые частные методы видны для кода в одном пакете, и что касается компилятора Java, ваш код может называть их.

Но, как уже упоминалось, это не допускается правилами EJB, и, таким образом, создается исключение.

Вы можете легко воспроизвести это путем инъекции компонента, как показано ниже:

@Stateless
public class FooBean {

    public void callMe() {
    }

    protected void doNotCallMe() {
    }
}

Внесите это где-нибудь (например, Servlet в том же пакете) и попробуйте вызвать doNotCallMe(). Вы увидите то же исключение. Вызовите callMe() и все будет хорошо.

Ответ 3

Что странно, у меня была такая же проблема с внутренним классом моего EJB. При попытке вызвать частный метод родительского элемента или доступа к вложенному EJB я столкнулся с некоторыми проблемами. У меня была видимость на большинстве вещей, но, в конце концов, рутина, все идет не так.

Наконец, я решил получить мой родительский класс через JNDI, поэтому я мог бы вызвать публичный метод без проблем. Тем временем я мог бы вызвать еще частные методы в классе моих родителей, но я все же должен помнить, что он потерпит неудачу.