Введение
Java API для модульной разработки корпоративного программного обеспечения
Jakarta Enterprise Beans (EJB; ранее Enterprise JavaBeans) — один из нескольких Java API для модульной разработки корпоративного программного обеспечения. EJB — это программный компонент серверной части, инкапсулирующий бизнес-логику приложения. Веб-контейнер EJB предоставляет среду выполнения для программных компонентов, связанных с веб-приложениями, включая компьютерную безопасность, управление жизненным циклом Java-сервлетов, обработку транзакций и другие веб-сервисы. Спецификация EJB является подмножеством спецификации Java EE.
Спецификация
Спецификация EJB была первоначально разработана в 1997 году компанией IBM, а затем принята Sun Microsystems (EJB 1.0 и 1.1) в 1999 году и усовершенствована в рамках Java Community Process как JSR 19 (EJB 2.0), JSR 153 (EJB 2.1), JSR 220 (EJB 3.0), JSR 318 (EJB 3.1) и JSR 345 (EJB 3.2). Спецификация EJB предоставляет стандартный способ реализации серверной стороны (также называемой "бэкендом") "бизнес-логики", типичной для корпоративных приложений (в отличие от "фронтенда" – программного обеспечения пользовательского интерфейса). Такие приложения решают одни и те же задачи, и решения этих задач часто повторно реализуются программистами. Jakarta Enterprise Beans призван решать такие общие задачи, как постоянное хранение данных, целостность транзакций и безопасность, в стандартизированном виде, позволяя программистам сосредоточиться на конкретных аспектах корпоративного программного обеспечения.
История
Предприятия обнаружили, что использование EJB для инкапсуляции бизнес-логики приводило к снижению производительности. Это было связано с тем, что первоначальная спецификация допускала только удаленный вызов методов через CORBA (и, опционально, другие протоколы), хотя подавляющее большинство бизнес-приложений на самом деле не требовали такой функциональности распределенных вычислений. Спецификация EJB 2.0 решила эту проблему, добавив концепцию локальных интерфейсов, которые можно было вызывать напрямую без снижения производительности приложениями, не распределенными по нескольким серверам. Спецификация EJB 3.0 (JSR 220) стала отходом от своих предшественников, следуя новой легковесной парадигме. EJB 3.0 демонстрирует влияние Spring в использовании простых Java-объектов и поддержку внедрения зависимостей для упрощения конфигурации и интеграции разнородных систем. EJB 3.0, наряду с другими версиями EJB, может быть интегрирован с MuleSoft v4 с использованием сертифицированного MuleSoft PlektonLabs EJB Connector. Гавин Кинг, создатель Hibernate, принимал участие в разработке EJB 3.0 и является активным сторонником этой технологии. Многие функции, изначально реализованные в Hibernate, были включены в Java Persistence API, которая заменила entity beans в EJB 3.0. Спецификация EJB 3.0 в значительной степени опирается на использование аннотаций (функция, добавленная в язык Java с выпуском версии 5.0) и принцип "соглашение важнее конфигурации", чтобы обеспечить менее многословный стиль кодирования. Соответственно, на практике EJB 3.0 значительно легче и представляет собой практически новый API, мало похожий на предыдущие спецификации EJB.
Исполнение
EJB развертываются в контейнере EJB, как правило, в сервере приложений. Спецификация описывает взаимодействие EJB с контейнером и взаимодействие клиентского кода с комбинацией контейнера и EJB. Классы EJB, используемые приложениями, включены в пакет. (Этот пакет является интерфейсом поставщика услуг, используемым только реализациями контейнера EJB.) Клиенты EJB не создают экземпляры этих компонентов напрямую с помощью оператора `new` в Java, а должны получить ссылку через контейнер EJB. Эта ссылка обычно не является ссылкой на сам компонент реализации, а на прокси, который динамически реализует либо локальный, либо удаленный бизнес-интерфейс, запрошенный клиентом, либо подтип фактического компонента. Затем прокси можно непосредственно привести к интерфейсу или компоненту соответственно. Клиент имеет "представление" (view) на EJB, а локальный интерфейс, удаленный интерфейс и сам подтип компонента соответственно соответствуют локальному представлению, удаленному представлению и представлению без интерфейса. Этот прокси необходим для того, чтобы контейнер EJB имел возможность прозрачно предоставлять сквозные (AOP-подобные) сервисы для компонента, такие как транзакции, безопасность, перехваты, внедрения зависимостей и удаленный вызов. Например, клиент вызывает метод у прокси, который сначала запускает транзакцию с помощью контейнера EJB, а затем вызывает фактический метод компонента. Когда метод компонента возвращает управление, прокси завершает транзакцию (то есть фиксирует ее или откатывает) и передает управление обратно клиенту. Контейнер EJB отвечает за обеспечение того, чтобы клиентский код имел достаточные права доступа к EJB. Аспекты безопасности могут быть декларативно применены к EJB с помощью аннотаций.
Сделки
Контейнеры EJB должны поддерживать как управляемые контейнером ACID-транзакции, так и управляемые bean-транзакции. Управляемые контейнером транзакции (CMT) по умолчанию активны для вызовов сеансовых компонентов. То есть, не требуется никакой явной конфигурации. Это поведение может быть декларативно настроено компонентом с помощью аннотаций, и при необходимости такая конфигурация может быть позже переопределена в дескрипторе развертывания. Настройка включает отключение транзакций для всего компонента или конкретных методов, или запрос альтернативных стратегий распространения транзакций и начала или присоединения к транзакции. Эти стратегии в основном определяют, что должно произойти, если транзакция уже активна или не активна в момент вызова компонента. Поддерживаются следующие варианты:
+ Declarative Transactions Management Types Type Explanation MANDATORY If the client has not started a transaction, an exception is thrown. Otherwise the client's transaction is used. REQUIRED If the client has started a transaction, it is used. Otherwise a new transaction is started. (this is the default when no explicit type has been specified) REQUIRES NEW If the client has started a transaction, it is suspended. A new transaction is always started. SUPPORTS If the client has started a transaction, it is used. Otherwise, no transaction is used. NOT SUPPORTED If the client has started a transaction, it is suspended. No new transaction is started. NEVER If the client has started a transaction, an exception is thrown. No new transaction is started. Alternatively, the bean can also declare via an annotation that it wants to handle transactions programmatically via the JTA API. This mode of operation is called Bean Managed Transactions (BMT), since the bean itself handles the transaction instead of the container.
+ Типы декларативного управления транзакциями
+ Declarative Transactions Management Types Type Explanation MANDATORY If the client has not started a transaction, an exception is thrown. Otherwise the client's transaction is used. REQUIRED If the client has started a transaction, it is used. Otherwise a new transaction is started. (this is the default when no explicit type has been specified) REQUIRES NEW If the client has started a transaction, it is suspended. A new transaction is always started. SUPPORTS If the client has started a transaction, it is used. Otherwise, no transaction is used. NOT SUPPORTED If the client has started a transaction, it is suspended. No new transaction is started. NEVER If the client has started a transaction, an exception is thrown. No new transaction is started. Alternatively, the bean can also declare via an annotation that it wants to handle transactions programmatically via the JTA API. This mode of operation is called Bean Managed Transactions (BMT), since the bean itself handles the transaction instead of the container.
| Тип | Описание |
|--------------|------------------------------------------------------------------------------------------------------|
| MANDATORY | Если клиент не начал транзакцию, выбрасывается исключение. В противном случае используется транзакция клиента. |
| REQUIRED | Если клиент начал транзакцию, она используется. В противном случае начинается новая транзакция. (Это значение по умолчанию, если тип не указан явно) |
| REQUIRES_NEW | Если клиент начал транзакцию, она приостанавливается. Всегда начинается новая транзакция. |
| SUPPORTS | Если клиент начал транзакцию, она используется. В противном случае транзакция не используется. |
| NOT_SUPPORTED| Если клиент начал транзакцию, она приостанавливается. Новая транзакция не начинается. |
| NEVER | Если клиент начал транзакцию, выбрасывается исключение. Новая транзакция не начинается. |
+ Declarative Transactions Management Types Type Explanation MANDATORY If the client has not started a transaction, an exception is thrown. Otherwise the client's transaction is used. REQUIRED If the client has started a transaction, it is used. Otherwise a new transaction is started. (this is the default when no explicit type has been specified) REQUIRES NEW If the client has started a transaction, it is suspended. A new transaction is always started. SUPPORTS If the client has started a transaction, it is used. Otherwise, no transaction is used. NOT SUPPORTED If the client has started a transaction, it is suspended. No new transaction is started. NEVER If the client has started a transaction, an exception is thrown. No new transaction is started. Alternatively, the bean can also declare via an annotation that it wants to handle transactions programmatically via the JTA API. This mode of operation is called Bean Managed Transactions (BMT), since the bean itself handles the transaction instead of the container.
Кроме того, компонент может также указать через аннотацию, что он хочет обрабатывать транзакции программно с помощью JTA API. Этот режим работы называется Bean Managed Transactions (BMT), поскольку сам компонент управляет транзакцией, а не контейнер.
+ Declarative Transactions Management Types Type Explanation MANDATORY If the client has not started a transaction, an exception is thrown. Otherwise the client's transaction is used. REQUIRED If the client has started a transaction, it is used. Otherwise a new transaction is started. (this is the default when no explicit type has been specified) REQUIRES NEW If the client has started a transaction, it is suspended. A new transaction is always started. SUPPORTS If the client has started a transaction, it is used. Otherwise, no transaction is used. NOT SUPPORTED If the client has started a transaction, it is suspended. No new transaction is started. NEVER If the client has started a transaction, an exception is thrown. No new transaction is started. Alternatively, the bean can also declare via an annotation that it wants to handle transactions programmatically via the JTA API. This mode of operation is called Bean Managed Transactions (BMT), since the bean itself handles the transaction instead of the container.
Удаленное/распределенное исполнение
Для связи с клиентом, написанным на языке программирования Java, сеансовый компонент (bean) может предоставлять удаленный интерфейс через интерфейс, аннотированный @Remote. Это позволяет вызывать эти компоненты из клиентов в других JVM, которые могут выполняться на других системах (с точки зрения контейнера EJB, любой код в другой JVM считается удаленным). Безъядерные (stateless) и синглтонные сеансовые компоненты также могут предоставлять "клиентский интерфейс веб-сервиса" для удаленной связи через WSDL и SOAP или обычный XML, в соответствии со спецификациями JAX-RPC и JAX-WS. Однако поддержка JAX-RPC планируется к удалению в будущем. Для поддержки JAX-WS сеансовый компонент аннотируется @WebService, а методы, предназначенные для удаленного доступа, – @WebMethod. Хотя спецификация EJB никак не предусматривает предоставление доступа как к RESTful веб-сервисам и не имеет для этого прямой поддержки, спецификация JAX-RS явно поддерживает EJB. В соответствии со спецификацией JAX-RS, безъядерные и синглтонные сеансовые компоненты могут быть объявлены как корневые ресурсы с помощью аннотации @Path, а бизнес-методы EJB могут быть сопоставлены с методами ресурсов с помощью аннотаций @GET, @PUT, @POST и @DELETE. Однако это не считается "клиентским интерфейсом веб-сервиса", который используется исключительно для JAX-WS и JAX-RPC. Связь через веб-сервисы обычно используется для клиентов, написанных не на языке программирования Java, но также удобна для Java-клиентов, которым сложно получить доступ к серверу EJB через брандмауэр. Кроме того, Java-клиенты могут использовать связь на основе веб-сервисов для обхода сложных и нечетко определенных требований к так называемым "клиентским библиотекам" – набору JAR-файлов, которые Java-клиент должен иметь в classpath для связи с удаленным сервером EJB. Эти клиентские библиотеки потенциально могут конфликтовать с библиотеками, которые уже установлены у клиента (например, если сам клиент также является полноценным сервером Java EE), и разрешение такого конфликта считается очень сложным или невозможным.
Интерфейсы для домашних пользователей и требуемый бизнес-интерфейс
С EJB 2.1 и более ранних версий каждый EJB требовал наличия класса реализации на Java и двух интерфейсов Java. Контейнер EJB создавал экземпляры класса реализации Java для предоставления функциональности EJB. Клиентский код EJB использовал интерфейсы Java.