Примечание

Одиночные EJB-компоненты не поддерживают кластер. Кластер — это группа контейнеров, которые тесно работают друг с другом (совместно используют одни и те же ресурсы, EJB-компоненты и т. д.). Таким образом, в ситуациях, когда несколько распределенных контейнеров будут образовывать кластер, функционируя на нескольких машинах, каждый контейнер будет располагать своим экземпляром одиночного EJB-компонента.

Чтобы превратить приведенный в листинге 7.9 код одиночного Java-класса в код одиночного сессионного EJB-компонента (листинг 7.10), не потребуется много усилий. Фактически вам придется лишь снабдить класс аннотацией @Singleton, при этом не придется беспокоиться о закрытом конструкторе или статическом методе getInstance(). Контейнер убедится в том, что вы создали только один экземпляр. Аннотация @javax.ejb.Singleton обладает тем же самым API-интерфейсом, что и аннотация @Stateless, описанная ранее в листинге 7.7.

Листинг 7.10. Одиночный сессионный EJB-компонент

@Singleton

public class CacheEJB {

··private Map cache = new HashMap<>();

··public void addToCache(Long id, Object object) {

····if (!cache.containsKey(id))

······cache.put(id, object);

··}

··public void removeFromCache(Long id) {

····if (cache.containsKey(id))

······cache.remove(id);

··}

··public Object getFromCache(Long id) {

····if (cache.containsKey(id))

······return cache.get(id);

····else

······return null;

··}

}

Как вы можете видеть, разработка сессионных EJB-компонентов без сохранения состояния, с сохранением состояния и одиночных очень легка: вам потребуется лишь одна аннотация. Вместе с тем об одиночных EJB-компонентах можно сказать еще немного. Можно инициализировать их при запуске, объединять в цепочку и настраивать их конкурентный доступ.

<p>Инициализация при запуске</p>

Когда клиентскому классу требуется доступ к методу в одиночном сессионном EJB-компоненте, контейнер обеспечивает либо создание его экземпляра, либо использование того, что уже имеется в этом контейнере. Однако инициализация одиночного EJB-компонента иногда может отнимать много времени. Представим, что CacheEJB (приведенному в листинге 7.10) необходим доступ к базе данных для загрузки в свой кэш тысяч объектов. Первый вызов EJB-компонента окажется затратным, и первому клиенту придется ожидать завершения инициализации.

Чтобы избежать такой задержки, вы можете дать указание контейнеру инициализировать одиночный EJB-компонент при запуске. Если снабдить класс EJB-компонента аннотацией @Startup, то контейнер инициализирует его во время запуска приложения, а не в тот момент, когда клиент вызовет его. В приведенном далее коде показано, как следует использовать эту аннотацию:

@Singleton

@Startup

public class CacheEJB {…}

Примечание

В Java EE 7 экспертная группа попыталась изъять аннотацию @Startup из спецификации EJB, чтобы она могла быть использована с любым управляемым MBean-компонентом или сервлетом. Сделать это не получилось, однако теоретически это окажется возможным в Java EE 8.

<p>Объединение одиночных EJB-компонентов в цепочку</p>

В некоторых случаях, когда у вас есть несколько одиночных EJB-компонентов, может быть важно явно задать порядок инициализации. Представим, что CacheEJB необходимо сохранить данные, которые исходят от другого одиночного EJB-компонента (скажем, CountryCodeEJB, который возвращает ISO-коды стран). Тогда CountryCodeEJB потребуется инициализировать раньше CacheEJB. Между несколькими одиночными EJB-компонентами могут существовать зависимости, которые выражаются аннотацией @javax.ejb.DependsOn. Использование этой аннотации демонстрируется в приведенном далее примере:

@Singleton

public class CountryCodeEJB {…}

@DependsOn("CountryCodeEJB")

@Singleton

Перейти на страницу:

Похожие книги