0

I have a simple Spring Boot 2 application using hibernate-jpamodelgen. Here's the entire Maven POM:

    <?xml version="1.0" encoding="UTF-8"?>
    <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/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>

      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
      </parent>

      <groupId>gov.idaho.isp</groupId>
      <artifactId>SpringBootJpaModelGenIssue</artifactId>
      <version>0.1</version>  
      <packaging>jar</packaging>

      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <tomcat.version>9.0.5</tomcat.version>
        <java.version>1.8</java.version>
      </properties>

      <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-devtools</artifactId>
          <optional>true</optional>
        </dependency>

        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
        </dependency>

        <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-jpamodelgen</artifactId>
        </dependency>
      </dependencies>

    </project>

The application contains a single simple entity, Widget having an @NotNull java bean validation constraint annotation:

    import java.io.Serializable;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.validation.constraints.NotNull;

    @Entity
    public class Widget implements Serializable {
      @Id @GeneratedValue
      private Long id;

      @NotNull
      private String name;
      ...
    }

When running this Spring Boot application and then making a change to this entity, the application fails to restart successfully due to the error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.cfg.beanvalidation.IntegrationException: Error activating Bean Validation integration

With a final root cause of:

Caused by: java.lang.annotation.AnnotationFormatError: Duplicate annotation for class: interface javax.validation.constraints.NotNull: @javax.validation.constraints.NotNull(message={javax.validation.constraints.NotNull.message}, groups=[], payload=[])

This restart error disappears if the hibernate-jpamodelgen dependency is removed. Is this a known issue?

See sample application at https://github.com/BriceRoncace/SpringBootJpaModelGenIssue to recreate the issue. (I've encountered this issue with Spring Boot 2.0.0 and 2.0.2.)

Brice Roncace
  • 10,110
  • 9
  • 60
  • 69

1 Answers1

0

A workaround is to use the maven-processor-plugin to explicitly specify that the org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor ought to execute and move the hibernate-jpamodelgen dependency into the plugin definition:

<plugin>
  <groupId>org.bsc.maven</groupId>
  <artifactId>maven-processor-plugin</artifactId>
  <version>3.3.3</version>
  <executions>
    <execution>
      <id>process</id>
      <goals>
        <goal>process</goal>
      </goals>
      <phase>generate-sources</phase>
      <configuration>
        <processors>                                
          <processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
        </processors>
      </configuration>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-jpamodelgen</artifactId>
      <version>5.2.17.Final</version>
    </dependency>
  </dependencies>
</plugin>

The hibernate metamodel docs indicate you should disable annotation processing for the compiler plugin:

<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <compilerArgument>-proc:none</compilerArgument>
  </configuration>
</plugin>

However, I found that the spring boot restart errors reported above disappear even if not disabling the compiler annotation processing.

See commit https://github.com/BriceRoncace/SpringBootJpaModelGenIssue/commit/033ba0078b519d188e7d4c0e6ec66f4278d50ab1

Brice Roncace
  • 10,110
  • 9
  • 60
  • 69