Ćwiczenie — wdrażanie aplikacji Java EE (Jakarta EE) w aplikacji JBoss EAP w usłudze Azure App Service
W tym ćwiczeniu wdrożysz aplikację Java EE (Jakarta EE) w aplikacji JBoss EAP w usłudze Azure App 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 Azure App Service
Skonfigurujmy aplikację, wykonując cel konfiguracji w wtyczce Maven dla usługi Azure App Service.
./mvnw com.microsoft.azure:azure-webapp-maven-plugin:2.9.0:config
Ważny
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 Java 11 jako wersję Java 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 następujący wpis zostanie dodany w pliku pom.xml
narzędzia 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>
Ważny
Sprawdź element <region>
. 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 /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 -->
Notatka
Możesz określić następujący zasób do wdrożenia w pliku XML:
type=<war|jar|ear|lib|startup|static|zip>
-
type=war
wdroży plik WAR do/home/site/wwwroot/app.war
, jeślipath
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/<nazwa aplikacji> -
type=jar
wdroży plik wojenny w/home/site/wwwroot/app.jar
.path
parametr zostanie zignorowany -
type=ear
wdroży plik wojenny w/home/site/wwwroot/app.ear
.path
parametr zostanie zignorowany -
type=lib
wdroży plik jar w katalogu /home/site/libs. Parametrpath
musi być określony -
type=static
wdroży skrypt w/home/site/scripts
.path
parametr musi zostać określony -
type=startup
wdroży skrypt jakostartup.sh
(Linux) lubstartup.cmd
(Windows) w/home/site/scripts/
.path
parametr zostanie zignorowany -
type=zip
rozpakowuje plik zip do/home/site/wwwroot
. parametrpath
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 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 budowanie aplikacji Java EE
Po skonfigurowaniu ustawień wdrażania usługi Azure App Service 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 Azure App Service
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 pom.xml
okreś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 związku z tym 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ć obiekt DataSource
w aplikacji JBoss EAP i określić nazwę JNDI w kodzie źródłowym.
Aby utworzyć obiekt DataSource
MySQL w JBoss EAP, utworzyliśmy następujący skrypt startowy. Plik skryptu createMySQLDataSource.sh
znajduje się w katalogu /WEB-INF
.
Notatka
W skrypcie wiążemy źródło danych MySQL za pomocą komendy JBoss CLI. Parametry połączenia, nazwa użytkownika i hasło używają zmiennych środowiskowych MYSQL_CONNECTION_URL
, MYSQL_USER
i 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.
Notatka
Jeśli artefakt wdrożenia nie jest ROOT.war
, musisz również zmienić wartość --driver-name=YOUR_ARTIFACT.war_com.mysql.cj.jdbc.Driver_8_0
.
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_URL
, MYSQL_USER
i MYSQL_PASSWORD
zostały ustawione z poprzedniej jednostki.
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 wprowadzona w pliku persistence.xml
, który jest plikiem konfiguracji JPA.
Uzyskaj dostęp do następującego pliku:
├── src
│ ├── main
│ │ ├── resources
│ │ │ └── META-INF
│ │ │ └── persistence.xml
Sprawdź, czy nazwa DataSource
jest zgodna 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 jednostki PersistenceContext
w 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. Możesz uzyskać dostęp do aplikacji i zweryfikować te punkty końcowe przy użyciu przeglądarki internetowej lub polecenia curl
.
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.
$ 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.
$ 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 po /countries
określisz kod kraju/regionu, możesz uzyskać wszystkie miasta, które mają populację większą niż 1 milion w kraju/regionie.
$ 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 ćwiczenia
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.