Мавен Полиглот

Мавен Полиглот

1. обзор

Maven Polyglot - это набор расширений ядра Maven, который позволяет писать модель POM на любом языке. Это включает в себя множество скриптов и языков разметки, кроме XML.

Основная цель полиглота Maven - уйти от XML, поскольку в настоящее время он больше не является популярным языком.

В этом руководстве мы сначала начнем с понимания концепции расширения ядра Maven и проекта Maven Polyglot.

Затем мы покажем, как написать расширение ядра Maven, которое позволяет создавать модель POM из файла JSON, а не из известногоpom.xml.

2. Механизм загрузки расширения Maven Core

The Maven core extensions are plugins loaded at Maven initialization и до начала сборки проекта Maven. Эти плагины позволяют изменять поведение Maven без изменения ядра.

Например, подключаемый модуль, загружаемый при запуске, может переопределить поведение Maven по умолчанию и может считывать модель POM из другого файла, чемpom.xml.

Техническиa Maven core extension is a Maven artifact declared in an extensions.xml file:

${projectDirectory}/.mvn/extensions.xml

Вот пример расширения:



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

Наконец, нужно отметить, чтоthis mechanism requires Maven 3.3.1 or higher.

3. Мавен Полиглот

Maven Polyglot is a collection of core extensions. Каждый из них отвечает за чтение модели POM из скрипта или языка разметки.

Maven Polyglot предоставляет расширения для следующих языков:

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

В следующих разделах мы сначала рассмотрим создание проекта Maven с использованием одного из поддерживаемых языков выше.

Затем мы напишем наше расширение для поддержки POM на основе JSON.

4. Использование расширения Maven Polyglot

Одним из вариантов создания проекта Maven на основе языка, отличного от XML, является использование одного из артефактов, предоставленных проектом Polyglot.

В нашем примереwe’ll create a Maven project with a pom.yaml configuration file.

Первым шагом является создание файла расширения ядра Maven:

${projectDirectory}/.mvn/extensions.xml

Затем мы добавим следующий контент:



    
        io.takari.polyglot
        polyglot-yaml
        0.3.1
    

Не стесняйтесь настраиватьartifactId на выбранный вами язык в соответствии с языками, указанными выше, и проверять, доступен ли какой-либоnew version.

Последний шаг - предоставить метаданные проекта в файлеYAML:

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}

Теперь мы можем запустить нашу сборку, как обычно. Например, мы можем вызвать команду:

mvn clean install

5. Использование плагина Polyglot Translate

Другой вариант получить проект на одном из поддерживаемых языков - использоватьpolyglot-translate-plugin.

Это означает, что мы можем начать с существующего проекта Maven с традиционнымpom.xml.

Тогда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. Написание собственного расширения

Поскольку JSON не является одним из языков, предоставляемых проектом Maven Polyglot,we’ll implement a simple extension that allows reading project metadata from a JSON file.

Наше расширение предоставит настраиваемую реализацию API MavenModelProcessor, которая переопределит реализацию Maven по умолчанию.

Для этого мы изменим порядок поиска файла POM, а также способы чтения и преобразования метаданных в API MavenModel.

6.1. Maven Зависимости

Мы начнем с создания проекта Maven со следующими зависимостями:


    org.apache.maven
    maven-core
    3.5.4
    provided


    com.fasterxml.jackson.core
    jackson-databind
    2.9.6

Здесьwe use the maven-core dependency as we’ll implement a core extension. ЗависимостьJackson используется для десериализации файла JSON.

И поскольку Maven использует контейнер Plexus Dependency Injection,we need our implementation to be a Plexus component. Поэтому нам нужен этот плагин для генерации метаданных Plexus:


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

6.2. Пользовательская реализацияModelProcessor

Maven создает модель POM, вызывая методModelBuilder.build(), который, в свою очередь, делегирует методуModelProcessor.read().

Maven предоставляет реализациюDefaultModelProcessor, которая по умолчанию считывает модель POM из файлаpom.xml, расположенного в корневом каталоге или указанного в качестве команды параметра.

Как следствие, мы предоставим специальную реализациюModelProcessor, которая переопределит поведение по умолчанию. Это расположение файла модели POM и способ его чтения.

Итак, давайте начнем с создания реализацииCustomModelProcessor и отметим ее как компонент 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). Итак, когда Maven требуется инъекцияModelProcessor вModelBuilder,, контейнер Plexus предоставит эту реализацию, а неDefaultModelProcessor.

Далееwe’ll provide the implementation for the locatePom() method. Этот метод возвращает файл, в котором Maven будет читать метаданные проекта.

Поэтому мы вернем файлpom.json, если он существует, в противном случае -pom.xml, как мы обычно делаем:

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

Следующий шаг - прочитать этот файл и преобразовать его в модель Maven. Это достигается методом 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;
}

В этом примере мы проверяем, является ли файл файлом JSON, и используем Jackson для десериализации его в MavenModel.. В противном случае это обычный XML-файл, и он будет прочитан MavenDefaultModelReader.

Нам нужно построить расширение, и оно будет готово к использованию:

mvn clean install

6.3. Использование расширения

Чтобы продемонстрировать использование расширения, мы будем использовать веб-проект Spring Boot.

Сначала мы создадим проект Maven и удалимpom.xml.

Тогда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
    

И, наконец, мы создаемpom.json со следующим содержимым:

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

Теперь мы можем запустить проект с помощью команды:

mvn spring-boot:run

7. Заключение

В этой статье мы продемонстрировали, как можно изменить поведение Maven по умолчанию с помощью проекта Maven Polyglot. Для достижения этой цели мы использовали новую функцию Maven 3.3.1, которая упрощает загрузку основных компонентов.

Код и все образцы можно найти как обычноover on Github.