Maven Poliglota
1. Visão geral
Maven Polyglot é um conjunto de extensões de núcleo Maven que permite que o modelo POM seja escrito em qualquer linguagem. Isso inclui muitos scripts e linguagens de marcação que não XML.
O principal objetivo do poliglota Maven é escapar do XML, já que não é mais a linguagem utilizada atualmente.
Neste tutorial, começaremos primeiro entendendo o conceito de extensão principal do Maven e o projeto Maven Polyglot.
Em seguida, mostraremos como escrever uma extensão de núcleo Maven que permite que o modelo POM seja construído a partir de um arquivo JSON em vez do famosopom.xml.
2. Mecanismo de carregamento da extensão do núcleo Maven
The Maven core extensions are plugins loaded at Maven initializatione antes do início da construção do projeto Maven. Esses plugins permitem alterar o comportamento do Maven sem alterar o núcleo.
Por exemplo, um plug-in carregado na inicialização pode substituir o comportamento padrão do Maven e pode ler o modelo POM de outro arquivo diferente depom.xml.
Tecnicamente,a Maven core extension is a Maven artifact declared in an extensions.xml file:
${projectDirectory}/.mvn/extensions.xml
Aqui está um exemplo de extensão:
com.example.maven.polyglot
maven-polyglot-json-extension
1.0-SNAPSHOT
Finalmente, precisamos observar quethis mechanism requires Maven 3.3.1 or higher.
3. Maven Poliglota
Maven Polyglot is a collection of core extensions. Cada um deles é responsável pela leitura do modelo POM a partir de um script ou linguagem de marcação.
O Maven Polyglot fornece extensões para os seguintes idiomas:
+-----------+-------------------+--------------------------------------+
| Language | Artifact Id | Accepted POM files |
+-----------+-------------------+--------------------------------------+
| Atom | polyglot-atom | pom.atom |
| Clojure | polyglot-clojure | pom.clj |
| Groovy | polyglot-groovy | pom.groovy, pom.gy |
| Java | polyglot-java | pom.java |
| Kotlin | polyglot-kotlin | pom.kts |
| Ruby | polyglot-ruby | pom.rb, Mavenfile, Jarfile, Gemfile |
| Scala | polyglot-scala | pom.scala |
| XML | polyglot-xml | pom.xml |
| YAML | polyglot-yaml | pom.yaml, pom.yml |
+-----------+-------------------+--------------------------------------+
Nas próximas seções, primeiro daremos uma olhada na construção de um projeto Maven usando uma das linguagens suportadas acima.
Em seguida, escreveremos nossa extensão para oferecer suporte a um POM baseado em JSON.
4. Usando uma extensão poliglota Maven
Uma opção para construir um projeto Maven com base em um idioma diferente do XML é usar um dos artefatos fornecidos pelo projeto Polyglot.
Em nosso exemplo,we’ll create a Maven project with a pom.yaml configuration file.
A primeira etapa é criar o arquivo de extensão principal do Maven:
${projectDirectory}/.mvn/extensions.xml
Em seguida, adicionaremos o seguinte conteúdo:
io.takari.polyglot
polyglot-yaml
0.3.1
Sinta-se à vontade para ajustar oartifactId ao idioma escolhido de acordo com os idiomas acima e verificar se algumnew version está disponível.
A última etapa é fornecer os metadados do projeto no arquivoYAML:
modelVersion: 4.0.0
groupId: com.example.maven.polyglot
artifactId: maven-polyglot-yml-app
version: 1.0-SNAPSHOT
name: 'YAML Demo'
properties: {maven.compiler.source: 1.8, maven.compiler.target: 1.8}
Agora podemos executar nossa compilação como costumamos fazer. Por exemplo, podemos chamar o comando:
mvn clean install
5. Usando o plug-in Polyglot Translate
Outra opção para obter um projeto baseado em uma das linguagens suportadas é usar opolyglot-translate-plugin.
Isso significa que podemos começar a partir de um projeto Maven existente com umpom.xml. tradicional
Então,we can convert the existing pom.xml project to the desired polyglot by using the translate plugin:
mvn io.takari.polyglot:polyglot-translate-plugin:translate -Dinput=pom.xml -Doutput=pom.yml
6. Escrevendo uma extensão personalizada
Como JSON não é uma das linguagens fornecidas pelo projeto Maven Polyglot,we’ll implement a simple extension that allows reading project metadata from a JSON file.
Nossa extensão fornecerá uma implementação personalizada da API MavenModelProcessor que substituirá a implementação padrão do Maven.
Para conseguir isso, vamos mudar o comportamento de como localizar o arquivo POM e como ler e transformar os metadados para a API MavenModel.
6.1. Dependências do Maven
Começaremos criando um projeto Maven com as seguintes dependências:
org.apache.maven
maven-core
3.5.4
provided
com.fasterxml.jackson.core
jackson-databind
2.9.6
Aqui,we use the maven-core dependency as we’ll implement a core extension. A dependênciaJackson é usada para desserializar o arquivo JSON.
E como o Maven usa o contêiner Plexus Dependency Injection,we need our implementation to be a Plexus component. Portanto, precisamos deste plugin para gerar os metadados do Plexus:
org.codehaus.plexus
plexus-component-metadata
1.7.1
generate-metadata
6.2. A implementação deModelProcessor personalizada
O Maven constrói o modelo POM invocando o métodoModelBuilder.build() que, por sua vez, delega ao métodoModelProcessor.read().
O Maven fornece uma implementaçãoDefaultModelProcessor que, por padrão, lê o modelo POM de um arquivopom.xml localizado no diretório raiz ou especificado como um comando de parâmetro.
Como consequência, forneceremos uma implementaçãoModelProcessor personalizada que substituirá o comportamento padrão. Essa é a localização do arquivo de modelo POM e como lê-lo.
Então, vamos começar criando uma implementaçãoCustomModelProcessor e marcá-la como um componente Plexus:
@Component(role = ModelProcessor.class)
public class CustomModelProcessor implements ModelProcessor {
@Override
public File locatePom(File projectDirectory) {
return null;
}
@Override
public Model read(
InputStream input,
Map options) throws IOException, ModelParseException {
return null;
}
//...
}
The @Component annotation will make the implementation available for injection by the DI container (Plexus). Assim, quando o Maven precisa de uma injeção deModelProcessor noModelBuilder,, o contêiner Plexus fornecerá esta implementação e não o
A seguir,we’ll provide the implementation for the locatePom() method. Este método retorna o arquivo em que o Maven lerá os metadados do projeto.
Portanto, retornaremos um arquivopom.json se ele existir, caso contrário, opom.xml como normalmente fazemos:
@Override
public File locatePom(File projectDirectory) {
File pomFile = new File(projectDirectory, "pom.json");
if (!pomFile.exists()) {
pomFile = new File(projectDirectory, "pom.xml");
}
return pomFile;
}
A próxima etapa é ler esse arquivo e transformá-lo no modelo Maven. Isso é feito pelo método read ():
@Requirement
private ModelReader modelReader;
@Override
public Model read(InputStream input, Map options)
throws IOException, ModelParseException {
FileModelSource source = getFileFromOptions(options);
try (InputStream is = input) {
//JSON FILE ==> Jackson
if (isJsonFile(source)) {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(input, Model.class);
} else {
// XML FILE ==> DefaultModelReader
return modelReader.read(input, options);
}
}
return model;
}
Neste exemplo, verificamos se o arquivo é um arquivo JSON e usamos o Jackson para desserializar para um MavenModel.. Caso contrário, é um arquivo XML normal e será lido pelo MavenDefaultModelReader.
Precisamos construir a extensão, e ela estará pronta para uso:
mvn clean install
6.3. Usando a extensão
Para demonstrar o uso da extensão, usaremos um projeto Spring Boot Web.
Primeiro, vamos criar um projeto Maven e excluir opom.xml.
Então,we’ll add the extension that we have implemented above, in ${projectDirectory}/.mvn/extensions.xml:
com.example.maven.polyglot
maven-polyglot-json-extension
1.0-SNAPSHOT
E, finalmente, criamos opom.json com o seguinte conteúdo:
{
"modelVersion": "4.0.0",
"groupId": "com.example.maven.polyglot",
"artifactId": "maven-polyglot-json-app",
"version": "1.0.1",
"name": "Json Maven Polyglot",
"parent": {
"groupId": "org.springframework.boot",
"artifactId": "spring-boot-starter-parent",
"version": "2.0.5.RELEASE",
"relativePath": null
},
"properties": {
"project.build.sourceEncoding": "UTF-8",
"project.reporting.outputEncoding": "UTF-8",
"maven.compiler.source": "1.8",
"maven.compiler.target": "1.8",
"java.version": "1.8"
},
"dependencies": [
{
"groupId": "org.springframework.boot",
"artifactId": "spring-boot-starter-web"
}
],
"build": {
"plugins": [
{
"groupId": "org.springframework.boot",
"artifactId": "spring-boot-maven-plugin"
}
]
}
}
Agora podemos executar o projeto com o comando:
mvn spring-boot:run
7. Conclusão
Neste artigo, demonstramos como podemos alterar o comportamento padrão do Maven por meio do projeto Maven Polyglot. Para atingir esse objetivo, usamos o novo recurso Maven 3.3.1 que simplifica o carregamento dos componentes principais.
O código e todas as amostras podem ser encontrados normalmenteover on Github.