演習 - JBoss EAP on Azure App Service に Jakarta EE アプリケーションをデプロイする

完了

このユニットでは、Azure App Service 上の Red Hat JBoss Enterprise Application Platform (JBoss EAP) に Jakarta EE アプリケーションをデプロイします。 Azure App Service 用の Maven プラグインを使用して、プロジェクトの構成、アプリケーションのコンパイルとデプロイ、データ ソースの構成を行います。

アプリを設定する

次の手順を使用して、Azure App Service 用の Maven プラグインを使用してアプリを構成します。

  1. 次のコマンドを使用して、Azure プラグインの構成目標を対話形式で実行します。

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

    Von Bedeutung

    MySQL サーバーのリージョンを変更する場合は、待機時間の遅延を最小限に抑えるために、そのリージョンを Jakarta EE アプリケーション サーバーのリージョンと一致させる必要があります。

  2. 対話型プロンプトに応答するには、次の表の値を使用します。

    Input 要素 価値
    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. pom.xmlファイル内の<region>要素を確認します。 その値が MySQL のインストール場所と一致しない場合は、同じ場所に変更します。

  4. 次の例を使用して、Azure App Service 上の JBoss EAP 8 環境に対して、pom.xml ファイル内のwebContainer値をJbosseap 8するように変更します。

    ヒント

    2025 年 2 月の時点で、JBoss EAP の最新バージョンは 8.0 Update 4.1 です。

    <runtime>
        <os>Linux</os>
        <javaVersion>Java 17</javaVersion>
        <webContainer>Jbosseap 8</webContainer> <!-- Change this value -->
    </runtime>
    
  5. pom.xml ファイルの<resources>要素に次の XML を追加します。 この構成は、このユニットの後半で更新するスタートアップ ファイルを展開するために使用されます。

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

    startupのリソース <type>値は、指定されたスクリプトを Linux または Windows 用のstartup.cmdstartup.sh ファイルとしてデプロイします。 展開場所は /home/site/scripts/ です

    展開オプションと展開場所を選択するには、次のいずれかの方法で type を指定します。

    • type=war pathが指定されていない場合は、WAR ファイルを /home/site/wwwroot/app.war にデプロイします。
    • 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 は、スクリプトを Linux に startup.sh としてデプロイするか、Windows で startup.cmd します。 スクリプトは /home/site/scripts/ に展開されます。 path パラメーターは無視されます。
    • type=zip は、.zip ファイルを /home/site/wwwroot に解凍します。 path パラメーターは省略可能です。
  6. pom.xml ファイル内resourceGroup要素とappName要素の値を確認します。

  7. 次のコマンドを使用して、 resourceGroupappName の値を環境変数に割り当てます。

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

Jakarta EE アプリをコンパイルしてビルドする

Azure App Service のデプロイ設定を構成したら、次のコマンドを使用してソース コードをコンパイルしてパッケージ化します。

./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] ------------------------------------------------------------------------

JBoss EAP on Azure App Service に Jakarta EE アプリをデプロイする

コードをコンパイルしてパッケージ化した後、次のコマンドを使用してアプリケーションをデプロイします。

./mvnw azure-webapp:deploy

成功メッセージとデプロイされたアプリケーションの URL を含む出力が表示されます。 後で使用するために、必ず URL を保存しておいてください。

データベース接続を構成する

サンプル アプリケーションは MySQL データベースに接続し、データを表示します。 pom.xml ファイルの Maven プロジェクト構成では、次の例に示すように MySQL JDBC ドライバーを指定します。

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

その結果、JBoss EAP によって、デプロイ パッケージ ROOT.war に JDBC ドライバー ROOT.war_com.mysql.cj.jdbc.Driver_9_2が自動的にインストールされます。

JBoss EAP で MySQL DataSource オブジェクトを作成する

Azure Database for MySQL にアクセスするには、JBoss EAP で DataSource オブジェクトを構成し、ソース コードで Java Naming and Directory Interface (JNDI) 名を指定する必要があります。 JBoss EAP で MySQL DataSource オブジェクトを作成するには、 /WEB-INF/createMySQLDataSource.sh スタートアップ シェル スクリプトを使用します。 次の例は、Azure App Service に既に存在する構成されていないバージョンのスクリプトを示しています。

#!/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 ユーザー名が使用されます。 この URL に &authenticationPlugins=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin を追加することで、 aad_jbossapp ユーザーに対して Microsoft Entra ID 認証が有効になります。

次のコマンドを使用して、スタートアップ スクリプトを呼び出すように App Service インスタンスを構成します。

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 フレキシブル サーバー接続に Service Connector を使用するように App Service を構成します。

  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 は、MySQL フレキシブル サーバーへの接続に使用される Azure App Service インスタンスの ID です。
    • MYSQL_ID は MySQL フレキシブル サーバーの ID です。
    • TARGET_MYSQL_IDは、world データベースにアクセスする権限を持つユーザーとの接続を確立するための$MYSQL_ID/databases/worldとしてデータベース名を指定します。
    • MANAGED_ID は、MySQL フレキシブル サーバーへの接続に使用されるマネージド ID です。
  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_auth プラグインを使用するaad_jbossapp ユーザーが表示されます。 Azure にデプロイされた JBoss EAP から、パスワードなしで aad_jbossapp ユーザー名を使用して MySQL フレキシブル サーバーに接続できます。

コード内の DataSource 参照を確認する

アプリケーションから MySQL データベースにアクセスするには、アプリケーション プロジェクトでデータ ソース参照を構成する必要があります。

データベース アクセス コードは、Java Persistence API (JPA) を使用して実装されます。 DataSource参照の構成は、JPA 構成ファイル persistence.xmlにあります。

DataSource参照を確認するには、次の手順に従います。

  1. src/main/resources/META-INF/persistence.xml ファイルを開き、DataSource名が構成で使用されている名前と一致するかどうかを確認します。 スタートアップ スクリプトでは、次の例に示すように、 java:jboss/datasources/JPAWorldDataSourceとして JNDI 名が既に作成されています。

    <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. 次の例に示すように、 PersistenceContext ユニット名で MySQL データベースにアクセスします。

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

アプリケーションへのアクセス

サンプル アプリケーションは、3 つの REST エンドポイントを実装します。 アプリケーションにアクセスしてデータを取得するには、次の手順に従います。

  1. ブラウザーを使用して、アプリケーションの URL に移動します。この URL は、アプリケーションのデプロイ時に出力に表示されます。

  2. すべての大陸情報を JSON 形式で取得するには、area エンドポイントで GET メソッドを使用します。

    エリア エンドポイントのスクリーンショット。

  3. 指定した大陸のすべての国と地域を取得するには、area エンドポイントで GET メソッドを使用し、continentパス パラメーターを指定します。

    大陸パス パラメーターを持つエリア エンドポイントのスクリーンショット。

  4. 指定された国または地域内で人口が 100 万を超えるすべての都市を取得するには、countries エンドポイントで GET メソッドを使用し、countrycode パス パラメーターを指定します。

    countrycode path パラメーターを持つ国のエンドポイントのスクリーンショット。

演習の概要

このユニットでは、アプリケーション REST エンドポイントを検証し、アプリケーションが MySQL データベースからデータを取得できることを確認しました。 次のユニットでは、サーバー ログを調べます。