1. Обзор
В этой статье мы собираемся обсудить, как начать разработку Enterprise JavaBean (EJB).
Enterprise JavaBeans используются для разработки масштабируемых распределенных серверных компонентов и обычно инкапсулируют бизнес-логику приложения.
Мы будем использовать WildFly 10.1.0
в качестве предпочтительного серверного решения, однако вы можете использовать любой сервер приложений Java Enterprise по своему выбору.
2. Настройка
Начнем с обсуждения зависимостей Maven, необходимых для разработки EJB 3.2, и того, как настроить сервер приложений WildFly с помощью подключаемого модуля Maven Cargo или вручную.
2.1. Зависимость от Maven
Чтобы использовать EJB 3.2 , убедитесь, что вы добавили последнюю версию в раздел зависимостей вашего файла
pom.xml
:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
Вы найдете последнюю зависимость в репозитории Maven . Эта зависимость гарантирует, что все API Java EE 7 будут доступны во время компиляции. Предоставленная область гарантирует, что после развертывания зависимость будет предоставлена контейнером, в котором она была развернута .
2.2. Настройка WildFly с помощью Maven Cargo
Давайте поговорим о том, как использовать плагин Maven Cargo для настройки сервера.
Вот код профиля Maven, который инициализирует сервер WildFly:
<profile>
<id>wildfly-standalone</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>${cargo-maven2-plugin.version</version>
<configuration>
<container>
<containerId>wildfly10x</containerId>
<zipUrlInstaller>
<url>
http://download.jboss.org/
wildfly/10.1.0.Final/
wildfly-10.1.0.Final.zip
</url>
</zipUrlInstaller>
</container>
<configuration>
<properties>
<cargo.hostname>127.0.0.0</cargo.hostname>
<cargo.jboss.management-http.port>
9990
</cargo.jboss.management-http.port>
<cargo.servlet.users>
testUser:admin1234!
</cargo.servlet.users>
</properties>
</configuration>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Мы используем плагин для загрузки ZIP-файла WildFly 10.1
непосредственно с веб-сайта WildFly. Который затем настраивается, удостоверяясь, что имя хоста
127.0.0.1
и установка порта 9990.
Затем мы создаем тестового пользователя, используя свойство cargo.servlet.users
, с идентификатором пользователя testUser
и паролем admin1234!.
Теперь, когда настройка плагина завершена, мы можем вызвать цель Maven и загрузить, установить, запустить сервер и развернуть приложение.
Для этого перейдите в каталог ejb-remote
и выполните следующую команду:
mvn clean package cargo:run
Когда вы запускаете эту команду в первый раз, она загружает zip-файл WildFly 10.1, извлекает его и выполняет установку, а затем запускает ее. Это также добавит тестового пользователя, о котором говорилось выше. Любые дальнейшие выполнения не будут снова загружать zip-файл.
2.3. Ручная настройка WildFly
Чтобы настроить WildFly вручную, вы должны сами загрузить установочный zip-файл с веб-сайта wildfly.org . Следующие шаги представляют собой высокоуровневое представление процесса установки сервера WildFly:
После загрузки и разархивирования содержимого файла в место, где вы хотите установить сервер, настройте следующие переменные среды:
JBOSS_HOME=/Users/$USER/../wildfly.x.x.Final
JAVA_HOME=`/usr/libexec/java_home -v 1.8`
Затем в каталоге bin
запустите ./standalone.sh
для операционных систем на базе Linux или ./standalone.bat
для Windows.
После этого вам нужно будет добавить пользователя. Этот пользователь будет использоваться для подключения к удаленному компоненту EJB. Чтобы узнать, как добавить пользователя, обратитесь к документации по добавлению пользователя .
Подробные инструкции по настройке см. в документации по началу работы WildFly .
POM проекта был настроен для работы с плагином Cargo и ручной конфигурацией сервера путем установки двух профилей. По умолчанию выбран плагин Cargo. Однако для развертывания приложения на уже установленном, настроенном и работающем сервере Wildfly выполните следующую команду в каталоге ejb-remote
:
mvn clean install wildfly:deploy -Pwildfly-runtime
3. Удаленный
против локального
Бизнес-интерфейс для компонента может быть как локальным
, так и удаленным.
Доступ к аннотированному @Local
bean - компоненту возможен только в том случае, если он находится в том же приложении, что и bean-компонент, выполняющий вызов, т. е. если они находятся в одном и том же .ear
или .war
.
Доступ к аннотированному @Remote
bean - компоненту можно получить из другого приложения, т. е. из приложения, находящегося на другом JVM
или сервере приложений.
Есть несколько важных моментов, которые следует учитывать при разработке решения, включающего EJB:
- java.io.Serializable ,
java.io.Externalizable
и интерфейсы, определенныепакетом
javax.ejb
, всегда исключаются, когда bean-компонент объявлен с@Local
или@Remote
- Если класс компонента является удаленным, то все реализованные интерфейсы должны быть удаленными.
- Если класс bean-компонента не содержит аннотации или указана аннотация
@Local
, то все реализованные интерфейсы считаются локальными . - Любой интерфейс, явно определенный для bean-компонента, который не содержит интерфейса, должен быть объявлен как
@Local.
- Версия EJB 3.2, как правило, обеспечивает большую степень детализации для ситуаций, когда локальные и удаленные интерфейсы должны быть явно определены.
4. Создание удаленного
EJB
Давайте сначала создадим интерфейс бина и назовем его HelloWorld:
@Remote
public interface HelloWorld {
String getHelloWorld();
}
Теперь мы реализуем вышеуказанный интерфейс и назовем конкретную реализацию HelloWorldBean:
@Stateless(name = "HelloWorld")
public class HelloWorldBean implements HelloWorld {
@Resource
private SessionContext context;
@Override
public String getHelloWorld() {
return "Welcome to EJB Tutorial!";
}
}
Обратите внимание на аннотацию @Stateless
в объявлении класса. Это означает, что этот компонент является сеансовым компонентом без сохранения состояния. Этот тип bean-компонента не имеет никакого связанного состояния клиента , но может сохранять свое состояние экземпляра и обычно используется для выполнения независимых операций.
Аннотация @Resource
вводит контекст сеанса в удаленный компонент.
Интерфейс SessionContext
обеспечивает доступ к контексту сеанса времени выполнения, который контейнер предоставляет для экземпляра сеансового компонента . Затем контейнер передает интерфейс SessionContext
экземпляру после создания экземпляра. Контекст сеанса остается связанным с этим экземпляром на протяжении всего времени его существования.
Контейнер EJB обычно создает пул объектов bean-компонентов без сохранения состояния и использует эти объекты для обработки клиентских запросов. В результате этого механизма пула не гарантируется сохранение значений переменных экземпляра при вызовах методов поиска.
5. Удаленная настройка
В этом разделе мы обсудим, как настроить Maven для сборки и запуска приложения на сервере.
Давайте рассмотрим плагины один за другим.
5.1. EJB-плагин
Приведенный ниже подключаемый модуль EJB используется для упаковки модуля EJB. Мы указали версию EJB как 3.2.
Следующая конфигурация подключаемого модуля используется для настройки целевого JAR-файла для bean-компонента:
<plugin>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.4</version>
<configuration>
<ejbVersion>3.2</ejbVersion>
</configuration>
</plugin>
5.2. Разверните удаленный EJB
Чтобы развернуть компонент на сервере WildFly, убедитесь, что сервер запущен и работает.
Затем, чтобы выполнить удаленную настройку, нам нужно будет запустить следующие команды Maven для файла pom в проекте ejb-remote
:
mvn clean install
Затем мы должны запустить:
mvn wildfly:deploy
В качестве альтернативы мы можем развернуть его вручную как пользователь- администратор
из административной консоли сервера приложений .
6. Настройка клиента
После создания удаленного компонента мы должны протестировать развернутый компонент, создав клиент.
Во-первых, давайте обсудим настройку Maven для клиентского проекта.
6.1. Настройка Maven на стороне клиента
Чтобы запустить клиент EJB3, нам нужно добавить следующие зависимости:
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<type>pom</type>
<scope>import</scope>
</dependency>
Мы зависим от удаленных бизнес-интерфейсов EJB этого приложения для запуска клиента. Поэтому нам нужно указать зависимость JAR клиента EJB. Мы добавляем следующее в родительский pom:
<dependency>
<groupId>com.foreach.ejb</groupId>
<artifactId>ejb-remote</artifactId>
<type>ejb</type>
</dependency>
<type>
указывается как ejb
.
6.2. Доступ к удаленному компоненту
Нам нужно создать файл в папке src/main/resources
и назвать его jboss-ejb-client.properties
, который будет содержать все свойства, необходимые для доступа к развернутому компоненту:
remote.connections=default
remote.connection.default.host=127.0.0.1
remote.connection.default.port=8080
remote.connection.default.connect.options.org.xnio.Options
.SASL_POLICY_NOANONYMOUS = false
remote.connection.default.connect.options.org.xnio.Options
.SASL_POLICY_NOPLAINTEXT = false
remote.connection.default.connect.options.org.xnio.Options
.SASL_DISALLOWED_MECHANISMS = ${host.auth:JBOSS-LOCAL-USER}
remote.connection.default.username=testUser
remote.connection.default.password=admin1234!
7. Создание клиента
Класс, который будет обращаться к удаленному bean-компоненту HelloWorld
и использовать его , был создан в EJBClient.java
, который находится в пакете com.foreach.ejb.client
.
7.1. URL-адрес удаленного компонента
Удаленный компонент находится по URL-адресу, соответствующему следующему формату:
ejb:${appName}/${moduleName}/${distinctName}/${beanName}!${viewClassName}
${appName}
— это имя приложения для развертывания. Здесь мы не использовали какой-либо файл EAR, а простое развертывание JAR или WAR, поэтому имя приложения будет пустым.${moduleName}
— это имя, которое мы установили для нашего развертывания ранее, так что этоejb-remote .
${distinctName}
— это конкретное имя, которое можно дополнительно назначить развертываниям, развернутым на сервере. Если развертывание не используетотличное имя
, мы можем использовать пустую строку в имени JNDI дляотдельного имени
, как мы сделали в нашем примере .- Переменная
${beanName}
— это простое имя класса реализации EJB, поэтому в нашем примере этоHelloWorld.
${viewClassName}
обозначает полное имя интерфейса удаленного интерфейса.
7.2. Логика поиска
Далее, давайте посмотрим на нашу простую логику поиска:
public HelloWorld lookup() throws NamingException {
String appName = "";
String moduleName = "remote";
String distinctName = "";
String beanName = "HelloWorld";
String viewClassName = HelloWorld.class.getName();
String toLookup = String.format("ejb:%s/%s/%s/%s!%s",
appName, moduleName, distinctName, beanName, viewClassName);
return (HelloWorld) context.lookup(toLookup);
}
Чтобы подключиться к только что созданному bean
-компоненту , нам понадобится URL-адрес, который мы можем передать в контексте.
7.3. Исходный контекст
Теперь мы создадим/инициализируем контекст сеанса:
public void createInitialContext() throws NamingException {
Properties prop = new Properties();
prop.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
prop.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jboss.naming.remote.client.InitialContextFacto[ERROR]
prop.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
prop.put(Context.SECURITY_PRINCIPAL, "testUser");
prop.put(Context.SECURITY_CREDENTIALS, "admin1234!");
prop.put("jboss.naming.client.ejb.context", false);
context = new InitialContext(prop);
}
Для подключения к удаленному компоненту нам нужен контекст JNDI. Фабрика контекста предоставляется артефактом Maven org.jboss:jboss-remote-naming,
и это создает контекст JNDI, который преобразует URL-адрес, созданный в методе поиска
, в прокси для процесса удаленного сервера приложений.
7.4. Определить параметры поиска
Мы определяем класс фабрики с параметром Context.INITIAL_CONTEXT_FACTORY.
Context.URL_PKG_PREFIXES используется
для определения пакета для сканирования дополнительного контекста именования.
Параметр org.jboss.ejb.client.scoped.context = false
сообщает контексту, что параметры подключения (такие как узел подключения и порт) следует читать из предоставленной карты, а не из файла конфигурации пути к классам. Это особенно полезно, если мы хотим создать пакет JAR, который должен иметь возможность подключаться к разным хостам.
Параметр Context.PROVIDER_URL
определяет схему соединения и должен начинаться с http-remoting://
.
8. Тестирование
Чтобы протестировать развертывание и проверить настройку, мы можем запустить следующий тест, чтобы убедиться, что все работает правильно:
@Test
public void testEJBClient() {
EJBClient ejbClient = new EJBClient();
HelloWorldBean bean = new HelloWorldBean();
assertEquals(bean.getHelloWorld(), ejbClient.getEJBRemoteMessage());
}
Теперь, когда тест пройден, мы можем быть уверены, что все работает так, как ожидалось.
9. Заключение
Итак, мы создали сервер EJB и клиент, который вызывает метод на удаленном EJB. Проект можно запустить на любом сервере приложений, правильно добавив зависимости для этого сервера.
Весь проект можно найти на GitHub .