Внедрение EJB управляемого компонента JSF

У меня есть EJB (PersonManager) в модуле Enterprise Application, который вводит другой EJB (Person):

@Stateful
public class PersonManager implements PersonManagerLocal {
    @EJB
    private PersonLocal person;

    @Override
    public void setPersonName(String name) {
        person.setName(name);
    }

    @Override
    public String getPersonName() {
        return person.getName();
    }
}

Я хочу использовать EJB PersonManager в веб-приложении JSF. Я определяю это в файле faces-config.xml:

<managed-bean>
    <managed-bean-name>personManager</managed-bean-name>
    <managed-bean-class>ejb.PersonManager</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

Проблема в том, что инъекции PersonLocal EJB не происходит. Свойство person всегда равно NULL. Что я сделал не так?

Но если я введу PersonManager в управляемый компонент JSF следующим образом:

@ManagedBean
@RequestScoped
public class Index {
    @EJB
    private PersonManagerLocal personManager;
    ....

ОНО РАБОТАЕТ. Мне нужен первый сценарий, пожалуйста, помогите мне :-D


person Forty    schedule 24.12.2011    source источник
comment
Почему бы вам не использовать аннотацию @EJB вместо того, чтобы вручную объявить ее в faces-config.xml ?? Это похоже на попытку вернуться в прошлое, когда аннотации еще не придумали: P   -  person Mr.J4mes    schedule 24.12.2011
comment
Вы правы :-D это чисто теоретически, хотелось бы узнать ответ.   -  person Forty    schedule 25.12.2011
comment
@Forty Так почему это не работает? Ответ мне непонятен.   -  person Koray Tugay    schedule 19.06.2013


Ответы (1)


Вы смешиваете обязанности EJB и управляемых компонентов JSF. faces-config.xml регистрирует только артефакты JSF, такие как управляемые компоненты, но не EJB. Ваша регистрация в faces-config.xml

<managed-bean>
    <managed-bean-name>personManager</managed-bean-name>
    <managed-bean-class>ejb.PersonManager</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

делает в основном то же самое, что и

@ManagedBean
@SessionScoped
public class PersonManager {
    // ...
}

Другими словами, вы регистрируете класс как управляемый компонент JSF, который доступен в представлениях #{personManager}. Это не тот же экземпляр, которым управляет контейнер EJB. Вы можете и не должны использовать faces-config.xml для регистрации EJB. Здесь вы используете аннотации из пакета javax.ejb для, например, @Stateless и @Stateful. Это все, что вам нужно для регистрации EJB.

Фактически, регистрация управляемых компонентов JSF в faces-config.xml - это старый способ JSF 1.x, который в JSF 2.x был заменен новой аннотацией @ManagedBean.


Обновить правильным подходом будет:

Просмотр (файл Facelets):

<h:form>
    <h:inputText value="#{personManager.person.name}" />
    ...
    <h:commandButton value="Save" action="#{personManager.save}" />
    <h:messages />
</h:form>

Контроллер (управляемый компонент JSF):

@ManagedBean
@ViewScoped
public class PersonManager implements Serializable {

    private Person person;

    @EJB
    private PersonService personService;

    @PostConstruct
    public void init() {
        person = new Person();
    }

    public void save() {
        personService.create(person);
        FacesContext.getCurrentInstance().addMessage(null,
            new FacesMessage("Person successfully created, new ID is " + person.getId()));
    }

    // ...
}

Модель (объект JPA):

@Entity
public class Person implements Serializable {

    @Id
    private Long id;

    private String name;

    // ...
}

Сервис (EJB без сохранения состояния):

@Stateless
public class PersonService {

    @PersistenceContext
    private EntityManager em;

    public void create(Person person) {
        em.persist(person);
    }

    // ...
}
person BalusC    schedule 24.12.2011
comment
Спасибо, PersonManager - это бизнес-EJB, поэтому не содержит аннотации @ManagedBean. Он создается механизмом JSF, но не внедряет в него EJB-объект person, согласно сценарию faces-config. - person Forty; 25.12.2011
comment
Я знаю, что такое EJB-компоненты и как их следует использовать. Ты? Что именно сейчас пока неясно? - person BalusC; 25.12.2011
comment
Обратите внимание, что в моем примере ответа отсутствует @Stateful. Это не EJB в этом смысле. Вы пытались использовать EJB как управляемый компонент JSF. Это неправильно. В основном у вас должен быть 1 файл XHTML как представление, 1 управляемый компонент JSF как контроллер, 1 объект как модель и 1 EJB как услуга. В вашем вопросе PersonManager должен быть управляемым bean-компонентом JSF, а не EJB. PersonLocal кажется слишком сущностью, а не EJB. Поэтому я сомневаюсь, что это действительно должен быть EJB. EJB-компоненты предназначены для предоставления таких услуг, как create(), save() и т. Д. - person BalusC; 25.12.2011
comment
См. Также обновленный ответ для примера начала. Обратите внимание, что вам вообще не нужны файлы конфигурации xml. - person BalusC; 25.12.2011
comment
Спасибо :-D Теперь понятно. Я могу просто сделать это, как во втором сценарии (внедрение EJB в управляемый компонент JSF), потому что PersonManager является EJB и не может действовать как управляемый компонент JSF. Я прав? - person Forty; 25.12.2011
comment
@BalusC, если PersonManager в вашем примере оказался @SessionScoped вместо @ViewScoped, нужно ли искать PersonService через InitialContext вместо того, чтобы вводить? - person Patrick Garner; 21.02.2012
comment
Я читал ответ и в то же время восхищался автором, но когда я подошел к концу, мое волнение уменьшилось, увидев внизу ваше имя BalacC. Неудивительно, что только вы можете писать такие красивые ответы. Удачи чувак - person ehsun7b; 20.04.2013
comment
@BalusC: Могу я спросить пример, который вы написали в качестве ответа, можно ли поместить все (представление, контроллер и службу) в один веб-проект maven? Упакован как файл * .war? - person DaeYoung; 10.08.2018
comment
@BalusC Разве нам не нужно создавать интерфейс для EJB ...? например: в приведенном выше случае: @Stateless public class PersonService implements PersonServiceInterface{ ... } и мы вводим PersonServiceInterface внутри ManagedBean ..? - person paawan; 27.10.2020
comment
@ Paawan12: нет. В этом больше нет необходимости, поскольку EJB 3.0 был выпущен более десяти лет назад. - person BalusC; 27.10.2020
comment
@BalusC Итак, это хороший шаблон проектирования - напрямую внедрять EJB вместо интерфейса? - person paawan; 28.10.2020
comment
@ Paawan12: Если у вас только один имп, то да, это вполне приемлемо. - person BalusC; 28.10.2020