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

Завершено

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

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

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

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

Важно!

Если вы изменили регион сервера MySQL, вам также следует задать тот же регион для сервера приложения Java EE, чтобы минимизировать задержки.
В команде выберите Java 11 для версии Java и JBoss EAP 7 для стека среды выполнения.

Входной элемент Значение
Available subscriptions: Your appropriate subsctioption
Choose a Web Container Web App [\<create\>]: 1: <create>
Define value for OS [Linux]: Linux
Define value for javaVersion [Java 17]: 2: Java 11
Define value for runtimeStack: 1: Jbosseap 7
Define value for pricingTier [P1v3]: P1v3
Confirm (Y/N) [Y]: Y

После выполнения команды вы получите сообщения, как показано в терминале:

$ ./mvnw com.microsoft.azure:azure-webapp-maven-plugin:2.9.0:config
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------< com.microsoft.azure.samples:jakartaee-app-on-jboss >---------
[INFO] Building jakartaee-app-on-jboss 1.0-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO] 
[INFO] --- azure-webapp-maven-plugin:2.5.0:config (default-cli) @ jakartaee-app-on-jboss ---
[WARNING] The POM for com.microsoft.azure.applicationinsights.v2015_05_01:azure-mgmt-insights:jar:1.0.0-beta is invalid, transitive dependencies (if any) will not be available, enable debug logging for more details
[INFO] Auth type: OAUTH2
Username: YOUR_EMAIL_ADDRESS@microsoft.com
Available subscriptions:
[INFO] Subscription: YOUR_SUBSCRIPTION(********-****-****-****-************)
[INFO] It may take a few minutes to load all Java Web Apps, please be patient.
Web Container Web Apps in subscription Microsoft Azure Internal Billing-CDA:
* 1: <create>
  2: jakartaee-app-on-jboss-yoshio (linux, jbosseap 7.2-java8)
Please choose a Web Container Web App [<create>]: 
Define value for OS [Linux]:
* 1: Linux
  2: Windows
  3: Docker
Enter your choice: 
Define value for javaVersion [Java 8]:
* 1: Java 8
  2: Java 11
Enter your choice: 
Define value for runtimeStack:
  1: Jbosseap 7.2
  2: Jbosseap 7
* 3: Tomcat 8.5
  4: Tomcat 9.0
Enter your choice: 1
Define value for pricingTier [P1v3]:
  1: P3v3
  2: P2v3
* 3: P1v3
Enter your choice: 
Please confirm webapp properties
Subscription Id : ********-****-****-****-************
AppName : jakartaee-app-on-jboss-1625038814881
ResourceGroup : jakartaee-app-on-jboss-1625038814881-rg
Region : westeurope
PricingTier : P1v3
OS : Linux
Java : Java 8
Web server stack: Jbosseap 7.2
Deploy to slot : false
Confirm (Y/N) [Y]: 
[INFO] Saving configuration to pom.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:43 min
[INFO] Finished at: 2021-06-30T16:40:47+09:00
[INFO] ------------------------------------------------------------------------
$ 

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

  <build>
    <finalName>ROOT</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.3.2</version>
      </plugin>
        <plugin>
            <groupId>com.microsoft.azure</groupId>
            <artifactId>azure-webapp-maven-plugin</artifactId>
            <version>2.9.0</version>
            <configuration>
                <schemaVersion>v2</schemaVersion>
                <resourceGroup>jakartaee-app-on-jboss-1625038814881-rg</resourceGroup>
                <appName>jakartaee-app-on-jboss-1625038814881</appName>
                <pricingTier>P1v3</pricingTier>
                <region>centralus</region>
                <runtime>
                    <os>Linux</os>
                    <javaVersion>Java 11</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>

Важно!

Проверьте элемент <region>. Если он не указывает на то же расположение установки, что и для MySQL, измените его на то же расположение.

Добавив описанную выше конфигурацию для развертывания в Azure, добавьте следующие записи XML для развертывания файла запуска. Ресурс <type>startup</type> развертывает указанный скрипт как startup.sh (Linux) или startup.cmd (Windows) в /home/site/scripts/. Мы настраиваем скрипт запуска на следующем шаге.

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

Примечание.

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

  • type=<war|jar|ear|lib|startup|static|zip>

    • type=war развернет WAR-файл в /home/site/wwwroot/app.war, если параметр pathне задан
    • type=war&path=webapps/<appname>\ будет работать точно так же, как wardeploy, путем распаковки приложения в папку /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 указывать не обязательно.

Теперь проверьте значения для имени группы ресурсов и имени приложения в приведенном выше XML-файле. Запишите эти имена или назначьте их переменным среды (что рекомендуется).

<resourceGroup>jakartaee-app-on-jboss-1625038814881-rg</resourceGroup>
<appName>jakartaee-app-on-jboss-1625038814881</appName>

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

export RESOURCEGROUP_NAME=jakartaee-app-on-jboss-1625038814881-rg
export WEBAPP_NAME=jakartaee-app-on-jboss-1625038814881

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

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

./mvnw clean package

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

[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] Webapp assembled in [369 msecs]
[INFO] Building war: /private/tmp/mslearn-jakarta-ee-azure/target/ROOT.war
[INFO] WEB-INF/web.xml already added, skipping
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.656 s
[INFO] Finished at: 2023-03-04T12:35:43-05:00
[INFO] ------------------------------------------------------------------------

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

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

./mvnw azure-webapp:deploy

В окне терминала появится следующее сообщение:

[INFO] Creating resource group jakartaee-app-on-jboss-1625038814881-rg in region westeurope...
[INFO] Successfully created resource group jakartaee-app-on-jboss-1625038814881-rg.
[INFO] Creating app service plan...
[INFO] Successfully created app service plan asp-jakartaee-app-on-jboss-1625038814881.
[INFO] Creating web app jakartaee-app-on-jboss-1625038814881...
[INFO] Successfully created Web App jakartaee-app-on-jboss-1625038814881.
[INFO] Trying to deploy artifact to jakartaee-app-on-jboss-1625038814881...
[INFO] Deploying (/private/tmp/mslearn-jakarta-ee-azure/target/ROOT.war)[war]  ...
[INFO] Successfully deployed the artifact to https://jakartaee-app-on-jboss-1625038814881.azurewebsites.net
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  02:11 min
[INFO] Finished at: 2023-03-04T12:38:39-05:00
[INFO] ------------------------------------------------------------------------

Обратите внимание на URL-адрес развернутого приложения, особенно следующую строку в выходных данных Maven:

[INFO] Successfully deployed the artifact to https://jakartaee-app-on-jboss-1625038814881.azurewebsites.net

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

Пример приложения подключается к данным My База данных SQL и отображает данные.

В конфигурации проекта Maven в файле pom.xml мы указали драйвер MySQL JDBC следующим образом:

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

В результате JBoss EAP автоматически устанавливает драйвер JDBC в пакет развертывания (ROOT.war). Ссылаться на имя драйвера MySQL JDBC можно следующим образом:

ROOT.war_com.mysql.cj.jdbc.Driver_8_0

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

Чтобы получить доступ к Базе данных Azure для MySQL, необходимо настроить объект DataSource в JBoss EAP и указать имя JNDI в исходном коде.

Чтобы создать объект DataSource MySQL в JBoss EAP, мы создали следующий скрипт запуска оболочки. Файл скрипта createMySQLDataSource.sh находится в каталоге /WEB-INF.

Примечание.

В скрипте мы привязываем объект DataSource MySQL с помощью команды интерфейса командной строки JBoss. Строка подключения, имя пользователя и пароль используют переменные среды MYSQL_CONNECTION_URL, MYSQL_USER и MYSQL_PASSWORD.

Источник файла скрипта показан далее. Этот файл скрипта уже был отправлен в Служба приложений, но он еще не настроен для вызова.

#!/usr/bin/bash

# In order to use the variables in JBoss 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=${MYSQL_CONNECTION_URL} \
--driver-name=ROOT.war_com.mysql.cj.jdbc.Driver_8_0 \
--user-name=${MYSQL_USER} \
--password=${MYSQL_PASSWORD} \
--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

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

az webapp config set --startup-file '/home/site/scripts/startup.sh' \
-n ${WEBAPP_NAME} \
-g ${RESOURCEGROUP_NAME}

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

Примечание.

Если ваш артефакт развертывания не ROOT.war, необходимо также изменить значение --driver-name=YOUR_ARTIFACT.war_com.mysql.cj.jdbc.Driver_8_0.

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

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

az webapp config appsettings set \
  --resource-group ${RESOURCEGROUP_NAME} --name ${WEBAPP_NAME} \
  --settings \
  MYSQL_CONNECTION_URL='jdbc:mysql://mysqlserver-**********.mysql.database.azure.com:3306/world?useSSL=true&requireSSL=false' \
  MYSQL_PASSWORD='************' \
  MYSQL_USER=azureuser

Совет

Значения переменных MYSQL_CONNECTION_URL, MYSQL_USER и MYSQL_PASSWORD были заданы в предыдущем уроке.

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

Чтобы получить доступ к базе данных MySQL из приложения, необходимо настроить ссылку на источник данных в проекте приложения. Мы реализовали код доступа к базе данных с помощью Java Persistence API (JPA).

Конфигурация ссылки на DataSource была добавлена в файл persistence.xml, который является файлом конфигурации JPA.

Перейдите к следующему файлу:

├── 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>
</persistence>

Затем можно получить доступ к базе данных MySQL, указанной в имени модуля PersistenceContext, следующим образом:

@Transactional(REQUIRED)
@RequestScoped
public class CityService {

    @PersistenceContext(unitName = "JPAWorldDatasourcePU")
    EntityManager em;

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

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

Чтобы получить доступ к приложению, необходимо сослаться на URL-адрес приложения, полученный в предыдущем разделе:

[INFO] Successfully deployed the artifact to  
https://jakartaee-app-on-jboss-1606464084546.azurewebsites.net

Выполните следующую команду, чтобы получить все сведения о континентах в формате JSON.

Screenshot that shows area as the REST endpoint.

$ curl https://${WEBAPP_NAME}.azurewebsites.net/area
["North America","Asia","Africa","Europe","South America","Oceania","Antarctica"]$ 

Если указать континент в URL-адресе, вы можете получить все страны и регионы в указанном континенте.

Screenshot that shows continent as the REST endpoint.

$ curl https://${WEBAPP_NAME}.azurewebsites.net/area/Asia | jq '.[] | { name: .name, code: .code }'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--   100 16189  100 16189    0     0  65278      0 --:--:-- --:--:-- --:--:-- 65542
{
  "name": "Afghanistan",
  "code": "AFG"
}
{
  "name": "United Arab Emirates",
  "code": "ARE"
}
{
  "name": "Armenia",
  "code": "ARM"
}
{
  "name": "Azerbaijan",
  "code": "AZE"
}
{
  "name": "Bangladesh",
  "code": "BGD"
}
....

Наконец, если указать код страны или региона после /countries, вы можете получить все города с населением более 1 миллиона в пределах страны или региона.

Screenshot that shows cities as the REST endpoint.

$ curl https://${WEBAPP_NAME}.azurewebsites.net/countries/JPN | jq '.[].name'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--   100   788  100   788    0     0   2671      0 --:--:-- --:--:-- --:--:--  2662
"Tokyo"
"Jokohama [Yokohama]"
"Osaka"
"Nagoya"
"Sapporo"
"Kioto"
"Kobe"
"Fukuoka"
"Kawasaki"
"Hiroshima"
"Kitakyushu"

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

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

В следующем уроке вы изучите журналы сервера.