Генерация источников путем запуска Java-класса проекта в Maven

Я конвертирую довольно большую конструкцию Ant в Maven. В составе сборки Ant у нас есть несколько шагов, которые создавали классы Java, вызывая один из классов проекта, упрощенный как:

javac SomeGenerator.java
java  SomeGenerator  generated # generate classes in generated/
javac generated/*.java

Я разделил каждый генератор в своем собственном модуле Maven, но у меня проблема с невозможностью запуска генератора, поскольку он еще не скомпилирован в фазе generate-sources.

Я пробовал что-то похожее на

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.1.1</version>
            <executions>
                <execution>
                    <id>generate-model</id>
                    <goals>
                        <goal>java</goal>
                    </goals>
                    <phase>generate-sources</phase>

                    <configuration>
                        <mainClass>DTOGenerator</mainClass>
                        <arguments>
                            <argument>${model.generated.dir}</argument>
                        </arguments>
                    </configuration>
                </execution>
            </executions>
        </plugin>

Что, к сожалению, не работает по причинам, изложенным выше. Разделение генераторов кода на два проекта, один для компиляции генератора, а другой для генерации DTO кажется излишним.

Какие существуют альтернативы?


Использование Maven 2.2.1.

Ответ 1

Вы можете выполнить maven-compile-plugin в фазе генерации-источников. Просто добавьте еще одно исполнение перед выполнением и настройте его так, чтобы он просто собирал источники для генератора.

Или разделите проект на две части: постройте генератор с отдельным POM и включите библиотеку генератора в зависимость от POM, которая генерирует источники.

Лично я бы разделил проект. Сохраняет файлы сборки более чистыми и удобными в обслуживании.

Ответ 2

Мы столкнулись с той же проблемой. Мы хотели уважать поведение Maven как можно ближе, не иметь проблем с плагинами и т.д. Борьба с Maven просто слишком дорога!

Мы поняли, что частота обновления сгенерированного кода обычно сильно отличается от кода, который мы вручную пишем, поэтому разделение кода имеет очень хорошие характеристики производительности для сборки. Поэтому мы приняли, чтобы наши сгенерированные классы были зависимыми от написанного вручную.

Мы приняли следующую структуру, которая имела только одно небольшое изменение из регулярной конфигурации maven, изменения в исходном каталоге.

Родительский проект: Поколения

Мы создали родительский проект для всех наших поколений.

  • Он имеет тип JAR, если он содержит компилируемый код, в противном случае POM.
  • У нас есть наш код генерации в /src.
  • Он может компилироваться в /target как обычно.
  • Он запускает генерацию, каждый генератор создает код в подкаталоге /target.

Примечание. Если вы хотите получить несколько сгенерированных результатов в одной и той же банке, просто поместите их в один и тот же подкаталог.

Проекты дочерних банков: сгенерированные

  • Это подкаталог проекта Generations.
  • Он имеет тип JAR.
  • Исходный каталог указывает на подкаталог в родительской цели.

    <sourceDirectory>../target/generated1</sourceDirectory>

  • Он обычно компилируется в своем/целевом каталоге.


Эта структура позволяет нам:

  • имеют как можно меньшую модификацию стандартного maven-макета, поэтому каждая команда и плагин maven работают хорошо.
  • масштабируется, если у вас несколько генераторов,
  • хорошо, если вы хотите создать несколько банок (у нас был случай wsdl2java, где один генератор создавал код, который должен быть разделен на несколько банок, каждый проект сгенерированный потомком имел бы тот же исходный каталог, но был бы настроен с помощью <includes> для обработки только некоторых классов).

Ответ 3

Я не хотел иметь 2 разных проекта, поэтому я попытался настроить Maven для добавления сгенерированного скомпилированного кода в последний пакет jar.

Это рабочее решение, которое я использовал:

  • В фазе process-classes (выполняется сразу после фазы compile):
    • exec-maven-plugin для выполнения основного класса, способного генерировать мои исходные файлы в папке target/generated-sources/java (в моем конкретном случае я использовал Roaster library для генерации исходного кода);
    • build-helper-maven-plugin для добавления сгенерированных источников в правильное расположение
  • В фазе prepare-package:
    • maven-compiler-plugin, чтобы обнаружить изменения и перекомпилировать модуль
    • maven-jar-plugin для создания пакета банкоматов

Это мой pom.xml:

<build>
    <plugins>

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.6.0</version>
            <executions>
                <execution>
                    <phase>process-classes</phase>
                    <goals>
                        <goal>java</goal>
                    </goals>
                    <configuration>
                        <mainClass>com.example.MyClassWriter</mainClass>
                        <arguments>
                            <argument>${project.basedir}</argument>
                            <argument>${project.build.directory}</argument>
                        </arguments>
                    </configuration>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>3.0.0</version>
            <executions>
                <execution>
                    <phase>process-classes</phase>
                    <goals>
                        <goal>add-source</goal>
                    </goals>
                    <configuration>
                        <sources>
                            <source>${project.build.directory}/generated-sources/java</source>
                        </sources>
                    </configuration>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.6.1</version>
            <executions>
                <execution>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.0.2</version>
            <executions>
                <execution>
                    <phase>prepare-package</phase>
                </execution>
            </executions>
        </plugin>

    </plugins>
</build>

Ответ 4

Я разместил здесь минимальную рабочую настройку https://github.com/baloise/inlinesourcecodegenerator Он использует компилятор build-helper и плагины exec и имеет весь код в том же проекте.