··public void saveAccount() {
····account = new Account();
····// Задает свойства учетной записи
··}
··public void createCustomer() {
····Customer customer = new Customer();
····customer.setLogin(login);
····customer.setAccount(account);
····customerService.createCustomer(customer);
····conversation.end();
··}
}
В листинге 2.21 компонент CustomerCreationWizard сопровождается аннотацией @ConversationScoped. Затем он внедряет CustomerService для создания Customer, но что более важно, он внедряет Conversation. Этот интерфейс позволяет программно управлять жизненным циклом области видимости диалога. Обратите внимание, что при вызове метода saveLogin начинается диалог (conversation.begin()). Теперь он начинается и используется в течение всего времени работы мастера. Как только вызывается последний шаг мастера, вызывается метод createCustomer и диалог заканчивается (conversation.end()). Таблица 2.3 предлагает вам краткое обозрение API Conversation.
Метод | Описание |
---|---|
void begin() | Помечает текущий кратковременный диалог как длительный |
void begin(String id) | Помечает текущий кратковременный диалог как длительный, со специальным идентификатором |
void end() | Помечает текущий длительный диалог как кратковременный |
String getId() | Получает идентификатор текущего длительного диалога |
long getTimeout() | Получает время задержки текущего диалога |
void setTimeout(long millis) | Задает время задержки текущего диалога |
boolean isTransient() | Определяет, помечен ли диалог как кратковременный или длительный |
Компоненты в языке выражений
Одна из ключевых возможностей CDI состоит в том, что он связывает уровень транзакций и веб-уровень. Но, как вы уже могли видеть, одна из первоочередных характеристик CDI заключается в том, что внедрение зависимостей (DI) полностью типобезопасно и не зависит от символьных имен. В Java-коде это не вызывает проблем, поскольку компоненты не будут разрешимы без символьных имен за пределами Java. В частности, это касается EL-выражений на страницах JSF.
По умолчанию компонентам CDI не присваивается имя и они неразрешимы с помощью EL-связывания. Чтобы можно было присвоить компоненту имя, он должен быть аннотирован встроенным квалификатором @javax.inject.Named, как показано в листинге 2.22.
@Named
public class BookService {
··private String title, description;
··private Float price;
··private Book book;
··@Inject @ThirteenDigits
··private NumberGenerator numberGenerator;
··public String createBook() {
····book = new Book(title, price, description);
····book.setIsbn(numberGenerator.generateNumber());
····return "customer.xhtml";
··}
}
Квалификатор @Named позволяет получить доступ к компоненту BookService через его имя (им по умолчанию является имя класса в «верблюжьем регистре» (CamelCase) с первой строчной буквой). Следующий отрывок кода показывает кнопку JSF, вызывающую метод createBook:
Вы также можете переопределить имя компонента, добавив другое имя к квалификатору.
@Named("myService")
public class BookService {…}
Затем вы можете использовать это новое имя на странице JSF.
Перехватчики
Перехватчики позволяют добавлять к вашим компонентам сквозную функциональность. Как показано на рис. 2.2, когда клиент вызывает метод на управляемом компоненте (а значит, и на компоненте CDI, EJB либо веб-службе RESTful и т. д.), контейнер может перехватить вызов и обработать бизнес-логику перед тем, как будет вызван метод компонента. Перехватчики делятся на четыре типа:
•