Exercício – Implantar um aplicativo Java EE (Jakarta EE) na JBoss EAP no Serviço de Aplicativo do Azure
Neste exercício, você implantará um aplicativo Java EE (Jakarta EE) na JBoss EAP no Serviço de Aplicativo do Azure. Use o plug-in do Maven para configurar o projeto, compilar e implantar o aplicativo e configurar uma fonte de dados.
Configurar o aplicativo com o plug-in do Maven para o Serviço de Aplicativo do Azure
Iremos configurar nosso aplicativo executando a meta de configuração no plug-in do Maven para o Serviço de Aplicativo do Azure.
./mvnw com.microsoft.azure:azure-webapp-maven-plugin:2.9.0:config
Importante
Se você mudou a região do servidor MySQL, também deve mudar para a mesma região do servidor do aplicativo Java EE para minimizar os atrasos de latência.
No comando, selecione Java 11 para a versão Java e JBoss EAP 7 para a pilha de execução.
Elemento de entrada | Valor |
---|---|
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 |
Depois de executar o comando, você receberá mensagens como as seguintes no terminal:
$ ./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] ------------------------------------------------------------------------
$
Depois que o comando for concluído, você verá a seguinte entrada ser adicionada no arquivo pom.xml
do 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>
Importante
Verifique o elemento <region>
. Se não for a mesma localização de instalação que a do MySQL, altere-a para a mesma localização.
Depois de adicionar a configuração acima para a implantação no Azure, adicione as seguintes entradas XML para implantar o arquivo de inicialização. O recurso <type>startup</type>
implanta o script especificado como startup.sh
(Linux) ou startup.cmd
(Windows) em /home/site/scripts/
. Configuramos o script de inicialização na etapa a seguir.
<!-- 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 -->
Observação
Você pode especificar o recurso a seguir para implantar no XML:
type=<war|jar|ear|lib|startup|static|zip>
type=war
implantará o arquivo war em/home/site/wwwroot/app.war
sepath
não for especificadotype=war&path=webapps/<appname>\
se comportará exatamente como a implantação war descompactando o aplicativo para /home/site/wwwroot/webapps/<appname>type=jar
implantará o arquivo war em/home/site/wwwroot/app.jar
. O parâmetropath
será ignoradotype=ear
implantará o arquivo war em/home/site/wwwroot/app.ear
. O parâmetropath
será ignoradotype=lib
implantará jar em /home/site/libs. O parâmetropath
deve ser especificadotype=static
implantará o script em/home/site/scripts
. O parâmetropath
deve ser especificadotype=startup
implantará o script comostartup.sh
(Linux) oustartup.cmd
(Windows) em/home/site/scripts/
. O parâmetropath
será ignoradotype=zip
descompactará zip em/home/site/wwwroot
. O parâmetropath
é opcional.
Agora, verifique os valores do nome do grupo de recursos e do nome do aplicativo no arquivo XML acima. Anote esses nomes ou atribua-os a variáveis de ambiente.
<resourceGroup>jakartaee-app-on-jboss-1625038814881-rg</resourceGroup>
<appName>jakartaee-app-on-jboss-1625038814881</appName>
Se você está usando Bash, configure as variáveis de ambiente com o comando a seguir. Você usará esses valores mais tarde.
export RESOURCEGROUP_NAME=jakartaee-app-on-jboss-1625038814881-rg
export WEBAPP_NAME=jakartaee-app-on-jboss-1625038814881
Compilar e criar o aplicativo Java EE
Depois de definir as configurações de implantação do Serviço de Aplicativo do Azure, compile e empacote o código-fonte.
./mvnw clean package
A seguinte saída é exibida no terminal:
[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] ------------------------------------------------------------------------
Implantar o aplicativo Java EE na JBoss EAP no Serviço de Aplicativo do Azure
Depois de compilar e empacotar o código, implante o aplicativo:
./mvnw azure-webapp:deploy
A seguinte mensagem é exibida no terminal:
[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] ------------------------------------------------------------------------
Anote a URL do aplicativo implantado, especialmente a seguinte linha na saída do Maven:
[INFO] Successfully deployed the artifact to https://jakartaee-app-on-jboss-1625038814881.azurewebsites.net
Configurar uma conexão de banco de dados
O aplicativo de exemplo se conecta ao Banco de Dados MySQL e exibe os dados.
Na configuração do projeto do Maven no pom.xml
, especificamos o driver JDBC do MySQL da seguinte maneira:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-jdbc-driver}</version>
</dependency>
Como resultado, a JBoss EAP instala automaticamente o driver JDBC em seu pacote de implantação (ROOT.war
). Você pode consultar o nome do driver JDBC do MySQL da seguinte maneira:
ROOT.war_com.mysql.cj.jdbc.Driver_8_0
Criar um objeto DataSource MySQL na JBoss EAP
Para acessar o Banco de Dados do Azure para MySQL, você precisa configurar o objeto DataSource
na JBoss EAP e especificar o nome da JNDI em seu código-fonte.
Para criar um objeto DataSource
do MySQL na JBoss EAP, criamos o script do shell de inicialização a seguir. O arquivo de script é createMySQLDataSource.sh
no diretório /WEB-INF
.
Observação
No script, associamos o DataSource MySQL usando um comando da CLI do JBoss. A cadeia de conexão, o nome de usuário e a senha usam as variáveis de ambiente MYSQL_CONNECTION_URL
, MYSQL_USER
e MYSQL_PASSWORD
.
A origem do arquivo de script é mostrada em seguida. Esse arquivo de script já foi carregado no Serviço de Aplicativo, mas ainda não foi configurado para ser invocado.
#!/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
Agora, configure sua instância do Serviço de Aplicativo para invocar o script de inicialização:
az webapp config set --startup-file '/home/site/scripts/startup.sh' \
-n ${WEBAPP_NAME} \
-g ${RESOURCEGROUP_NAME}
Após a execução do script, ele será invocado toda vez que o servidor de aplicativos for reiniciado.
Observação
Se o seu artefato de implantação não for ROOT.war
, você precisará alterar o valor de --driver-name=YOUR_ARTIFACT.war_com.mysql.cj.jdbc.Driver_8_0
também.
Configurar as variáveis de ambiente para conexão ao MySQL
Depois de configurar o script de inicialização, configure o Serviço de Aplicativo para usar determinadas variáveis de ambiente:
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
Dica
Os valores de MYSQL_CONNECTION_URL
, MYSQL_USER
e MYSQL_PASSWORD
foram definidos usando a unidade anterior.
Confirmar a referência de DataSource no código
Para acessar o banco de dados MySQL do seu aplicativo, você precisa configurar a referência de fonte de dados em seu projeto de aplicativo. Implementamos o código de acesso de banco de dados usando a JPA (API de Persistência Java).
A configuração para a referência de DataSource
foi adicionada no persistence.xml
, que é o arquivo de configuração do JPA.
Acesse o seguinte arquivo:
├── src
│ ├── main
│ │ ├── resources
│ │ │ └── META-INF
│ │ │ └── persistence.xml
Verifique se o nome do DataSource
corresponde ao nome usado na configuração. O código já criou o nome JNDI como 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>
Em seguida, você pode acessar o banco de dados MySQL referenciado no nome da unidade PersistenceContext
da seguinte maneira:
@Transactional(REQUIRED)
@RequestScoped
public class CityService {
@PersistenceContext(unitName = "JPAWorldDatasourcePU")
EntityManager em;
Acessar o aplicativo
No aplicativo de exemplo, implementamos três pontos de extremidade REST. Você pode acessar o aplicativo e validar esses pontos de extremidade usando um navegador da Web ou um comando curl
.
Para acessar o aplicativo, você precisa fazer referência à URL do aplicativo, que você obteve em uma seção anterior:
[INFO] Successfully deployed the artifact to
https://jakartaee-app-on-jboss-1606464084546.azurewebsites.net
Execute o comando a seguir para obter todas as informações de continente no formato JSON.
$ curl https://${WEBAPP_NAME}.azurewebsites.net/area
["North America","Asia","Africa","Europe","South America","Oceania","Antarctica"]$
Se você especificar o continente na URL, poderá obter todos os países/todas as regiões do continente especificado.
$ 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"
}
....
Por fim, se você especificar um código de país/região após /countries
, poderá obter todas as cidades com uma população com mais um milhão dentro do país/da região.
$ 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"
Resumo do exercício
Você validou os pontos de extremidade REST do aplicativo e testou se seu aplicativo pode obter dados do banco de dados MySQL.
Na próxima unidade, você examinará os logs do servidor.