Criando projeto Maven com profiles distintos de dependências

No trabalho tivemos um problema com a GraalVM, e devido a isso essa issue foi criada.

Eu falei com o autor e pensei “será que não seria melhor criar um projeto maven com isso bonitinho? Subir um repo, MCVE, que você controla através de profiles as dep…


This content originally appeared on DEV Community and was authored by Jefferson Quesado

No trabalho tivemos um problema com a GraalVM, e devido a isso essa issue foi criada.

Eu falei com o autor e pensei "será que não seria melhor criar um projeto maven com isso bonitinho? Subir um repo, MCVE, que você controla através de profiles as dependências?"

E cá está o repo! github.com/jeffque/graalvm-regression

Pois bem, aproveitar que vou fazer isso e compartilhar um pouco o processo.

Iniciando um projeto maven

Para começar, eu gosto de iniciar o projeto maven colocar o mvnw (maven wrapper). Eu normalmente começo copiando o mvnw de um outro repositório meu conhecido, mas posso fazer isso de modo mais canônico. Como por exemplo, seguindo esse tutorial do Baeldung:

$ mvn -N wrapper:wrapper

Ficou assim o diretório:

.
├── .mvn
│   └── wrapper
│       └── maven-wrapper.properties
├── mvnw
└── mvnw.cmd

Qual a versão do maven que ele usa? Podemos perguntar diretamente ao mvwn ou então consultar em .mvn/wrapper/maven-wrapper.properties. No caso, o conteúdo do arquivo é:

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip

Muito bem, maven na versão 3.9.9, uma delícia.

Criando o projeto base

Existem diversas maneiras de iniciar um projeto maven. Inclusive a de você
o pom.xml totalmente do zero. Mas... um modo mais canônico seria pedir um
arquétipo, que nem eu fiz em "Hello, World!" em GWT usando arquétipo do TBroyer.

Então, vamos pedir o arquétipo vazio? Normalmente eu peço o maven-archetype-quickstart. Tem uma lista não exaustiva de arquétipos aqui.

./mvnw archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.5

Após baixar as dependências necessárias para rodar o arquétipo ele me pergunta:

  • Define value for property 'groupId'
    • com.jeffque
  • Define value for property 'artifactId'
    • graalvm-24-1-2-regression
  • Define value for property 'version' 1.0-SNPASHOT
    • <enter> (o que é equivalente a usar o default, que no caso é 1.0-SNAPSHOT)
  • Define value for property 'package' com.jeffque:
    • <enter> (o que é equivalente a usar o default, que no caso é com.jeffque)

Após responder, ele pede para confirmar:

Define value for property 'package' com.jeffque: 
Confirm properties configuration:
javaCompilerVersion: 17
junitVersion: 5.11.0
groupId: com.jeffque
artifactId: graalvm-24-1-2-regression
version: 1.0-SNAPSHOT
package: com.jeffque
 Y:

Confimei e... puff!

.
├── .mvn
│   └── wrapper
│       └── maven-wrapper.properties
├── graalvm-24-1-2-regression
│   ├── .mvn
│   │   ├── jvm.config
│   │   └── maven.config
│   ├── pom.xml
│   └── src
│       ├── main
│       │   └── java
│       │       └── com
│       │           └── jeffque
│       │               └── App.java
│       └── test
│           └── java
│               └── com
│                   └── jeffque
│                       └── AppTest.java
├── mvnw
└── mvnw.cmd

Gerei no canto errado? Ok, só mover uma pasta pra lá

←\leftarrow

.

cd graalvm-24-1-2-regression
mv pom.xml src ../
mv .mvn/* ../.mvn
rmdir .mvn
cd ..
rmdir graalvm-24-1-2-regression

Ok, ajeitado:

.
├── .mvn
│   ├── jvm.config
│   ├── maven.config
│   └── wrapper
│       └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
    ├── main
    │   └── java
    │       └── com
    │           └── jeffque
    │               └── App.java
    └── test
        └── java
            └── com
                └── jeffque
                    └── AppTest.java

Adicionando comando de execução

Eu quero facilitar a vida de quem vai testar usando Maven. Para tal, vou configurar o plugin exec. O plugin é esse: exec-maven-plugin.

Na linha de comando:

> ./mvnw exec:java -Dexec.mainClass="com.jeffque.App"
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------< com.jeffque:graalvm-24-1-2-regression >----------------
[INFO] Building graalvm-24-1-2-regression 1.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- exec:3.5.0:java (default-cli) @ graalvm-24-1-2-regression ---
Hello World!
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.383 s
[INFO] Finished at: 2025-01-31T08:02:13-03:00
[INFO] ------------------------------------------------------------------------

Beleza, vamos por no pom? Em pluginManagement a gente indica commo o plugin vai ser executado ao ser chamado, não necessariamente ele será chamado. Então, se eu adicionar o exec-maven-plugin lá, o maven não tentará fazer o fetch desse plugin a priori. Já em build.plugins... aí a gente está indicando que o plugin será de fato executado.

Aí vem a questão: quando usar algo em build.plugins? Quando precisamos que o plugin seja executado e não tem implícito em algum lugar isso. Como por exemplo, chamar o retrolambda para permitir usar a sintaxe de lambdas e conseguir dar um target para java 7.

Ok, vamos adicionar as configurações do plugin em pluginManagement? Primeiramente, vamos colocar o plugin lá:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>3.5.0</version>
</plugin>

Ok, prendemos a versão. Agora, vamos para o como vai ser chamado. No caso, quando for chamado o mojo exec:java: exec identifica esse plugin e java o goal específico:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>3.5.0</version>
    <executions>
        <execution>
            <goals>
                <goal>java</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Ok, agora, vamos por a configuração da classe principal:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>3.5.0</version>
    <executions>...</executions>
    <configuration>
        <mainClass>com.jeffque.App</mainClass>
    </configuration>
</plugin>

Plugin configurado! Será?

> ./mvnw exec:java
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------< com.jeffque:graalvm-24-1-2-regression >----------------
[INFO] Building graalvm-24-1-2-regression 1.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- exec:3.5.0:java (default-cli) @ graalvm-24-1-2-regression ---
Hello World!
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.341 s
[INFO] Finished at: 2025-01-31T08:28:48-03:00
[INFO] ------------------------------------------------------------------------

Adaptando ao problema da issue

Vamos colocar as coisas da issue do GitHub. Primeiramente, para a versão problemática do GraalVM. Vamos alterar a main para refletir como está na issue.

Adicionar as dependências e alterar a main foi uma non-issue, bem direto ao ponto. Para testar, coloquei as dependências para a versão do GraalVM com problema e mandei executar:

> ./mvnw compile exec:java
...
org.graalvm.polyglot.PolyglotException: TypeError: k.equals is not a function
    at <js>.:=> (Unnamed:6)
    at com.oracle.truffle.polyglot.PolyglotFunctionProxyHandler.invoke (PolyglotFunctionProxyHandler.java:151)
...

Perfeito! Tal qual aparece na issue!

Profiles

Vou criar perfis distintos. E neles vou colocar as dependências. Você pode ler mais na documentação oficial.

Vou criar dois perfis:

  • graalvm-24, apresenta o problema
  • graalvm-20, não apresenta o problema
<profiles>
    <profile>
        <id>graalvm-24</id>
    </profile>
    <profile>
        <id>graalvm-24</id>
    </profile>
</profiles>

Ok. Agora, vou deixar o perfil graalvm-24 ativo por default. Se ninguém falar nada, ele que será invocado:

<profile>
    <id>graalvm-24</id>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>
</profile>

Como invocar esse perfil? Passando a opção -P na linha de comando!

Por exemplo:

./mvnw exec:java -Pgraalvm-24

Estou explicitando que quero o perfil graalvm-24. De modo semelhante:

./mvnw exec:java -Pgraalvm-20

Para o perfil graalvm-20. Eu poderia passar múltiplos perfis também:

./mvnw exec:java -Pgraalvm-20,jeff,marmota

Isso ativa os perfis graalvm-20, jeff e marmota. E no caso o activateByDefault, funciona como? Bem, se você não falar nada...

./mvnw exec:java
# note que não tem -P

Aí só ativa o que tá cadastrado pra rodar por padrão.

Muito bem, agora eu coloco as dependências:

<profiles>
    <profile>
        <id>graalvm-24</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <dependencies>
            <dependency>
                <groupId>org.graalvm.polyglot</groupId>
                <artifactId>polyglot</artifactId>
                <version>24.1.2</version>
            </dependency>
            <dependency>
                <groupId>org.graalvm.polyglot</groupId>
                <artifactId>js-community</artifactId>
                <version>24.1.2</version>
                <type>pom</type>
                <scope>runtime</scope>
            </dependency>
        </dependencies>
    </profile>
    <profile>
        <id>graalvm-20</id>
        <dependencies>
            <dependency>
                <groupId>org.graalvm.sdk</groupId>
                <artifactId>graal-sdk</artifactId>
                <version>20.1.0</version>
            </dependency>
            <dependency>
                <groupId>org.graalvm.js</groupId>
                <artifactId>js</artifactId>
                <version>20.1.0</version>
            </dependency>
        </dependencies>
    </profile>
</profiles>

E pronto, agora tenho dois perfis distintos! Note que o graalvm foi removido do project.dependencies, pois essas dependências sem perfil afetam a todos.

Para testar:

> ./mvnw exec:java
...
org.graalvm.polyglot.PolyglotException: TypeError: k.equals is not a function
    at <js>.:=> (Unnamed:6)
...

> ./mvnw exec:java -P graalvm-20
...
[INFO] --- exec:3.5.0:java (default-cli) @ graalvm-24-1-2-regression ---
Optional[true]
[INFO] ------------------------------------------------------------------------
...


This content originally appeared on DEV Community and was authored by Jefferson Quesado


Print Share Comment Cite Upload Translate Updates
APA

Jefferson Quesado | Sciencx (2025-01-31T16:05:52+00:00) Criando projeto Maven com profiles distintos de dependências. Retrieved from https://www.scien.cx/2025/01/31/criando-projeto-maven-com-profiles-distintos-de-dependencias/

MLA
" » Criando projeto Maven com profiles distintos de dependências." Jefferson Quesado | Sciencx - Friday January 31, 2025, https://www.scien.cx/2025/01/31/criando-projeto-maven-com-profiles-distintos-de-dependencias/
HARVARD
Jefferson Quesado | Sciencx Friday January 31, 2025 » Criando projeto Maven com profiles distintos de dependências., viewed ,<https://www.scien.cx/2025/01/31/criando-projeto-maven-com-profiles-distintos-de-dependencias/>
VANCOUVER
Jefferson Quesado | Sciencx - » Criando projeto Maven com profiles distintos de dependências. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/01/31/criando-projeto-maven-com-profiles-distintos-de-dependencias/
CHICAGO
" » Criando projeto Maven com profiles distintos de dependências." Jefferson Quesado | Sciencx - Accessed . https://www.scien.cx/2025/01/31/criando-projeto-maven-com-profiles-distintos-de-dependencias/
IEEE
" » Criando projeto Maven com profiles distintos de dependências." Jefferson Quesado | Sciencx [Online]. Available: https://www.scien.cx/2025/01/31/criando-projeto-maven-com-profiles-distintos-de-dependencias/. [Accessed: ]
rf:citation
» Criando projeto Maven com profiles distintos de dependências | Jefferson Quesado | Sciencx | https://www.scien.cx/2025/01/31/criando-projeto-maven-com-profiles-distintos-de-dependencias/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.