演習 - Java EE (Jakarta EE) アプリケーションを JBoss EAP on Azure App Service にデプロイする
この演習では、Java EE (Jakarta EE) アプリケーションを JBoss EAP on Azure App Service にデプロイします。 Maven プラグインを使用し、プロジェクトの構成、アプリケーションのコンパイルとデプロイ、データ ソースの構成を行います。
Azure App Service 用の Maven プラグインを使用してアプリを構成する
Azure App Service 用の Maven プラグインで構成目標を実行することにより、アプリケーションを構成しましょう。
./mvnw com.microsoft.azure:azure-webapp-maven-plugin:2.9.0:config
重要
MySQL サーバーのリージョンを変更した場合、待機時間の遅延を最小限に抑えるために、Java EE アプリケーション サーバーも同じリージョンに変更する必要があります。
コマンドで、Java バージョンに Java 11、ランタイム スタックに 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] ------------------------------------------------------------------------
$
コマンドが完了すると、Maven の pom.xml
ファイルに次のエントリが追加されていることがわかります。
<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 -->
Note
XML では次のリソースを指定してデプロイできます。
type=<war|jar|ear|lib|startup|static|zip>
path
が指定されて "いない" 場合、type=war
により、war ファイルは/home/site/wwwroot/app.war
に展開されます。type=war&path=webapps/<appname>\
の場合、アプリを /home/site/wwwroot/webapps/<appname> に解凍することで、WarDeploy とまったく同じように動作します。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 App Service のデプロイ設定を構成した後、ソース コードをコンパイルしてパッケージ化します。
./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 on Azure App Service にデプロイする
コードをコンパイルしてパッケージ化した後、アプリケーションをデプロイします。
./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
データベース接続の構成
サンプル アプリケーションが MySQL データベースに接続され、データが表示されます。
pom.xml
の Maven プロジェクト構成では、MySQL JDBC ドライバーを次のように指定しました。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-jdbc-driver}</version>
</dependency>
この結果、JDBC ドライバーは、JBoss EAP によってデプロイ パッケージ ROOT.war
に自動的にインストールされます。 MySQL JDBC ドライバーの名前は次のように参照できます。
ROOT.war_com.mysql.cj.jdbc.Driver_8_0
JBoss EAP で MySQL の DataSource オブジェクトを作成する
Azure Database for MySQL にアクセスするには、JBoss EAP で DataSource
オブジェクトを構成し、ソース コードで JNDI 名を指定する必要があります。
JBoss EAP で MySQL の DataSource
オブジェクトを作成するため、次のスタートアップ シェル スクリプトを作成しました。 スクリプト ファイルは、/WEB-INF
ディレクトリにある createMySQLDataSource.sh
です。
Note
このスクリプトで、JBoss CLI コマンドを使用して MySQL の DataSource をバインドします。 接続文字列、ユーザー名、パスワードには、環境変数 MYSQL_CONNECTION_URL
、MYSQL_USER
、MYSQL_PASSWORD
を使用します。
次にスクリプト ファイルのソースが表示されます。 このスクリプト ファイルは App Service に既にアップロードされていますが、呼び出されるようにはまだ構成されていません。
#!/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
次に、スタートアップ スクリプトを呼び出すように App Service インスタンスを構成します。
az webapp config set --startup-file '/home/site/scripts/startup.sh' \
-n ${WEBAPP_NAME} \
-g ${RESOURCEGROUP_NAME}
スクリプトは、実行された後、アプリケーション サーバーが再起動されるたびに呼び出されます。
Note
デプロイ成果物が ROOT.war
ではない場合は、--driver-name=YOUR_ARTIFACT.war_com.mysql.cj.jdbc.Driver_8_0
の値も変更する必要があります。
MySQL に接続するための環境変数を構成する
スタートアップ スクリプトを構成した後、特定の環境変数を使用するように App Service を構成します。
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
は、前のユニットの設定値を使用します。
コード内のデータソース参照を確認する
アプリケーションから MySQL データベースにアクセスするには、アプリケーション プロジェクトでデータ ソース参照を構成する必要があります。 Java Persistence API (JPA) を使用して、データベース アクセス コードを実装しました。
DataSource
の参照の構成が、JPA の構成ファイルである persistence.xml
に追加されています。
次のファイルにアクセスします。
├── 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>
次に、PersistenceContext
のユニット名で次のように参照される MySQL データベースにアクセスできます。
@Transactional(REQUIRED)
@RequestScoped
public class CityService {
@PersistenceContext(unitName = "JPAWorldDatasourcePU")
EntityManager em;
アプリケーションへのアクセス
サンプル アプリケーションで、3 つの REST エンドポイントを実装しました。 Web ブラウザーまたは curl
コマンドを使用して、アプリケーションにアクセスし、これらのエンドポイントを検証することができます。
アプリケーションにアクセスするには、前のセクションで取得したアプリケーションの URL を参照する必要があります。
[INFO] Successfully deployed the artifact to
https://jakartaee-app-on-jboss-1606464084546.azurewebsites.net
次のコマンドを実行し、すべての大陸情報を JSON 形式で取得します。
$ curl https://${WEBAPP_NAME}.azurewebsites.net/area
["North America","Asia","Africa","Europe","South America","Oceania","Antarctica"]$
URL で大陸を指定すると、指定した大陸のすべての国/地域を取得できます。
$ 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
の後に国/地域番号を指定すると、その国/地域内で人口が 100 万を超えるすべての都市を確認できます。
$ 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 データベースのデータを取得できることをテストしました。
次のユニットでは、サーバー ログを調べます。