Übung – Bereitstellen einer Jakarta EE-Anwendung für JBoss EAP auf Azure App Service

Abgeschlossen

In dieser Einheit stellen Sie eine Jakarta EE-Anwendung auf dem Azure App Service auf Red Hat JBoss Enterprise Application Platform (JBoss EAP) bereit. Sie verwenden das Maven-Plug-In für Azure App Service, um das Projekt zu konfigurieren, die Anwendung zu kompilieren und bereitzustellen und eine Datenquelle zu konfigurieren.

Konfigurieren der App

Konfigurieren Sie die App mit dem Maven-Plug-In für Azure App Service mithilfe der folgenden Schritte:

  1. Führen Sie das Konfigurationsziel des Azure-Plug-Ins interaktiv mit dem folgenden Befehl aus:

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

    Von Bedeutung

    Wenn Sie die Region Ihres MySQL-Servers ändern, sollten Sie diese Region mit der Region Ihres Jakarta EE-Anwendungsservers abgleichen, um Latenzverzögerungen zu minimieren.

  2. Verwenden Sie die Werte in der folgenden Tabelle, um die interaktiven Eingabeaufforderungen zu beantworten:

    Eingabeelement Wert
    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

    Das folgende Ergebnis ist typisch:

    [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] ------------------------------------------------------------------------
    

    Nachdem Sie den Befehl Maven verwendet haben, ist das folgende Beispiel eine typische Ergänzung zu Ihrer Maven pom.xml Datei:

    <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. Überprüfen Sie das <region> Element in Ihrer pom.xml Datei. Wenn der Wert nicht mit dem Installationsspeicherort von MySQL übereinstimmt, ändern Sie ihn an denselben Speicherort.

  4. Verwenden Sie das folgende Beispiel, um den webContainer-Wert in Ihrer pom.xml-Datei auf Jbosseap 8 zu ändern, für die JBoss EAP 8-Umgebung in Azure App Service.

    Tipp

    Ab Februar 2025 ist die neueste verfügbare Version von JBoss EAP 8.0 Update 4.1.

    <runtime>
        <os>Linux</os>
        <javaVersion>Java 17</javaVersion>
        <webContainer>Jbosseap 8</webContainer> <!-- Change this value -->
    </runtime>
    
  5. Fügen Sie dem Element Ihrer <resources> den folgenden XML-Code hinzu. Diese Konfiguration wird verwendet, um die Startdatei bereitzustellen, die Sie später in dieser Einheit aktualisieren.

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

    Der <type>-Wert startup der Ressource stellt das angegebene Skript als Datei startup.sh für Linux bzw. startup.cmd für Windows bereit. Der Bereitstellungsspeicherort ist /home/site/scripts/.

    Hinweis

    Sie können die Bereitstellungsoption und den Bereitstellungsort auswählen, indem Sie eine der folgenden Möglichkeiten angeben type :

    • type=war stellt die WAR-Datei auf /home/site/wwwroot/app.war bereit, falls path nicht angegeben.
    • type=war&path=webapps/<appname> stellt die WAR-Datei auf /home/site/wwwroot/webapps/<appname> bereit.
    • type=jar stellt die WAR-Datei auf /home/site/wwwroot/app.jar bereit. Der Parameter path wird ignoriert.
    • type=ear stellt die WAR-Datei auf /home/site/wwwroot/app.ear bereit. Der Parameter path wird ignoriert.
    • type=lib stellt den JAR auf /home/site/libs bereit. Sie müssen den Parameter path angeben.
    • type=static stellt das Skript auf "/home/site/scripts" bereit. Sie müssen den path Parameter angeben.
    • type=startup stellt das Skript als startup.sh unter Linux oder startup.cmd unter Windows bereit . Das Skript wird für /home/site/scripts/bereitgestellt. Der Parameter path wird ignoriert.
    • type=zip entpackt die .zip Datei auf /home/site/wwwroot. Der Parameter path ist optional.
  6. Überprüfen Sie die Werte für die resourceGroup und appName Elemente in Ihrer pom.xml Datei.

  7. Weisen Sie die Werte für resourceGroup und appName Umgebungsvariablen mithilfe der folgenden Befehle zu:

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

Kompilieren und Erstellen der Jakarta EE-App

Nachdem Sie die Azure App Service-Bereitstellungseinstellungen konfiguriert haben, kompilieren und verpacken Sie den Quellcode mithilfe des folgenden Befehls:

./mvnw clean package

Das folgende Ergebnis ist typisch:

[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] ------------------------------------------------------------------------

Bereitstellen der Jakarta EE-App für JBoss EAP im Azure App Service

Stellen Sie nach dem Kompilieren und Verpacken des Codes die Anwendung mithilfe des folgenden Befehls bereit:

./mvnw azure-webapp:deploy

Die Ausgabe sollte eine Erfolgsmeldung und die URL der bereitgestellten Anwendung enthalten. Achten Sie darauf, die URL für die spätere Verwendung zu speichern.

Konfigurieren einer Datenbankverbindung

Die Beispielanwendung stellt eine Verbindung mit Ihrer MySQL-Datenbank und zeigt Daten an. Die Maven-Projektkonfiguration in der Dateipom.xml gibt den MySQL-JDBC-Treiber an, wie im folgenden Beispiel veranschaulicht:

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

Daher installiert JBoss EAP automatisch den JDBC-Treiber ROOT.war_com.mysql.cj.jdbc.Driver_9_2 zu Ihrem Bereitstellungspaket ROOT.war.

Erstellen des MySQL DataSource-Objekts in JBoss EAP

Um auf Azure Database for MySQL zuzugreifen, müssen Sie das DataSource Objekt in JBoss EAP konfigurieren und den Namen der Java Naming and Directory Interface (JNDI) in Ihrem Quellcode angeben. Zum Erstellen eines MySQL-Objekts DataSource in JBoss EAP verwenden Sie das Startshellskript "/WEB-INF/createMySQLDataSource.sh ". Das folgende Beispiel zeigt eine nicht konfigurierte Version des Skripts, die bereits in Azure App Service enthalten ist:

#!/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

Hinweis

Wenn Sie die Datenquelle erstellen, geben Sie kein Kennwort für die MySQL-Verbindung an. Die Umgebungsvariable AZURE_MYSQL_CONNECTIONSTRING wird im --connection-url Parameter angegeben. Diese Umgebungsvariable wird automatisch festgelegt, wenn die Dienstverbindung später erstellt wird.

Der Dienstverbindungswert ist auf jdbc:mysql://$MYSQL_SERVER_INSTANCE.mysql.database.azure.com:3306/world?serverTimezone=UTC&sslmode=required&user=aad_jbossapp gesetzt, was den aad_jbossapp Benutzernamen ohne Kennwort verwendet. Durch Anfügen &authenticationPlugins=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin an diese URL ist die Microsoft Entra ID-Authentifizierung für den aad_jbossapp Benutzer aktiviert.

Konfigurieren Sie Ihre App Service-Instanz so, dass das Startskript mithilfe des folgenden Befehls aufgerufen wird:

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

Nachdem das Skript ausgeführt wurde, ruft der Anwendungsserver ihn jedes Mal auf, wenn der Anwendungsserver neu gestartet wird.

Hinweis

Wenn Ihr Bereitstellungsartefakt nicht ROOT.war ist, ändern Sie auch den --driver-name=YOUR_ARTIFACT.war_com.mysql.cj.jdbc.Driver_9_2 Wert.

Konfigurieren der Dienstverbindung für den flexiblen MySQL-Server

Nachdem Sie das Startskript konfiguriert haben, konfigurieren Sie Den App-Dienst so, dass Service Connector für die flexible Serververbindung mySQL verwendet wird, indem Sie die folgenden Schritte ausführen:

  1. Festlegen von Umgebungsvariablen mithilfe der folgenden Befehle:

    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)
    

    Die Umgebungsvariablen werden für die folgenden Zwecke verwendet:

    • PASSWORDLESS_USER_NAME_SUFFIX ist das Suffix für den Benutzernamen, der zum Herstellen einer Verbindung mit dem flexiblen MySQL-Server verwendet wird. Der erstellte Benutzername hat das Präfix aad_ gefolgt vom angegebenen Suffix.
    • SOURCE_WEB_APP_ID ist die ID der Azure App Service-Instanz, die zum Herstellen einer Verbindung mit dem flexiblen MySQL-Server verwendet wird.
    • MYSQL_ID ist die ID des flexiblen MySQL-Servers.
    • TARGET_MYSQL_ID gibt den Datenbanknamen $MYSQL_ID/databases/world an, um eine Verbindung für einen Benutzer herzustellen, der berechtigt ist, auf die world-Datenbank zuzugreifen.
    • MANAGED_ID ist die verwaltete Identität, die zum Herstellen einer Verbindung mit dem flexiblen MySQL-Server verwendet wird.
  2. Fügen Sie die Erweiterung serviceconnector-passwordless hinzu und erstellen Sie die Dienstverbindung mithilfe der folgenden Befehle:

    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
    

    Hinweis

    Wenn Sie eine Fehlermeldung wie Resource '********-****-****-****-************' does not exist or one of its queried reference-property objects are not present. erhalten, führen Sie den Befehl nach ein paar Sekunden erneut aus.

  3. Überprüfen Sie an der SQL-Eingabeaufforderung die Liste der benutzer, die in MySQL registriert sind, indem Sie die folgende Abfrage verwenden:

    SELECT user, host, plugin FROM mysql.user;
    

    Das folgende Ergebnis ist typisch:

    +----------------------------------+-----------+-----------------------+
    | 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)
    

    Sie sollten einen aad_jbossapp Benutzer sehen, der das aad_auth Plug-In verwendet. Von JBoss EAP, das in Azure bereitgestellt wird, können Sie über den aad_jbossapp Benutzernamen ohne Kennwort eine Verbindung mit dem flexiblen MySQL-Server herstellen.

Bestätigen des DataSource-Verweises im Code

Um von Ihrer Anwendung aus auf die MySQL-Datenbank zuzugreifen, müssen Sie den Datenquellenverweis in Ihrem Anwendungsprojekt konfigurieren.

Der Datenbankzugriffscode wird mithilfe der Java-Persistenz-API (JPA) implementiert. Die Konfiguration für den Verweis befindet sich in der DataSource JPA-Konfigurationsdatei persistence.xml.

Führen Sie die folgenden Schritte aus, um den DataSource Verweis zu bestätigen:

  1. Öffnen Sie die Datei "src/main/resources/META-INF/persistence.xml ", und überprüfen Sie, ob der DataSource Name dem in der Konfiguration verwendeten Namen entspricht. Das Startskript hat den JNDI-Namen bereits als java:jboss/datasources/JPAWorldDataSource erstellt, wie im folgenden Beispiel gezeigt:

    <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. Greifen Sie auf die MySQL-Datenbank im PersistenceContext-Einheitennamen zu, wie im folgenden Beispiel gezeigt:

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

Zugreifen auf die Anwendung

Die Beispielanwendung implementiert drei REST-Endpunkte. Führen Sie die folgenden Schritte aus, um auf die Anwendung zuzugreifen und Daten abzurufen:

  1. Verwenden Sie Ihren Browser, um zur Anwendungs-URL zu navigieren, die bei der Bereitstellung der Anwendung in der Ausgabe angezeigt wurde.

  2. Um alle Kontinentinformationen im JSON-Format abzurufen, verwenden Sie die GET Methode auf dem area Endpunkt.

    Screenshot: Bereichsendpunkt

  3. Um alle Länder und Regionen auf einem bestimmten Kontinent abzurufen, verwenden Sie die GET Methode für den area Endpunkt, und geben Sie einen continent Pfadparameter an.

    Screenshot: Bereichsendpunkt mit einem Kontinentpfadparameter

  4. Um alle Städte zu erhalten, die eine Bevölkerung von mehr als einer Million innerhalb des angegebenen Landes oder der angegebenen Region haben, verwenden Sie die GET Methode auf dem countries Endpunkt, und geben Sie einen countrycode Pfadparameter an.

    Screenshot des Länderendpunkts mit dem Pfadparameter

Zusammenfassung der Übung

In dieser Einheit haben Sie die REST-Endpunkte der Anwendung überprüft und bestätigt, dass Ihre Anwendung Daten aus Ihrer MySQL-Datenbank abrufen kann. In der nächsten Einheit untersuchen Sie die Serverprotokolle.