Exercício - Implantar um aplicativo Jakarta EE no JBoss EAP no Serviço de Aplicativo do Azure
Nesta unidade, você implanta um aplicativo Jakarta EE no Red Hat JBoss Enterprise Application Platform (JBoss EAP) no Serviço de Aplicativo do Azure. Use o plug-in Maven para o Serviço de Aplicativo do Azure para configurar o projeto, compilar e implantar o aplicativo e configurar uma fonte de dados.
Configurar o aplicativo
Configure o aplicativo com o plug-in Maven para o Serviço de Aplicativo do Azure usando as seguintes etapas:
Execute a meta de configuração do plug-in do Azure interativamente usando o seguinte comando:
./mvnw com.microsoft.azure:azure-webapp-maven-plugin:2.13.0:configImportante
Se você alterar a região do seu servidor MySQL, você deve corresponder essa região à região do seu servidor de aplicativos Jakarta EE para minimizar os atrasos de latência.
Use os valores na tabela a seguir para responder aos prompts interativos:
Elemento de entrada Valor Create new run configuration (Y/N) [Y]:YDefine value for OS [Linux]:LinuxDefine value for javaVersion [Java 17]:1: Java 17Define value for runtimeStack:3: Jbosseap 7Define value for pricingTier [P1v3]:P1v3Confirm (Y/N) [Y]:YA seguinte saída é típica:
[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] ------------------------------------------------------------------------Depois de usar o comando Maven, o exemplo a seguir é uma adição típica ao seu arquivo 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>Verifique o elemento
<region>no seu ficheiro pom.xml. Se o seu valor não corresponder ao local de instalação do MySQL, altere-o para o mesmo local.Use o exemplo a seguir para modificar o
webContainervalor em seu arquivo pom.xml paraJbosseap 8, para o ambiente JBoss EAP 8 no Serviço de Aplicativo do Azure:Dica
A partir de fevereiro de 2025, a última versão disponível do JBoss EAP é a 8.0 Update 4.1.
<runtime> <os>Linux</os> <javaVersion>Java 17</javaVersion> <webContainer>Jbosseap 8</webContainer> <!-- Change this value --> </runtime>Adicione o seguinte XML ao
<resources>elemento do seu arquivo pom.xml . Essa configuração é usada para implantar o arquivo de inicialização, que você atualiza posteriormente nesta unidade.<resource> <type>startup</type> <directory>${project.basedir}/src/main/webapp/WEB-INF/</directory> <includes> <include>createMySQLDataSource.sh</include> </includes> </resource>O valor de recurso
<type>implanta o script especificado como o arquivostartupstartup.sh para Linux ou startup.cmd para Windows. O local de implantação é /home/site/scripts/.Observação
Você pode escolher a opção de implantação e o local de implantação especificando
typede uma das seguintes maneiras:-
type=warimplanta o arquivo WAR em /home/site/wwwroot/app.war sepathnão for especificado. -
type=war&path=webapps/<appname>implanta o arquivo WAR em /home/site/wwwroot/webapps/<appname>. -
type=jarimplanta o arquivo WAR em /home/site/wwwroot/app.jar. O parâmetropathé ignorado. -
type=earimplanta o arquivo WAR em /home/site/wwwroot/app.ear. O parâmetropathé ignorado. -
type=libimplanta o JAR em /home/site/libs. Você deve especificarpathparâmetro. -
type=staticimplanta o script em /home/site/scripts. Você deve especificar opathparâmetro. -
type=startupimplanta o script como startup.sh no Linux ou startup.cmd no Windows. O script é implantado em /home/site/scripts/. O parâmetropathé ignorado. -
type=zipDescompacta o arquivo .zip para /home/site/wwwroot. Opathparâmetro é opcional.
-
Verifique os valores para os elementos
resourceGroupeappNameno seu arquivo pom.xml.Atribua os valores para
resourceGroupeappNamepara variáveis de ambiente usando os seguintes comandos:export RESOURCE_GROUP_NAME=<resource-group> export WEB_APP_NAME=<app-name>
Compilar e construir o aplicativo Jakarta EE
Depois de definir as configurações de implantação do Serviço de Aplicativo do Azure, compile e empacote o código-fonte usando o seguinte comando:
./mvnw clean package
A seguinte saída é típica:
[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] ------------------------------------------------------------------------
Implantar o aplicativo Jakarta EE no JBoss EAP no Serviço de Aplicativo do Azure
Depois de compilar e empacotar o código, implante o aplicativo usando o seguinte comando:
./mvnw azure-webapp:deploy
Você deve ver a saída que inclui uma mensagem de êxito e a URL do aplicativo implantado. Certifique-se de salvar o URL para uso posterior.
Configurar uma conexão de banco de dados
O aplicativo de exemplo se conecta ao seu banco de dados MySQL e exibe dados. A configuração do projeto Maven no arquivo pom.xml especifica o driver JDBC MySQL, conforme mostrado no exemplo a seguir:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-jdbc-driver}</version>
</dependency>
Como resultado, o JBoss EAP instala automaticamente o driver ROOT.war_com.mysql.cj.jdbc.Driver_9_2 JDBC no seu pacote de implementação ROOT.war.
Criar o objeto MySQL DataSource no JBoss EAP
Para acessar o Banco de Dados do Azure para MySQL, você precisa configurar o DataSource objeto no JBoss EAP e especificar o nome JNDI (Java Naming and Directory Interface) em seu código-fonte. Para criar um objeto MySQL DataSource no JBoss EAP, use o script de shell de inicialização /WEB-INF/createMySQLDataSource.sh . O exemplo a seguir mostra uma versão não configurada do script já no Serviço de Aplicativo do Azure:
#!/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
Observação
Quando você cria a fonte de dados, você não especifica uma senha para a conexão MySQL. A variável AZURE_MYSQL_CONNECTIONSTRING de ambiente é especificada no --connection-url parâmetro. Essa variável de ambiente é definida automaticamente quando a conexão de serviço é criada posteriormente.
O valor da conexão de serviço é definido como jdbc:mysql://$MYSQL_SERVER_INSTANCE.mysql.database.azure.com:3306/world?serverTimezone=UTC&sslmode=required&user=aad_jbossapp, que utiliza o nome de utilizador aad_jbossapp sem uma palavra-passe.
Ao anexar &authenticationPlugins=com.azure.identity.extensions.jdbc.mysql.AzureMysqlAuthenticationPlugin a essa URL, a autenticação do Microsoft Entra ID é habilitada para o aad_jbossapp usuário.
Configure sua instância do Serviço de Aplicativo para invocar o script de inicialização usando o seguinte comando:
az webapp config set \
--resource-group ${RESOURCE_GROUP_NAME} \
--name ${WEB_APP_NAME} \
--startup-file '/home/site/scripts/startup.sh'
Depois que o script é executado, o servidor de aplicativos o invoca sempre que o servidor de aplicativos é reiniciado.
Observação
Se o artefato de implantação não for ROOT.war, altere também o valor --driver-name=YOUR_ARTIFACT.war_com.mysql.cj.jdbc.Driver_9_2.
Configurar a conexão de serviço para o servidor flexível MySQL
Depois de configurar o script de inicialização, configure o Serviço de Aplicativo para usar o Service Connector para a conexão de servidor flexível do MySQL usando as seguintes etapas:
Defina variáveis de ambiente usando os seguintes comandos:
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)As variáveis de ambiente são usadas para os seguintes fins:
-
PASSWORDLESS_USER_NAME_SUFFIXé o sufixo para o nome de usuário usado para se conectar ao servidor flexível MySQL. O nome de usuário criado tem o prefixoaad_seguido pelo sufixo especificado. -
SOURCE_WEB_APP_IDé a ID da instância do Serviço de Aplicativo do Azure usada para se conectar ao servidor flexível MySQL. -
MYSQL_IDé o ID do servidor flexível MySQL. -
TARGET_MYSQL_IDespecifica o nome da base de dados como$MYSQL_ID/databases/worldpara estabelecer uma ligação com um utilizador que tem permissão para aceder à base de dadosworld. -
MANAGED_IDé a identidade gerenciada usada para se conectar ao servidor flexível MySQL.
-
Adicione a extensão para
serviceconnector-passwordlesse crie a conexão de serviço usando os seguintes comandos: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_IDObservação
Se você receber uma mensagem de erro como
Resource '********-****-****-****-************' does not exist or one of its queried reference-property objects are not present., execute novamente o comando após alguns segundos.No prompt SQL, verifique a lista de usuários registrados no MySQL usando a seguinte consulta:
SELECT user, host, plugin FROM mysql.user;A seguinte saída é típica:
+----------------------------------+-----------+-----------------------+ | 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)Você deve ver um
aad_jbossappusuário que usa oaad_authplugin. A partir do JBoss EAP implantado no Azure, você pode se conectar ao servidor flexível MySQL usando oaad_jbossappnome de usuário sem uma senha.
Confirme a referência DataSource no código
Para acessar o banco de dados MySQL de seu aplicativo, você precisa configurar a referência da fonte de dados em seu projeto de aplicativo.
O código de acesso ao banco de dados é implementado usando a Java Persistence API (JPA). A configuração para a DataSource referência está no arquivo de configuração JPA persistence.xml.
Use as seguintes etapas para confirmar a DataSource referência:
Abra o ficheiro src/main/resources/META-INF/persistence.xml e verifique se o nome
DataSourcecorresponde ao nome usado na configuração. O script de inicialização já criou o nome JNDI comojava:jboss/datasources/JPAWorldDataSource, conforme mostrado no exemplo a seguir:<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>Acesse o banco de dados MySQL no nome da unidade,
PersistenceContextconforme mostrado no exemplo a seguir:@Transactional(REQUIRED) @RequestScoped public class CityService { @PersistenceContext(unitName = "JPAWorldDatasourcePU") EntityManager em;
Aceda à aplicação
O aplicativo de exemplo implementa três pontos de extremidade REST. Para acessar o aplicativo e recuperar dados, use as seguintes etapas:
Use seu navegador para navegar até a URL do aplicativo, que foi mostrada na saída quando você implantou o aplicativo.
Para obter todas as informações do continente no formato JSON, use o método
GETno endpointarea.Para obter todos os países e regiões em um continente especificado, use o método
GETno endpointareae especifique um path parametercontinent.Para obter todas as cidades que têm uma população superior a um milhão no país ou região especificado, utilize o método
GETno ponto de extremidadecountriese especifique um parâmetro de caminhocountrycode.
Resumo do exercício
Nesta unidade, você validou os endpoints REST do aplicativo e confirmou que seu aplicativo pode obter dados do seu banco de dados MySQL. Na próxima unidade, você examina os logs do servidor.