Maven Polyglot

Maven Polyglot

1. Überblick

Maven Polyglot ist eine Reihe von Maven-Kernerweiterungen, mit denen das POM-Modell in einer beliebigen Sprache geschrieben werden kann. Dies umfasst viele andere Skripts und Markup-Sprachen als XML.

Das Hauptziel von Maven Polyglot ist die Flucht aus XML, da es heutzutage nicht mehr die bevorzugte Sprache ist.

In diesem Tutorial werden wir zunächst das Maven-Kernerweiterungskonzept und das Maven Polyglot-Projekt verstehen.

Anschließend zeigen wir, wie eine Maven-Kernerweiterung geschrieben wird, mit der das POM-Modell aus einer JSON-Datei und nicht aus den berühmtenpom.xml. erstellt werden kann

2. Maven Core Extension Lademechanismus

The Maven core extensions are plugins loaded at Maven initialization und vor dem Start des Maven-Projekts. Diese Plugins ermöglichen das Ändern des Maven-Verhaltens, ohne den Core zu ändern.

Beispielsweise kann ein beim Start geladenes Plugin das Standardverhalten von Maven überschreiben und das POM-Modell aus einer anderen Datei alspom.xml lesen.

Technisch gesehena Maven core extension is a Maven artifact declared in an extensions.xml file:

${projectDirectory}/.mvn/extensions.xml

Hier ist ein Beispiel für eine Erweiterung:



    
        com.example.maven.polyglot
        maven-polyglot-json-extension
        1.0-SNAPSHOT
    

Schließlich müssen wir beachten, dassthis mechanism requires Maven 3.3.1 or higher.

3. Maven Polyglot

Maven Polyglot is a collection of core extensions. Jeder von ihnen ist für das Lesen des POM-Modells aus einem Skript oder einer Auszeichnungssprache verantwortlich.

Maven Polyglot bietet Erweiterungen für die folgenden Sprachen:

+-----------+-------------------+--------------------------------------+
| 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                    |
+-----------+-------------------+--------------------------------------+

In den nächsten Abschnitten werden wir uns zunächst mit dem Erstellen eines Maven-Projekts in einer der oben genannten unterstützten Sprachen befassen.

Anschließend schreiben wir unsere Erweiterung zur Unterstützung eines JSON-basierten POM.

4. Verwenden einer Maven Polyglot-Erweiterung

Eine Möglichkeit, ein Maven-Projekt zu erstellen, das auf einer anderen Sprache als XML basiert, besteht darin, eines der vom Polyglot-Projekt bereitgestellten Artefakte zu verwenden.

In unserem Beispielwe’ll create a Maven project with a pom.yaml configuration file.

Der erste Schritt besteht darin, die Maven-Core-Erweiterungsdatei zu erstellen:

${projectDirectory}/.mvn/extensions.xml

Dann fügen wir den folgenden Inhalt hinzu:



    
        io.takari.polyglot
        polyglot-yaml
        0.3.1
    

Sie können dieartifactId entsprechend den oben genannten Sprachen an die von Ihnen gewählte Sprache anpassen und prüfen, obnew version verfügbar sind.

Der letzte Schritt besteht darin, die Projektmetadaten in der DateiYAML bereitzustellen:

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}

Jetzt können wir unseren Build wie gewohnt ausführen. Zum Beispiel können wir den Befehl aufrufen:

mvn clean install

5. Verwenden des Polyglot Translate Plugins

Eine weitere Option, um ein Projekt zu erhalten, das auf einer der unterstützten Sprachen basiert, ist die Verwendung vonpolyglot-translate-plugin.

Dies bedeutet, dass wir von einem bestehenden Maven-Projekt mit einem traditionellenpom.xml. ausgehen können

Dannwe 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. Eine benutzerdefinierte Erweiterung schreiben

Da JSON keine der vom Maven Polyglot-Projekt bereitgestellten Sprachen ist,we’ll implement a simple extension that allows reading project metadata from a JSON file.

Unsere Erweiterung stellt eine benutzerdefinierte Implementierung der API von MavenModelProcessordar, die die Maven-Standardimplementierung außer Kraft setzen wird.

Um dies zu erreichen, müssen wir das Verhalten beim Auffinden der POM-Datei und beim Lesen und Transformieren der Metadaten in die API von MavenModeländern.

6.1. Maven-Abhängigkeiten

Zunächst erstellen wir ein Maven-Projekt mit den folgenden Abhängigkeiten:


    org.apache.maven
    maven-core
    3.5.4
    provided


    com.fasterxml.jackson.core
    jackson-databind
    2.9.6

Hierwe use the maven-core dependency as we’ll implement a core extension. Die Abhängigkeit vonJacksonwird zum Deserialisieren der JSON-Datei verwendet.

Und da Maven den Plexus Dependency Injection-Container verwendet,we need our implementation to be a Plexus component. Also brauchen wir dieses Plugin, um die Plexus-Metadaten zu generieren:


    org.codehaus.plexus
    plexus-component-metadata
    1.7.1
    
        
            
                generate-metadata
            
        
    

6.2. Die Implementierung von CustomModelProcessor

Maven erstellt das POM-Modell durch Aufrufen der MethodeModelBuilder.build(), die wiederum an die MethodeModelProcessor.read()delegiert.

Maven bietet eineDefaultModelProcessor-Implementierung, die standardmäßig das POM-Modell aus einerpom.xml-Datei liest, die sich im Stammverzeichnis befindet oder als Parameterbefehl angegeben ist.

Infolgedessen stellen wir eine benutzerdefinierteModelProcessor-Implementierung bereit, die das Standardverhalten überschreibt. Dies ist der Speicherort der POM-Modelldatei und deren Lesart.

Beginnen wir also mit der Erstellung einerCustomModelProcessor-Implementierung und markieren Sie sie als Plexus-Komponente:

@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). Wenn Maven also eineModelProcessor-Injektion inModelBuilder, benötigt, stellt der Plexus-Container diese Implementierung bereit und nicht dieDefaultModelProcessor.

Als nächsteswe’ll provide the implementation for the locatePom() method. Diese Methode gibt die Datei zurück, in der Maven die Projektmetadaten liest.

Wir geben also einepom.json-Datei zurück, falls vorhanden, andernfalls diepom.xml, wie wir es normalerweise tun:

@Override
public File locatePom(File projectDirectory) {
    File pomFile = new File(projectDirectory, "pom.json");
    if (!pomFile.exists()) {
        pomFile = new File(projectDirectory, "pom.xml");
    }
    return pomFile;
}

Der nächste Schritt besteht darin, diese Datei zu lesen und in das Maven-Modell umzuwandeln. Dies wird durch die read () -Methode erreicht:

@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;
}

In diesem Beispiel prüfen wir, ob es sich bei der Datei um eine JSON-Datei handelt, und verwenden den Jackson, um sie in einen MavenModel.zu deserialisieren. Andernfalls handelt es sich um eine normale XML-Datei, die von den MavenDefaultModelReader.gelesen wird

Wir müssen die Erweiterung erstellen, und sie wird einsatzbereit sein:

mvn clean install

6.3. Verwendung der Erweiterung

Um die Verwendung der Erweiterung zu demonstrieren, verwenden wir ein Spring Boot-Webprojekt.

Zuerst erstellen wir ein Maven-Projekt und löschen diepom.xml.

Dannwe’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
    

Und schließlich erstellen wir diepom.json mit folgendem Inhalt:

{
  "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"
      }
    ]
  }
}

Wir können das Projekt nun mit dem Befehl ausführen:

mvn spring-boot:run

7. Fazit

In diesem Artikel haben wir gezeigt, wie wir das Standardverhalten von Maven über das Maven Polyglot-Projekt ändern können. Um dieses Ziel zu erreichen, haben wir die neue Maven 3.3.1-Funktion verwendet, die das Laden der Kernkomponenten vereinfacht.

Der Code und alle Beispiele finden Sie wie gewohnt inover on Github.