Упражнение. Развертывание приложения Jakarta EE в JBoss EAP в Службе приложений Azure

Завершено

В этом уроке вы развернете приложение Jakarta EE в Red Hat JBoss Enterprise Application Platform (JBoss EAP) в Службе приложений Azure. Подключаемый модуль Maven для Службы приложений Azure используется для настройки проекта, компиляции и развертывания приложения и настройки источника данных.

Настройка приложения

Настройте приложение с помощью подключаемого модуля Maven для службы приложений Azure, выполнив следующие действия.

  1. Запустите целевую конфигурацию подключаемого модуля Azure в интерактивном режиме с помощью следующей команды:

    ./mvnw com.microsoft.azure:azure-webapp-maven-plugin:2.13.0:config
    

    Важный

    При изменении региона сервера MySQL следует сопоставить этот регион с регионом сервера приложений Jakarta EE, чтобы свести к минимуму задержки.

  2. Используйте значения в следующей таблице, чтобы ответить на интерактивные запросы:

    Входной элемент Ценность
    Create new run configuration (Y/N) [Y]: Y
    Define value for OS [Linux]: Linux
    Define value for javaVersion [Java 17]: 1: Java 17
    Define value for runtimeStack: 3: Jbosseap 7
    Define value for pricingTier [P1v3]: P1v3
    Confirm (Y/N) [Y]: Y

    Ниже приведены типичные выходные данные:

    [INFO] Saving configuration to pom.
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  03:00 min
    [INFO] Finished at: 2025-02-21T06:24:11+09:00
    [INFO] ------------------------------------------------------------------------
    

    После использования команды Maven следующий пример является типичным дополнением к файлу Maven pom.xml :

    <build>
      <finalName>ROOT</finalName>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.4.0</version>
        </plugin>
        <plugin>
            <groupId>com.microsoft.azure</groupId>
            <artifactId>azure-webapp-maven-plugin</artifactId>
            <version>2.13.0</version>
            <configuration>
                <schemaVersion>v2</schemaVersion>
                <resourceGroup>jakartaee-app-on-jboss-rg</resourceGroup>
                <appName>jakartaee-app-on-jboss</appName>
                <pricingTier>P1v3</pricingTier>
                <region>centralus</region>
                <runtime>
                    <os>Linux</os>
                    <javaVersion>Java 17</javaVersion>
                    <webContainer>Jbosseap 7</webContainer>
                </runtime>
                <deployment>
                    <resources>
                        <resource>
                            <directory>${project.basedir}/target</directory>
                            <includes>
                                <include>*.war</include>
                            </includes>
                        </resource>
                    </resources>
                </deployment>
            </configuration>
        </plugin>
      </plugins>
    </build>
    
  3. Проверьте <region> элемент в вашем файле pom.xml. Если его значение не соответствует расположению установки MySQL, измените его на то же расположение.

  4. Используйте следующий пример, чтобы изменить значение webContainer в файле pom.xml на Jbosseap 8, для среды JBoss EAP 8 в службе приложений Azure.

    Совет

    По состоянию на февраль 2025 г. последняя доступная версия JBoss EAP — 8.0 с обновлением 4.1.

    <runtime>
        <os>Linux</os>
        <javaVersion>Java 17</javaVersion>
        <webContainer>Jbosseap 8</webContainer> <!-- Change this value -->
    </runtime>
    
  5. Добавьте следующий XML-код в <resources> элемент файла pom.xml . Эта конфигурация используется для развертывания файла запуска, который вы обновляете позже в этом уроке.

    <resource>
      <type>startup</type>
      <directory>${project.basedir}/src/main/webapp/WEB-INF/</directory>
      <includes>
        <include>createMySQLDataSource.sh</include>
      </includes>
    </resource>
    

    Значение <type> ресурса startup развертывает указанный скрипт в виде файла startup.sh для Linux или startup.cmd для Windows. Расположение развертывания — /home/site/scripts/.

    Заметка

    Вы можете выбрать вариант развертывания и расположение развертывания, указав type один из следующих способов:

    • type=war развертывает WAR-файл в /home/site/wwwroot/app.war, если path не указан.
    • type=war&path=webapps/<appname> развертывает WAR-файл в папке /home/site/wwwroot/webapps/<appname>.
    • type=jar развертывает WAR-файл в /home/site/wwwroot/app.jar. Параметр path игнорируется.
    • type=ear развертывает WAR-файл в папке /home/site/wwwroot/app.ear. Параметр path игнорируется.
    • type=lib развертывает JAR-файл в папке /home/site/libs. Необходимо указать path параметр.
    • type=static развертывает скрипт в папке /home/site/scripts. Необходимо указать параметр path.
    • type=startup развертывает скрипт как startup.sh в Linux или startup.cmd в Windows. Скрипт развертывается в /home/site/scripts/. Параметр path игнорируется.
    • type=zip распакует файл.zip в папку /home/site/wwwroot. Параметр path является необязательным.
  6. Проверьте значения элементов resourceGroup и appName в вашем pom.xml файле.

  7. Присвойте значения resourceGroup переменным среды и appName переменным среды с помощью следующих команд:

    export RESOURCE_GROUP_NAME=<resource-group>
    export WEB_APP_NAME=<app-name>
    

Компиляция и сборка приложения Jakarta EE

После настройки параметров развертывания Службы приложений Azure скомпилируйте и упаковайте исходный код с помощью следующей команды:

./mvnw clean package

Ниже приведены типичные выходные данные:

[INFO] --- war:3.4.0:war (default-war) @ jakartaee-app-on-jboss ---
[INFO] Packaging webapp
[INFO] Assembling webapp [jakartaee-app-on-jboss] in [/private/tmp/mslearn-jakarta-ee-azure/target/ROOT]
[INFO] Processing war project
[INFO] Copying webapp resources [/private/tmp/mslearn-jakarta-ee-azure/src/main/webapp]
[INFO] Building war: /private/tmp/mslearn-jakarta-ee-azure/target/ROOT.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  4.881 s
[INFO] Finished at: 2025-02-21T06:32:30+09:00
[INFO] ------------------------------------------------------------------------

Разверните приложение Jakarta EE на JBoss EAP в Службе приложений Azure

После компиляции и упаковки кода разверните приложение с помощью следующей команды:

./mvnw azure-webapp:deploy

Вы увидите выходные данные, в том числе сообщение об успешном выполнении и URL-адрес развернутого приложения. Не забудьте сохранить URL-адрес для последующего использования.

Настройка подключения к базе данных

Пример приложения подключается к базе данных MySQL и отображает данные. Конфигурация проекта Maven в файлеpom.xml указывает драйвер JDBC MySQL, как показано в следующем примере:

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>${mysql-jdbc-driver}</version>
</dependency>

В результате JBoss EAP автоматически устанавливает драйвер ROOT.war_com.mysql.cj.jdbc.Driver_9_2 JDBC в пакет развертывания ROOT.war.

Создание объекта DataSource MySQL в JBoss EAP

Чтобы получить доступ к базе данных Azure для MySQL, необходимо настроить DataSource объект в JBoss EAP и указать в исходном коде имя Java Naming and Directory Interface (JNDI). Чтобы создать объект MySQL DataSource в JBoss EAP, используйте стартовый shell-скрипт /WEB-INF/createMySQLDataSource.sh. В следующем примере показана ненастроенная версия скрипта, уже размещенная в Службе приложений Azure:

#!/bin/bash
# In order to use the variables in CLI scripts
# https://access.redhat.com/solutions/321513
sed -i -e "s|.*<resolve-parameter-values.*|<resolve-parameter-values>true</resolve-parameter-values>|g" /opt/eap/bin/jboss-cli.xml
/opt/eap/bin/jboss-cli.sh --connect <<EOF
data-source add --name=JPAWorldDataSourceDS \
--jndi-name=java:jboss/datasources/JPAWorldDataSource \
--connection-url=${AZURE_MYSQL_CONNECTIONSTRING}&characterEncoding=utf8&sslMode=REQUIRED&serverTimezone=UTC&authenticationPlugins=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin \
--driver-name=ROOT.war_com.mysql.cj.jdbc.Driver_9_2 \
--min-pool-size=5 \
--max-pool-size=20 \
--blocking-timeout-wait-millis=5000 \
--enabled=true \
--driver-class=com.mysql.cj.jdbc.Driver \
--jta=true \
--use-java-context=true \
--valid-connection-checker-class-name=org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker \
--exception-sorter-class-name=com.mysql.cj.jdbc.integration.jboss.ExtendedMysqlExceptionSorter
exit
EOF

Заметка

При создании источника данных не укажите пароль для подключения MySQL. Переменная AZURE_MYSQL_CONNECTIONSTRING среды указана в параметре --connection-url . Эта переменная среды автоматически устанавливается при создании подключения к службе позже.

Значение параметра подключения к службе задано как jdbc:mysql://$MYSQL_SERVER_INSTANCE.mysql.database.azure.com:3306/world?serverTimezone=UTC&sslmode=required&user=aad_jbossapp, при этом используется имя пользователя aad_jbossapp без пароля. При добавлении &authenticationPlugins=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin к этому URL-адресу для пользователя включена аутентификация Microsoft Entra ID.

Настройте экземпляр службы приложений для вызова скрипта запуска с помощью следующей команды:

az webapp config set \
    --resource-group ${RESOURCE_GROUP_NAME} \
    --name ${WEB_APP_NAME} \
    --startup-file '/home/site/scripts/startup.sh'

После запуска скрипта сервер приложений вызывает его при каждом перезапуске сервера приложений.

Заметка

Если артефакт развертывания не является ROOT.war, измените значение --driver-name=YOUR_ARTIFACT.war_com.mysql.cj.jdbc.Driver_9_2.

Настройка подключения службы для гибкого сервера MySQL

После настройки скрипта запуска настройте службу приложений, чтобы использовать соединитель службы для гибкого подключения сервера MySQL, выполнив следующие действия.

  1. Задайте переменные среды с помощью следующих команд:

    export PASSWORDLESS_USER_NAME_SUFFIX=jbossapp
    export SOURCE_WEB_APP_ID=$(az webapp list \
        --resource-group  $RESOURCE_GROUP_NAME \
        --query "[0].id" \
        --output tsv)
    export MYSQL_ID=$(az mysql flexible-server list \
        --resource-group $RESOURCE_GROUP_NAME \
        --query "[0].id" \
        --output tsv)
    export TARGET_MYSQL_ID=$MYSQL_ID/databases/world
    export MANAGED_ID=$(az identity list \
        --resource-group $RESOURCE_GROUP_NAME \
        --query "[0].id" \
        --output tsv)
    

    Переменные среды используются в следующих целях:

    • PASSWORDLESS_USER_NAME_SUFFIX — суффикс для имени пользователя, используемого для подключения к гибкому серверу MySQL. Имя пользователя, созданное, имеет префикс aad_ , за которым следует указанный суффикс.
    • SOURCE_WEB_APP_ID — это идентификатор экземпляра службы приложений Azure, используемого для подключения к гибкому серверу MySQL.
    • MYSQL_ID — это идентификатор гибкого сервера MySQL.
    • TARGET_MYSQL_ID указывает имя базы данных $MYSQL_ID/databases/world, чтобы установить соединение с пользователем, который имеет разрешение на доступ к базе данных world.
    • MANAGED_ID — это управляемое удостоверение, используемое для подключения к гибкому серверу MySQL.
  2. Добавьте расширение для serviceconnector-passwordless и создайте подключение к службе с помощью следующих команд:

    az extension add \
        --name serviceconnector-passwordless \
        --upgrade
    az webapp connection create mysql-flexible \
        --resource-group ${RESOURCE_GROUP_NAME} \
        --connection $PASSWORDLESS_USER_NAME_SUFFIX \
        --source-id $SOURCE_WEB_APP_ID \
        --target-id $TARGET_MYSQL_ID \
        --client-type java \
        --system-identity mysql-identity-id=$MANAGED_ID
    

    Заметка

    Если вы получаете сообщение об ошибке, например Resource '********-****-****-****-************' does not exist or one of its queried reference-property objects are not present., повторно выполните команду через несколько секунд.

  3. В командной строке SQL проверьте список пользователей, зарегистрированных в MySQL, с помощью следующего запроса:

    SELECT user, host, plugin FROM mysql.user;
    

    Ниже приведены типичные выходные данные:

    +----------------------------------+-----------+-----------------------+
    | user                             | host      | plugin                |
    +----------------------------------+-----------+-----------------------+
    | aad_jbossapp                     | %         | aad_auth              |
    | azureuser                        | %         | mysql_native_password |
    | $CURRENT_AZ_LOGIN_USER_NAME#EXT#@| %         | aad_auth              |
    | azure_superuser                  | 127.0.0.1 | mysql_native_password |
    | azure_superuser                  | localhost | mysql_native_password |
    | mysql.infoschema                 | localhost | caching_sha2_password |
    | mysql.session                    | localhost | caching_sha2_password |
    | mysql.sys                        | localhost | caching_sha2_password |
    +----------------------------------+-----------+-----------------------+
    8 rows in set (2.06 sec)
    

    Вы должны увидеть aad_jbossapp пользователя, который использует плагин aad_auth. С помощью JBoss EAP, развернутого в Azure, можно подключиться к гибкому серверу MySQL с помощью aad_jbossapp имени пользователя без пароля.

Подтвердите ссылку на DataSource в коде

Чтобы получить доступ к базе данных MySQL из приложения, необходимо настроить ссылку на источник данных в проекте приложения.

Код доступа к базе данных реализуется с помощью API сохраняемости Java (JPA). Конфигурация ссылки DataSource находится в файле конфигурации JPA persistence.xml.

Чтобы подтвердить ссылку DataSource , выполните следующие действия.

  1. Откройте файл src/main/resources/META-INF/persistence.xml и проверьте, соответствует ли DataSource имя имени, используемому в конфигурации. Скрипт запуска уже создал имя JNDI, java:jboss/datasources/JPAWorldDataSource, как показано в следующем примере:

    <persistence-unit name="JPAWorldDatasourcePU" transaction-type="JTA">
      <jta-data-source>java:jboss/datasources/JPAWorldDataSource</jta-data-source>
      <exclude-unlisted-classes>false</exclude-unlisted-classes>
      <properties>
        <property name="hibernate.generate_statistics" value="true" />
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
      </properties>
    </persistence-unit>
    
  2. Получите доступ к базе данных MySQL в PersistenceContext названии единицы, как показано в следующем примере:

    @Transactional(REQUIRED)
    @RequestScoped
    public class CityService {
    
        @PersistenceContext(unitName = "JPAWorldDatasourcePU")
        EntityManager em;
    

Доступ к приложению

Пример приложения реализует три конечные точки REST. Чтобы получить доступ к приложению и получить данные, выполните следующие действия.

  1. Используйте браузер для перехода по URL-адресу приложения, который отображался в выходных данных при развертывании приложения.

  2. Чтобы получить все сведения о континенте в формате JSON, используйте GET метод в конечной точке area .

    Снимок экрана: конечная точка области.

  3. Чтобы получить все страны и регионы на указанном континенте, используйте GET метод в area конечной точке и укажите continent параметр пути.

    Снимок экрана: конечная точка области с параметром пути к континенту.

  4. Чтобы получить все города с населением более одного миллиона в указанной стране или регионе, используйте GET метод в countries конечной точке и укажите countrycode параметр пути.

    Снимок экрана: конечная точка стран с параметром пути к коду страны.

Сводка упражнений

В этом уроке вы проверили конечные точки REST приложения и подтвердили, что приложение может получать данные из базы данных MySQL. В следующем уроке вы проверяете журналы сервера.