Ćwiczenie — wdrażanie aplikacji Java EE (Jakarta EE) w usłudze JBoss EAP w usłudze aplikacja systemu Azure

Ukończone

W tym ćwiczeniu wdrożysz aplikację Java EE (Jakarta EE) w aplikacji JBoss EAP w usłudze aplikacja systemu Azure Service. Wtyczka Maven służy do konfigurowania projektu, kompilowania i wdrażania aplikacji oraz konfigurowania źródła danych.

Konfigurowanie aplikacji za pomocą wtyczki Maven dla usługi aplikacja systemu Azure

Skonfigurujmy aplikację, wykonując cel konfiguracji w wtyczki Maven dla usługi aplikacja systemu Azure Service.

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

Ważne

Jeśli zmienisz region serwera MySQL, należy również zmienić go na ten sam region dla serwera aplikacji Java EE, aby zminimalizować opóźnienia.
W poleceniu wybierz pozycję Java 11 dla języka Java w wersji i Stos środowiska uruchomieniowego JBoss EAP 7.

Element wejściowy Wartość
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

Po uruchomieniu polecenia w terminalu będą wyświetlane komunikaty podobne do następujących:

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

Po zakończeniu polecenia zobaczysz, że w pliku Maven pom.xml zostanie dodany następujący wpis.

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

Ważne

<region> Sprawdź element. Jeśli nie jest to ta sama lokalizacja instalacji co MySQL, zmień ją na tę samą lokalizację.

Po dodaniu powyższej konfiguracji do wdrożenia na platformie Azure dodaj następujące wpisy XML, aby wdrożyć plik startowy. Zasób <type>startup</type> wdraża określony skrypt jako startup.sh (Linux) lub startup.cmd (Windows) w systemie /home/site/scripts/. W poniższym kroku skonfigurujemy skrypt uruchamiania.

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

Uwaga

Możesz określić następujący zasób do wdrożenia w pliku XML:

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

    • type=warprogram wdroży plik wojny, /home/site/wwwroot/app.war jeśli path nie zostanie określony
    • type=war&path=webapps/<appname>\ będzie zachowywać się dokładnie tak jak wardeploy przez rozpakowywanie aplikacji do /home/site/wwwroot/webapps/<appname>
    • type=jar wdroży plik wojny w pliku /home/site/wwwroot/app.jar. path Parametr zostanie zignorowany
    • type=ear wdroży plik wojny w pliku /home/site/wwwroot/app.ear. path Parametr zostanie zignorowany
    • type=lib spowoduje wdrożenie pliku jar w folderze /home/site/libs. path Należy określić parametr
    • type=static spowoduje wdrożenie skryptu w pliku /home/site/scripts. path parametr musi zostać określony
    • type=startup spowoduje wdrożenie skryptu jako startup.sh (Linux) lub startup.cmd (Windows) w systemie /home/site/scripts/. path Parametr zostanie zignorowany
    • type=zip rozpakuj plik zip do /home/site/wwwrootpliku . path parametr jest opcjonalny.

Teraz sprawdź wartości nazwy grupy zasobów i nazwy aplikacji z powyższego pliku XML. Zanotuj te nazwy lub lepiej przypisz je do zmiennych środowiskowych.

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

Jeśli używasz powłoki Bash, skonfiguruj zmienne środowiskowe za pomocą następującego polecenia. Użyjesz tych wartości później.

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

Kompilowanie i kompilowanie aplikacji Java EE

Po skonfigurowaniu ustawień wdrażania usługi aplikacja systemu Azure skompiluj i spakuj kod źródłowy.

./mvnw clean package

Następujące dane wyjściowe są wyświetlane w terminalu:

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

Wdrażanie aplikacji Java EE w aplikacji JBoss EAP w usłudze aplikacja systemu Azure

Po skompilowaniu i spakowaniu kodu wdróż aplikację:

./mvnw azure-webapp:deploy

W terminalu zostanie wyświetlony następujący komunikat:

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

Zanotuj adres URL wdrożonej aplikacji, szczególnie następujący wiersz w danych wyjściowych narzędzia Maven:

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

Konfigurowanie połączenia z bazą danych

Przykładowa aplikacja łączy się z bazą danych MySQL i wyświetla dane.

W konfiguracji projektu Maven w systemie pom.xmlokreślono sterownik MySQL JDBC w następujący sposób:

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

W rezultacie narzędzie JBoss EAP automatycznie instaluje sterownik JDBC do pakietu wdrożeniowego (ROOT.war). Możesz odwołać się do nazwy sterownika JDBC mySQL w następujący sposób:

ROOT.war_com.mysql.cj.jdbc.Driver_8_0

Tworzenie obiektu MySQL DataSource w aplikacji JBoss EAP

Aby uzyskać dostęp do usługi Azure Database for MySQL, należy skonfigurować DataSource obiekt w aplikacji JBoss EAP i określić nazwę JNDI w kodzie źródłowym.

Aby utworzyć obiekt MySQL DataSource w aplikacji JBoss EAP, utworzyliśmy następujący skrypt powłoki uruchamiania. Plik skryptu znajduje się createMySQLDataSource.sh w /WEB-INF katalogu .

Uwaga

W skrypcie powiążemy źródło danych MySQL przy użyciu polecenia interfejsu wiersza polecenia JBoss. Parametry połączenia, nazwa użytkownika i hasło używają zmiennych środowiskowych MYSQL_CONNECTION_URL, MYSQL_USERi MYSQL_PASSWORD.

Źródło pliku skryptu jest wyświetlane w następnej kolejności. Ten plik skryptu został już przekazany do usługi App Service, ale nie został jeszcze skonfigurowany do wywołania.

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

Teraz skonfiguruj wystąpienie usługi App Service w celu wywołania skryptu uruchamiania:

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

Po uruchomieniu skryptu będzie on wywoływany za każdym razem, gdy serwer aplikacji zostanie ponownie uruchomiony.

Uwaga

Jeśli artefakt wdrożenia nie ROOT.warjest , musisz również zmienić --driver-name=YOUR_ARTIFACT.war_com.mysql.cj.jdbc.Driver_8_0 wartość.

Konfigurowanie zmiennych środowiskowych na potrzeby nawiązywania połączenia z bazą danych MySQL

Po skonfigurowaniu skryptu uruchamiania skonfiguruj usługę App Service tak, aby korzystała z określonych zmiennych środowiskowych:

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

Napiwek

Wartości MYSQL_CONNECTION_URLi MYSQL_USER MYSQL_PASSWORD zostały ustawione z poprzedniej lekcji.

Potwierdzanie odwołania do źródła danych w kodzie

Aby uzyskać dostęp do bazy danych MySQL z poziomu aplikacji, należy skonfigurować odwołanie do źródła danych w projekcie aplikacji. Zaimplementowaliśmy kod dostępu do bazy danych przy użyciu interfejsu API trwałości języka Java (JPA).

Konfiguracja odwołania DataSource została dodana w persistence.xmlpliku , który jest plikiem konfiguracji JPA.

Uzyskaj dostęp do następującego pliku:

├── src
│   ├── main
│   │   ├── resources
│   │   │   └── META-INF
│   │   │       └── persistence.xml

Sprawdź, czy nazwa jest zgodna DataSource z nazwą używaną w konfiguracji. Kod utworzył już nazwę JNDI jako 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>

Następnie możesz uzyskać dostęp do bazy danych MySQL, do której odwołuje się nazwa lekcji w PersistenceContext następujący sposób:

@Transactional(REQUIRED)
@RequestScoped
public class CityService {

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

Uzyskiwanie dostępu do aplikacji

W przykładowej aplikacji zaimplementowaliśmy trzy punkty końcowe REST. Dostęp do aplikacji i weryfikowanie tych punktów końcowych można uzyskać za pomocą przeglądarki internetowej lub curl polecenia.

Aby uzyskać dostęp do aplikacji, musisz odwołać się do adresu URL aplikacji, który został uzyskany z wcześniejszej sekcji:

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

Uruchom następujące polecenie, aby uzyskać wszystkie informacje o kontynencie w formacie 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"]$ 

Jeśli określisz kontynent w adresie URL, możesz pobrać wszystkie kraje/regiony na określonym kontynencie.

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"
}
....

Na koniec, jeśli określisz kod kraju/regionu po /countries, możesz pobrać wszystkie miasta, które mają populację większą niż 1 milion w kraju/regionie.

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"

Podsumowanie ćwiczeń

Sprawdzono teraz punkty końcowe REST aplikacji i przetestowano, czy aplikacja może pobierać dane z bazy danych MySQL.

W następnej lekcji zapoznasz się z dziennikami serwera.