Инъекция CDI EJB приводит к исключению NullPointerException - PullRequest
9 голосов
/ 17 ноября 2011

Я новичок в Java EE 6 и CDI. Я прочитал пару уроков и документацию по сварке. Однако что-то, что должно работать из моего понимания, не очень, поэтому мне нужна помощь.

У меня следующая ситуация. Я создал приложение Java EE 6 с NetBeans 7.0.1 с использованием архетипа maven, поставляемого с IDE, и развернул на GlassFish 3.1, также поставляемом с IDE.

Файл beans.xml находится в каталоге META-INF моего EJB-файла.

Я создал класс, который работает как класс производителя для моих EJB-артефактов (и EntityManager)

@Stateless
public class EjbArtifactProducer {

    @PersistenceContext(unitName = "trackProfiler-PU")    
    private EntityManager em;

    @EJB
    private UserFacadeLocal userFacade;

    @EJB
    private AuthServiceLocal authService;

    @EJB
    private NewsEntryFacadeLocal newsEntryFacade;

    @EJB
    private RoleFacadeLocal roleFacade;

    @EJB
    private TrackCommentFacade trackCommentFacade;

    @EJB
    private TrackFacade trackFacade;

    @EJB
    private TrackTypeFacade trackTypeFacade;

    @EJB
    private WaypointFacadeLocal waypointFacade;

    @Produces
    public AuthServiceLocal getAuthService() {
    return authService;
    }

    @Produces
    public EntityManager getEm() {
    return em;
    }

    @Produces
    public NewsEntryFacadeLocal getNewsEntryFacade() {
    return newsEntryFacade;
    }

    @Produces
    public RoleFacadeLocal getRoleFacade() {
    return roleFacade;
    }

    @Produces
    public TrackCommentFacade getTrackCommentFacade() {
    return trackCommentFacade;
    }

    @Produces
    public TrackFacade getTrackFacade() {
    return trackFacade;
    }

    @Produces
    public TrackTypeFacade getTrackTypeFacade() {
    return trackTypeFacade;
    }

    @Produces
    public UserFacadeLocal getUserFacade() {
    return userFacade;
    }

    @Produces
    public WaypointFacadeLocal getWaypointFacade() {
    return waypointFacade;
    }    

}

Я пытался применить аннотацию @Produces непосредственно к полям и методам on, как показано выше.

Однако следующее ничего не вставляет в другой EJB

@Inject
private NewsEntryFacadeLocal newsEntryFacade;

Это делается в сеансе без сохранения состояния, но когда я пытаюсь получить доступ к newsEntryFacade любым из моих бизнес-методов, генерируется исключение NullPointerException. Очевидно, что инъекций не происходит, или мои продюсеры дают нулевые ссылки.

Я что-то упустил? Или должен работать в соответствии с CDI / Weld?

Странно, но, кажется, работает так, когда я пытаюсь @Inject EJB-компонентов в часть веб-приложения (однако мне нужно было дополнительный класс производителя в моем .war для этого, вот так быть?).

РЕДАКТИРОВАТЬ: проект работает с сборкой муравей (генерируется NetBeans). Есть ли проблемы с архетипом Maven, предоставленным NetBeans? Кажется, что с архетипом Maven есть некоторые проблемы с внедрением CDI между модулями war и ejb. Я обнаружил, что если бы у меня были отдельные производители в модуле web и ejb, Glassfish генерирует ошибку развертывания, утверждая, что есть две неразличимые реализации интерфейса. Но когда я удаляю производителя из веб-модуля, Weld жалуется, что EJB, который я хочу внедрить в мои bean-компоненты в веб-модуле, не может быть разрешен. Также с помощью сборки Ant EJB могут быть @Injected без производителя, в то время как для сборки maven нужны поля производителя в классе. Я не могу объяснить, как это могло произойти. Ведь окончательное развертывание должно быть более или менее равным, не так ли?

Ответы [ 5 ]

1 голос
/ 20 сентября 2012

Джордан Денисон прав.Вы пытаетесь @Inject и EJB, но вы используете @EJB для EJB.Ваш EJB-класс, вероятно, помечен @Stateless или чем-то еще.@Inject следует использовать для сессионных компонентов, помеченных @Named и некоторой областью видимости.

1 голос
/ 22 июня 2012

Если вы хотите использовать @Inject, аннотируйте его как @Named @ApplicationScoped, в противном случае используйте @EJB при введении синглтона.

0 голосов
/ 25 января 2015

вы смешиваете две разные концепции ... используйте CDI в качестве основы для JSF. (CDI в веб-контейнере) и использование EJB и JPA на бизнес-уровне ... уровень CDI может внедрить EJB для вызова определенного бизнес-метода.

в этом случае у вас есть четкое разделение по проблемам.

Кстати: вам вообще не нужны интерфейсы EJB! используйте только интерфейсы, если у вас есть требования для связи с удаленным ... (@Remote). с помощью аннотации @LocalBean вы можете непосредственно внедрить сам EJB ..

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

Маскировка:

Веб-браузер -> JSF Facelet -> Компонент поддержки CDI -> Службы EJB -> EntityManager

0 голосов
/ 18 июля 2012

Трудно сказать, что происходит не так, но у нас определенно не получилось использовать CDI между границами загрузчика классов. Например, если ваше приложение упаковано в файл ear, ваши ejbs будут в jar-файле, а ваше web-приложение - в вашем war-файле. В этом случае вы не можете использовать CDI для внедрения ваших ejbs в ваш веб-слой. Проблема в том, что банку и войну загружают разные классовые грузчики. Возможно, новые реализации CDI ведут себя по-разному, но по крайней мере JBoss 6 и Glassfish имели эту проблему.

0 голосов
/ 10 апреля 2012

Попробуйте поместить @Named в EjbArtifactProducer. Кроме того, если продукт является таким простым, я думаю, что лучше удалить его тоже (в противном случае вам нужно сделать еще одно изменение).

...