Maven 3 - как добавить зависимость процессора аннотаций?

Мне нужно запустить обработчик аннотаций для источников моего проекта. Обработчик аннотаций не должен становиться транзитивной зависимостью проекта, поскольку он нужен только для обработки аннотаций и ничего больше.

Вот полный (нерабочий) тестовый модуль, который я использую для этого:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>test</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>Test annotations</name>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <hibernate-jpamodelgen.version>1.2.0.Final</hibernate-jpamodelgen.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>6.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.0</version>
        <configuration>
          <annotationProcessors>
            <annotationProcessor>
              org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</annotationProcessor>
          </annotationProcessors>
          <debug>true</debug>
          <optimize>true</optimize>
          <source>1.6</source>
          <target>1.6</target>
          <compilerArguments>
            <AaddGeneratedAnnotation>true</AaddGeneratedAnnotation>
            <Adebug>true</Adebug>
          </compilerArguments>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-jpamodelgen</artifactId>
            <version>${hibernate-jpamodelgen.version}</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
</project>

Я явно определил org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor как обработчик аннотаций в конфигурации плагина для тестов и знаю, что это не обязательно.

Проблема, с которой я сталкиваюсь, заключается в том, что зависимость hibernate-jpamodelgen не добавляется в путь к классам компилятора, поэтому процессор аннотаций не найден и сборка завершается неудачно.

В соответствии с этим ответом я попытался добавить зависимость в качестве расширения сборки (не уверен, что понимаю, что это должно быть! ) вот так:

<extensions>
  <extension>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-jpamodelgen</artifactId>
    <version>${hibernate-jpamodelgen.version}</version>
  </extension>
</extensions>

Это также не добавляет hibernate-jpamodelgen в путь к классам компилятора.

Единственное, что я нашел, что пока работает, - это добавление зависимости к проекту в разделе <dependencies>. У этого есть неприятный побочный эффект, заключающийся в добавлении hibernate-jpamodelgen в качестве транзитивной зависимости впоследствии, чего я хочу избежать.

Моя предыдущая рабочая установка использует плагин maven-processor-plugin для достижения того, что я хочу. Однако этот плагин не поддерживается eclipse m2e, и последняя версия maven-compiler-plugin теперь правильно обрабатывает несколько аргументов компилятора, поэтому я бы предпочел использовать последний.


person bernie    schedule 14.01.2013    source источник


Ответы (7)


Добавьте зависимость как необязательную зависимость (<optional>true</optional>). Это добавит зависимость при компиляции, но предотвратит ее переходную зависимость:

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-jpamodelgen</artifactId>
  <version>${hibernate-jpamodelgen.version}</version>
  <optional>true</optional>
</dependency>

Если вы создаете в этом модуле артефакт со всеми вашими зависимостями (например, .war), вы можете вместо этого использовать <scope>provided</scope>. Это предотвращает переход зависимости и ее включение в артефакт, создаваемый модулем.

person Aleksander Blomskøld    schedule 14.01.2013
comment
Спасибо, это работает! Однако, исходя из документа Maven относительно областей действия, это не похоже на предполагаемое использование optional и provided. Я приму ваш ответ (эй, он работает!), Если не появится лучший ответ. - person bernie; 14.01.2013
comment
Кроме того, похоже, что provided всегда будет поступать правильно, а optional - нет с war упаковкой. Видите ли вы какой-нибудь случай, когда provided потерпит неудачу? - person bernie; 14.01.2013
comment
Нет, полагаю, при условии, что он всегда будет делать то, что вам нужно. Я также согласен с тем, что это звучит неправильно, но я думаю, вы не найдете лучшего решения. - person Aleksander Blomskøld; 14.01.2013
comment
Необязательный просто означает, что это не требуется для других проектов, которые зависят от этого. Если они этого хотят, они должны заявить об этом явно. Обычно другим проектам не нужны ваши обработчики аннотаций, поэтому это необязательно (не обязательно). Чтобы обработчики аннотаций работали, javac находит их в пути к классам времени компиляции, который является областью компиляции в maven. Предоставляется специальная область для некоторых плагинов, которые упаковывают / связывают зависимости времени компиляции. Их часто путают, но проще подумать о том, что нужно другим проектам от вашего проекта, когда они зависят от вашего. - person Christopher; 25.03.2016
comment
В версии 3.5 плагина компилятора Maven была представлена ​​новая опция annotationProcessorPaths. Я рекомендую использовать это (см. Мой ответ ниже) вместо того, чтобы выставлять JAR процессора как зависимость проекта. - person Gunnar; 21.01.2017

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

<pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.6.1</version>
            <configuration>
                <annotationProcessorPaths>
                    <annotationProcessorPath>
                        <groupId>org.hibernate</groupId>
                        <artifactId>hibernate-jpamodelgen</artifactId>
                        <version>5.2.6.Final</version>
                    </annotationProcessorPath>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</pluginManagement>

Таким образом процессор отделен от реальных зависимостей проекта. Этот параметр также выбирается подключаемым модулем Eclipse M2E, если для проекта включена обработка аннотаций.

person Gunnar    schedule 21.01.2017

Проблема действительно в версии 3. * maven-compiler-plugin. Действует немного иначе, чем версия 2. *. В частности, кажется, что maven-compiler-plugin 3. * не добавляет свои зависимости и расширения сборки в путь к классам, потому что он использует инструменты javax.tools для запуска процесса компиляции. Чтобы вернуть старое поведение для maven-compiler-plugin, вы должны использовать новое свойство конфигурации forceJavacCompilerUse:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
    <forceJavacCompilerUse>true</forceJavacCompilerUse>
</configuration>
....
</plugin>
person Vadim    schedule 02.07.2014
comment
Я добавил этот флаг и все еще получаю сообщение об ошибке с Hibernate JPAMetalModelEntityProcessor версии 1.3. У меня есть сборка maven с несколькими модулями, и сгенерированные классы вместо перехода в parentmodule / submodule / target / ... идут прямо в родительский модуль, там только com dir сброшен с классами? Есть идеи, как это исправить? - person haskovec; 01.10.2014

Для JDK 10 мне действительно пришлось немного сходить с ума, чтобы заставить его работать, Надеясь, что кто-то сочтет это полезным

<jaxb.version>2.3.0</jaxb.version>
<maven.hibernate.version>5.3.2.Final</maven.hibernate.version>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>${maven.compiler.version}</version>
    <goals>
        <goal>compile</goal>
    </goals>
    <configuration>
        <outputDirectory>${project.build.directory}/generated-sources/annotations</outputDirectory>
        <annotationProcessorPaths>
            <annotationProcessorPath>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-jpamodelgen</artifactId>
                <version>${maven.hibernate.version}</version>
            </annotationProcessorPath>
            <annotationProcessorPath>
                <groupId>javax.xml.bind</groupId>
                <artifactId>jaxb-api</artifactId>
                <version>${jaxb.version}</version>
            </annotationProcessorPath>
        </annotationProcessorPaths>
        <annotationProcessors>
            <annotationProcessor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</annotationProcessor>
        </annotationProcessors>
        <compilerArgs>
            <arg>-AaddGeneratedAnnotation=false</arg>
        </compilerArgs>
        <compilerArguments>
            <AaddGeneratedAnnotation>false</AaddGeneratedAnnotation>
            <Adebug>true</Adebug>
        </compilerArguments>
        <failOnError>true</failOnError>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-jpamodelgen</artifactId>
            <version>${maven.hibernate.version}</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>${jaxb.version}</version>
            <type>jar</type>
        </dependency>
    </dependencies>
</plugin>
person Marc Magon    schedule 18.07.2018

Взгляните на jpa-metamodels-with-maven

Для других посетителей я обнаружил, что в серии maven-compiler-plugin 3.x есть некоторые существенные изменения.

Вот как я это делаю. (Я тот, кого вы связали)

Дело в том, что мое решение не работает с этой серией 3.x maven-compiler-plugin.

<project ...>

  <build>

    <extensions>
      <extension>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-jpamodelgen</artifactId>
        <version>1.3.0.Final</version>
      </extension>
    </extensions>

    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.5.1</version> <!-- See this? -->
      </plugin>
    </plugins>

  </build>
</project>
person Jin Kwon    schedule 23.09.2013
comment
Есть ли способ сделать это с помощью компилятора версии 3.1? Похоже, что новый аспект 1.8.2 построен на этих инструментах, так что они все равно втягиваются и ломают сборку. Сгенерированные файлы, похоже, сбрасываются в базовый каталог, а не в целевой каталог. ForceJavacCompilerUse, похоже, тоже не исправляет это для меня. - person haskovec; 01.10.2014
comment
@haskovec Надеюсь, ситуация изменилась. См. jpa-metamodels-with-maven-example. - person Jin Kwon; 10.01.2018
comment
Для меня это было пару вакансий назад. Я думаю, что в конечном итоге я полностью вырезал генерацию метамодели, потому что она не делала того, что мне нужно, поэтому я просто изменил наш код, чтобы он больше не нужен. - person haskovec; 11.01.2018

Не знаю, какая у вас ошибка сборки, но вот мой случай: в Idea появилась следующая ошибка компиляции: Annotation processor 'org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor' not found error

Но при компиляции из Maven все было нормально.

Итак, моя проблема заключалась в том, что я каким-то образом ошибся в настройках Idea. В частности, выяснилось, что Idea каким-то образом обнаружила процессор и внесла в настройки профилей модуля процессора. Здесь обсуждается.

Я исправил это следующим образом:

  1. Перейдите в «Идея»> «Настройки»> «Обработчики аннотаций».
  2. For each processor profile make sure that:
    • Enable annotation processing is Yes;
    • В списке справа отсутствует имя FQ обработчика аннотаций того, в котором возникла ошибка (например, «JPAMetaModelEntityProcessor»). Если он указан там, просто выберите и нажмите кнопку «-» минус, чтобы удалить его.
person Andrew Redko    schedule 03.07.2015

Я думаю, что это лучший способ содержать такие зависимости в профилях для решения таких проблем.

<profile>
    <id>XXX-profile</id>
    <dependencies>
         <dependency>
             // XXX artifact path
         </dependency>
    </dependencies>
</profile>
person Nikita Koval    schedule 18.09.2015