Maven Poliglota

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.