Пример cart
представляет корзину покупок в книжном онлайн-магазине и использует сессионный компонент с состоянием для управления операциями с корзиной покупок. Клиент бина может добавить книгу в корзину, удалить книгу или получить содержимое корзины. Для сборки cart
вам понадобится следующий код:
Все сессионные компоненты имеют соответствующий им класс Java. Все Enterprise-бины, которые разрешают удалённый доступ, должны иметь удалённый бизнес-интерфейс. Для удовлетворения потребностей конкретного приложения Enterprise-бину также могут потребоваться некоторые вспомогательные классы. Сессионный компонент CartBean
использует два вспомогательных класса — BookException
и IdVerifier
, которые обсуждаются в разделе Вспомогательные классы.
Исходный код для этого примера находится в каталоге tut-install/examples/ejb/cart/
.
Бизнес-интерфейс
Бизнес-интерфейс Cart
— это интерфейс Java, который определяет все бизнес-методы, реализованные в классе компонента. Если класс бина реализует один интерфейс, этот интерфейс считается бизнес-интерфейсом. Бизнес-интерфейс является локальным интерфейсом, если он не помечен аннотацией javax.ejb.Remote
. Аннотация javax.ejb.Local
в этом случае необязательна.
Класс бина может реализовывать более одного интерфейса. В этом случае бизнес-интерфейсы должны быть либо явно аннотированы @Local
или @Remote
, либо указаны путём аннотирования класса компонента аннотациями @Local
или @Remote
. Однако следующие интерфейсы исключаются при определении того, реализует ли класс бина более одного интерфейса:
Исходный код бизнес-интерфейса Cart
выглядит следующим образом:
package javaeetutorial.cart.ejb;
import cart.util.BookException;
import java.util.List;
import javax.ejb.Remote;
@Remote
public interface Cart {
public void initialize(String person) throws BookException;
public void initialize(String person, String id) throws BookException;
public void addBook(String title);
public void removeBook(String title) throws BookException;
public List<String> getContents();
public void remove();
}
Класс сессионного бина
Класс сессионного компонента для этого примера называется CartBean
. Как и любой сессионный компонент с состоянием, класс CartBean
должен соответствовать следующим требованиям.
Сессионные компоненты с сохранением состояния могут также выполнять следующие действия.
-
Реализовать бизнес-интерфейс — интерфейс Java Реализовать бизнес-интерфейс — хорошая практика.
-
Реализовать любые дополнительные Callback-методы жизненного цикла, аннотированные @PostConstruct
, @PreDestroy
, @PostActivate
и @PrePassivate
.
-
Реализовать любые необязательные бизнес-методы, аннотированные @Remove
.
Исходный код для класса CartBean
выглядит следующим образом:
package javaeetutorial.cart.ejb;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javaeetutorial.cart.util.BookException;
import javaeetutorial.cart.util.IdVerifier;
import javax.ejb.Remove;
import javax.ejb.Stateful;
@Stateful
public class CartBean implements Cart {
String customerId;
String customerName;
List<String> contents;
@Override
public void initialize(String person) throws BookException {
if (person == null) {
throw new BookException("Null person not allowed.");
} else {
customerName = person;
}
customerId = "0";
contents = new ArrayList<>();
}
@Override
public void initialize(String person, String id)
throws BookException {
if (person == null) {
throw new BookException("Null person not allowed.");
} else {
customerName = person;
}
IdVerifier idChecker = new IdVerifier();
if (idChecker.validate(id)) {
customerId = id;
} else {
throw new BookException("Invalid id: " + id);
}
contents = new ArrayList<>();
}
@Override
public void addBook(String title) {
contents.add(title);
}
@Override
public void removeBook(String title) throws BookException {
boolean result = contents.remove(title);
if (result == false) {
throw new BookException("\"" + title + " not in cart.");
}
}
@Override
public List<String> getContents() {
return contents;
}
@Remove
@Override
public void remove() {
contents = null;
}
}
Callback-методы жизненного цикла
Метод в классе бина может быть объявлен как Callback-метод жизненного цикла, добавлением в метод следующих аннотаций.
-
javax.annotation.PostConstruct
: методы, аннотированные с помощью @PostConstruct
, вызываются контейнером для вновь созданных объектов бинов после завершения инъецирования всех зависимостей и до вызова первого бизнес-метода в Enterprise-бине.
-
javax.annotation.PreDestroy
: методы, аннотированные с помощью @PreDestroy
, вызываются после завершения любого аннотированного @Remove
метода и перед удалением Enterprise-бина контейнером.
-
javax.ejb.PostActivate
: методы, помеченные @PostActivate
, вызываются контейнером после того, как контейнер перемещает компонент из вторичного хранилища в активное состояние.
-
javax.ejb.PrePassivate
: методы, аннотированные @PrePassivate
, вызываются контейнером до его пеактивации Enterprise-бином, то есть контейнер временно удаляет бин из среды и сохраняет его во вторичное хранилище.
Callback-методы жизненного цикла должны возвращать void
и не иметь параметров.
Бизнес-методы
Основная цель сессионного компонента — запуск бизнес-задач для клиента. Клиент вызывает бизнес-методы для ссылки на объект, который он получает при инъецирования зависимости или поиске JNDI. С точки зрения клиента, бизнес-методы работают локально, хотя они выполняются удалённо в сессионном компоненте. В следующем фрагменте кода показано, как программа CartClient
вызывает бизнес-методы:
cart.initialize("Duke DeEarl", "123");
...
cart.addBook("Bel Canto");
...
List<String> bookList = cart.getContents();
...
cart.removeBook("Gravity's Rainbow");
Класс CartBean
реализует бизнес-методы в следующем коде:
@Override
public void addBook(String title) {
contents.add(title);
}
@Override
public void removeBook(String title) throws BookException {
boolean result = contents.remove(title);
if (result == false) {
throw new BookException("\"" + title + "not in cart.");
}
}
@Override
public List<String> getContents() {
return contents;
}
Сигнатура бизнес-метода должна соответствовать следующим правилам.
-
Имя метода не должно начинаться с ejb
, чтобы избежать конфликтов с Callback-методами, определёнными архитектурой EJB. Например, вы не можете вызвать бизнес-метод ejbCreate
или ejbActivate
.
-
Модификатор доступа должен быть public
.
-
Если бин разрешает удалённый доступ через удалённый бизнес-интерфейс, аргументы и возвращаемые типы должны быть допустимыми типами для API удалённого вызова методов Java (RMI).
-
Если бин является конечной точкой веб-сервиса JAX-WS, аргументы и возвращаемые типы для аннотированных методов @WebMethod
должны быть допустимыми типами для JAX-WS.
-
Если бин является ресурсом JAX-RS, аргументы и возвращаемые типы для методов ресурса должны быть допустимыми типами для JAX-RS.
-
Модификатор не должен быть static
или final
.
Предложение throws
может содержать исключения, которые вы определяете для своего приложения. Например, метод removeBook
выдает BookException
, если книга отсутствует в корзине.
Чтобы указать на проблему на уровне системы, например невозможность подключения к базе данных, бизнес-метод может выбросить javax.ejb.EJBException
. Контейнер не будет обёртывать (wrap) исключения приложения, такие как BookException
. Поскольку EJBException
является дочерним классом RuntimeException
, вам не нужно добавлять его в throws
бизнес-метода.
Метод @Remove
Бизнес-методы, аннотированные javax.ejb.Remove
в классе сессионного компонента с сохранением состояния, могут вызываться клиентами Enterprise-бина для удаления объекта компонента. Контейнер удалит Enterprise-бин после завершения метода @Remove
независимо от того, завершился он нормально или с ошибкой.
В CartBean
метод remove
помечен аннотацией @Remove
:
@Remove
@Override
public void remove() {
contents = null;
}
Вспомогательные классы
Сессионный компонент CartBean
имеет два вспомогательных класса: BookException
и IdVerifier
. BookException
выбрасывается методом removeBook
, а IdVerifier
валидирует customerId
в одном из методов create
. Вспомогательные классы могут находиться в файле EJB JAR, который содержит класс Enterprise-бина. Или в WAR-файле, если Enterprise-бин упакован в WAR. Или EAR-файле, содержащем файл EJB JAR, WAR-файл или отдельный JAR-файл библиотеки. В cart
вспомогательные классы включены в библиотечный JAR, используемый клиентским приложением, и EJB JAR.
Запуск cart
Теперь вы готовы скомпилировать удалённый интерфейс (Cart.java
), класс Enterprise-бина (CartBean.java
), клиентский класс (CartClient.java
) и вспомогательные классы (BookException.java
и IdVerifier.java
).
Вы можете использовать IDE NetBeans или Maven для сборки, упаковки, развёртывания и запуска приложения cart
.
Здесь рассматриваются следующие темы:
Запуск cart с IDE NetBeans
-
Удостоверьтесь, чтобы GlassFish Server был запущен (см. Запуск и остановка сервера GlassFish).
-
В меню «Файл» выберите «Открыть проект».
-
В диалоговом окне «Открыть проект» перейдите к:
-
Выберите каталог cart
.
-
Установите флажок Открыть требуемые проекты.
-
Нажмите Открыть проект.
-
На вкладке «Проекты» кликните правой кнопкой мыши проект cart
и выберите «Сборка».
Это создаёт и упаковывает приложение в cart.ear
, расположенный в tut-install/examples/ejb/cart/cart-ear/target/
, и развёртывает этот файл EAR в ваш объект GlassFish Server.
Вы увидите выходные данные приложения-клиента cart-app-client
на вкладке Вывод:
...
Retrieving book title from cart: Infinite Jest
Retrieving book title from cart: Bel Canto
Retrieving book title from cart: Kafka on the Shore
Removing "Gravity's Rainbow" from cart.
Caught a BookException: "Gravity's Rainbow" not in cart.
Запуск cart с помощью Maven
-
Удостоверьтесь, чтобы GlassFish Server был запущен (см. Запуск и остановка сервера GlassFish).
-
В окне терминала перейдите в:
tut-install/examples/ejb/cart/
-
Введите следующую команду:
Эта команда компилирует и упаковывает приложение в файл EAR, cart.ear
, расположенный в каталоге target
, и развёртывает EAR в GlassFish Server.
Затем клиентские заглушки извлекаются и запускаются. Это эквивалентно выполнению следующей команды:
appclient -client cart-ear/target/cart-earClient.jar
Клиентский JAR cart-earClient.jar
содержит клиентский класс приложения, вспомогательный класс BookException
и бизнес-интерфейс Cart
.
При запуске клиента контейнер клиентского приложения инъецирует все ссылки на компоненты, объявленные в классе клиентского приложения, в данном случае ссылку на Enterprise-бин Cart
.
В окне терминала вы увидите вывод cart-app-client
:
...
Retrieving book title from cart: Infinite Jest
Retrieving book title from cart: Bel Canto
Retrieving book title from cart: Kafka on the Shore
Removing "Gravity's Rainbow" from cart.
Caught a BookException: "Gravity's Rainbow" not in cart.