Spring Boot 3.2.2: EntityManagerFactory interface org.hibernate.SessionFactory seems to conflict with Spring's EntityManagerFactoryInfo mixin
Asked Answered
D

1

6

When migrating from Spring Boot 2.4.3 to Spring Boot 3.2.2 (by using Java 17.0.2) I ran into the follwing issue with Spring Data JPA and Hibernate:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultEntityManagerFactory' defined in class path resource [de/mycompany/vector/backend/config/DefaultJPAConfig.class]: 
    EntityManagerFactory interface [interface org.hibernate.SessionFactory] seems to conflict with Spring's EntityManagerFactoryInfo mixin - consider resetting the 'entityManagerFactoryInterface' property to plain [jakarta.persistence.EntityManagerFactory]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1773)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521)
    ...
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
    at de.mycompany.vector.backend.Application.main(Application.java:21)
Caused by: java.lang.IllegalStateException: EntityManagerFactory interface [interface org.hibernate.SessionFactory] seems to conflict with Spring's EntityManagerFactoryInfo mixin - consider resetting the 'entityManagerFactoryInterface' property to plain [jakarta.persistence.EntityManagerFactory]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.createEntityManagerFactoryProxy(AbstractEntityManagerFactoryBean.java:469)
    ...
Caused by: java.lang.IllegalArgumentException: methods with same signature getSchemaManager() but incompatible return types: [interface org.hibernate.relational.SchemaManager, interface jakarta.persistence.SchemaManager]
    at java.base/java.lang.reflect.ProxyGenerator.checkReturnTypes(ProxyGenerator.java:311)

Full command line output while starting up the application is as follows:

jdk17.0.2\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:61495,suspend=y,server=n -XX:TieredStopAtLevel=1 -Dspring.profiles.active=dev -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-Dmanagement.endpoints.jmx.exposure.include=*" -javaagent:C:\Users\Me\AppData\Local\JetBrains\IntelliJIdea2023.3\captureAgent\debugger-agent.jar=file:/C:/Users/Me/AppData/Local/Temp/1/capture.props -Dfile.encoding=UTF-8 -classpath C:\Users\Me\AppData\Local\Temp\1\classpath477957752.jar de.mycompany.vector.backend.Application
Connected to the target VM, address: '127.0.0.1:61495', transport: 'socket'

MySpringBootBackendApp [Spring Boot Backend]
2024-02-27 17:33:51,302 INFO  [background-preinit] o.h.v.i.u.Version: HV000001: Hibernate Validator 8.0.1.Final
2024-02-27 17:33:51,380 INFO  [main] o.s.b.StartupInfoLogger: Starting Application using Java 17.0.2 with PID 30932 (C:\Develop\projects\myapp\src\backend\target\classes started by Me in C:\Develop\projects\myapp\src\backend)
2024-02-27 17:33:51,381 DEBUG [main] o.s.b.StartupInfoLogger: Running with Spring Boot v3.2.2, Spring v6.1.3
2024-02-27 17:33:51,382 INFO  [main] o.s.b.SpringApplication: The following 1 profile is active: "dev"
2024-02-27 17:33:55,279 INFO  [main] o.s.d.r.c.RepositoryConfigurationDelegate: Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2024-02-27 17:33:55,536 INFO  [main] o.s.d.r.c.RepositoryConfigurationDelegate: Finished Spring Data repository scanning in 244 ms. Found 19 JPA repository interfaces.
2024-02-27 17:33:59,911 INFO  [main] o.s.b.w.e.t.TomcatWebServer: Tomcat initialized with port 8081 (http)
2024-02-27 17:33:59,930 INFO  [main] o.a.j.l.DirectJDKLog: Initializing ProtocolHandler ["http-nio-8081"]
2024-02-27 17:33:59,934 INFO  [main] o.a.j.l.DirectJDKLog: Starting service [Tomcat]
2024-02-27 17:33:59,935 INFO  [main] o.a.j.l.DirectJDKLog: Starting Servlet engine: [Apache Tomcat/10.1.18]
2024-02-27 17:34:00,109 INFO  [main] o.a.j.l.DirectJDKLog: Initializing Spring embedded WebApplicationContext
2024-02-27 17:34:00,112 INFO  [main] o.s.b.w.s.c.ServletWebServerApplicationContext: Root WebApplicationContext: initialization completed in 8480 ms
2024-02-27 17:34:03,136 INFO  [main] o.f.c.i.l.s.Slf4jLog: Database: jdbc:oracle:thin:@myDBHost:1234:XXX (Oracle 19.0)
2024-02-27 17:34:04,731 INFO  [main] o.f.c.i.l.s.Slf4jLog: Successfully validated 133 migrations (execution time 00:01.188s)
2024-02-27 17:34:05,155 INFO  [main] o.f.c.i.l.s.Slf4jLog: Current version of schema "NBP_TEST": 2.121
2024-02-27 17:34:05,187 INFO  [main] o.f.c.i.l.s.Slf4jLog: Schema "NBP_TEST" is up to date. No migration necessary.
2024-02-27 17:34:06,689 INFO  [main] o.e.s.o.t.o.p.UpfrontAllocatingPageSource: Allocating 20.0MB in chunks
2024-02-27 17:34:06,739 INFO  [main] o.e.c.EhcacheManager: Cache 'keyAccountDataCache' created in EhcacheManager.
2024-02-27 17:34:06,746 INFO  [main] o.e.s.o.t.o.p.UpfrontAllocatingPageSource: Allocating 10.0MB in chunks
2024-02-27 17:34:06,752 INFO  [main] o.e.c.EhcacheManager: Cache 'meterInfoCache' created in EhcacheManager.
2024-02-27 17:34:06,798 INFO  [main] o.e.j.Eh107CacheManager: Registering Ehcache MBean javax.cache:type=CacheStatistics,CacheManager=file./C./Develop/projects/myapp/src/backend/target/classes/ehcache.xml,Cache=keyAccountDataCache
2024-02-27 17:34:06,802 INFO  [main] o.e.j.Eh107CacheManager: Registering Ehcache MBean javax.cache:type=CacheStatistics,CacheManager=file./C./Develop/projects/myapp/src/backend/target/classes/ehcache.xml,Cache=meterInfoCache
2024-02-27 17:34:07,011 INFO  [main] o.h.j.i.u.LogHelper: HHH000204: Processing PersistenceUnitInfo [name: default]
2024-02-27 17:34:07,149 INFO  [main] o.h.Version: HHH000412: Hibernate ORM core version 6.4.1.Final
2024-02-27 17:34:07,238 INFO  [main] o.h.c.i.RegionFactoryInitiator: HHH000026: Second-level cache disabled
2024-02-27 17:34:08,824 INFO  [main] o.s.o.j.p.SpringPersistenceUnitInfo: No LoadTimeWeaver setup: ignoring JPA class transformer
2024-02-27 17:34:12,277 INFO  [main] o.h.e.t.j.p.i.JtaPlatformInitiator: HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
2024-02-27 17:34:12,350 INFO  [main] o.s.o.j.AbstractEntityManagerFactoryBean: Initialized JPA EntityManagerFactory for persistence unit 'default'
2024-02-27 17:34:12,356 WARN  [main] o.s.c.s.AbstractApplicationContext: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultEntityManagerFactory' defined in class path resource [de/mycompany/vector/backend/config/DefaultJPAConfig.class]: EntityManagerFactory interface [interface org.hibernate.SessionFactory] seems to conflict with Spring's EntityManagerFactoryInfo mixin - consider resetting the 'entityManagerFactoryInterface' property to plain [jakarta.persistence.EntityManagerFactory]
2024-02-27 17:34:12,369 INFO  [main] o.e.c.EhcacheManager: Cache 'keyAccountDataCache' removed from EhcacheManager.
2024-02-27 17:34:12,372 INFO  [main] o.e.c.EhcacheManager: Cache 'meterInfoCache' removed from EhcacheManager.
2024-02-27 17:34:12,382 INFO  [main] o.a.j.l.DirectJDKLog: Stopping service [Tomcat]
2024-02-27 17:34:12,415 INFO  [main] o.s.b.a.l.ConditionEvaluationReportLogger: 

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2024-02-27 17:34:12,450 ERROR [main] o.s.b.SpringApplication: Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultEntityManagerFactory' defined in class path resource [de/mycompany/vector/backend/config/DefaultJPAConfig.class]: EntityManagerFactory interface [interface org.hibernate.SessionFactory] seems to conflict with Spring's EntityManagerFactoryInfo mixin - consider resetting the 'entityManagerFactoryInterface' property to plain [jakarta.persistence.EntityManagerFactory]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1773)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1231)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:949)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:334)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
    at de.mycompany.vector.backend.Application.main(Application.java:21)
Caused by: java.lang.IllegalStateException: EntityManagerFactory interface [interface org.hibernate.SessionFactory] seems to conflict with Spring's EntityManagerFactoryInfo mixin - consider resetting the 'entityManagerFactoryInterface' property to plain [jakarta.persistence.EntityManagerFactory]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.createEntityManagerFactoryProxy(AbstractEntityManagerFactoryBean.java:469)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:403)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1820)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1769)
    ... 16 common frames omitted
Caused by: java.lang.IllegalArgumentException: methods with same signature getSchemaManager() but incompatible return types: [interface org.hibernate.relational.SchemaManager, interface jakarta.persistence.SchemaManager]
    at java.base/java.lang.reflect.ProxyGenerator.checkReturnTypes(ProxyGenerator.java:311)
    at java.base/java.lang.reflect.ProxyGenerator.generateClassFile(ProxyGenerator.java:488)
    at java.base/java.lang.reflect.ProxyGenerator.generateProxyClass(ProxyGenerator.java:178)
    at java.base/java.lang.reflect.Proxy$ProxyBuilder.defineProxyClass(Proxy.java:558)
    at java.base/java.lang.reflect.Proxy$ProxyBuilder.build(Proxy.java:670)
    at java.base/java.lang.reflect.Proxy.lambda$getProxyConstructor$1(Proxy.java:440)
    at java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:329)
    at java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:205)
    at java.base/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:438)
    at java.base/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1037)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.createEntityManagerFactoryProxy(AbstractEntityManagerFactoryBean.java:464)
    ... 20 common frames omitted
Disconnected from the target VM, address: '127.0.0.1:61495', transport: 'socket'

Process finished with exit code 1

My coding is as shown below (class 'DefaultJPAConfig'):
The exception occures after creation of 'defaultEntityManagerFactory' bean.

package de.mycompany.vector.backend.config;

import jakarta.persistence.EntityManagerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.CollectionUtils;

import javax.sql.DataSource;

import java.util.Map;
import java.util.Properties;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "de.mycompany.vector.backend.dao",
  entityManagerFactoryRef = "defaultEntityManagerFactory",
  transactionManagerRef = "defaultTransactionManager"
)
public class DefaultJPAConfig {

  private final Environment env;

  private final JpaProperties jpaProperties;

  public DefaultDataSourceConfig(@Autowired Environment env, @Autowired JpaProperties jpaProperties) {
    this.env = env;
    this.jpaProperties = jpaProperties;
  }

  @Bean(name = {"defaultDataSource"})
  @Primary
  public DataSource defaultDataSource() {
    if (env == null) {
      return null;
    }
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    String url = env.getProperty("spring.datasource.url");
    String driver = env.getProperty("spring.datasource.driver-class");
    String username = env.getProperty("spring.datasource.username");
    String password = env.getProperty("spring.datasource.password");
    dataSource.setDriverClassName(driver);
    dataSource.setUrl(url);
    dataSource.setUsername(username);
    dataSource.setPassword(password);
    Resource initSchema = new ClassPathResource("schema.sql");
    if (initSchema.exists()) {
      DatabasePopulator databasePopulator = new ResourceDatabasePopulator(initSchema);
      DatabasePopulatorUtils.execute(databasePopulator, dataSource);
    }
    return dataSource;
  }

  /**
   * provide a simple jdbc template to export data without all the expensive JPA/ORM functions
   */
  @Bean(name = {"nbpJdbcTemplate"})
  public JdbcTemplate jdbcTemplate() {
    return new JdbcTemplate(defaultDataSource());
  }

  @Bean(name = "defaultEntityManagerFactory")
  @Primary
  @Autowired
  public LocalContainerEntityManagerFactoryBean defaultEntityManagerFactory(
    EntityManagerFactoryBuilder entityManagerFactoryBuilder,
    @Qualifier("defaultDataSource") DataSource ds) {
    return entityManagerFactoryBuilder
      .dataSource(ds)
      .packages("de.mycompany.vector.backend.model")
      .properties(jpaProperties != null ? jpaProperties.getProperties() : null)
      .persistenceUnit("default")
      .build();
  }

  @Bean(name = "defaultTransactionManager")
  @Primary
  @Autowired
  public PlatformTransactionManager defaultTransactionManager(EntityManagerFactory entityManagerFactory) {
    return new JpaTransactionManager(entityManagerFactory);
  }

}

Spring Boot/JPA related configuration in application context file 'application-dev.yml':

spring:
  ...
  jpa:
    # show-sql: true
    hibernate:
      ddl-auto: validate
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    properties:
      hibernate:
        jdbc:
          batch_size: 500
      jakarta:
        persistence:
          schema-generation:
            scripts:
              action: create
              create-target: create.sql
              create-source: metadata

  datasource:
    url: jdbc:oracle:thin:@myDBHost:1234:XXX
    username: NBP_TEST
    password: <secret>
    driver-class: oracle.jdbc.driver.OracleDriver
    hikari:
      connection-timeout: 60000
      maximum-pool-size: 5

Spring Boot/JPA related Maven dependencies in 'pom.xml':

<!-- Spring Boot Starter Parent -->
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>3.2.2</version>
</parent>

...

<dependencies>

    ...

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
      <exclusions>
        <exclusion>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>tomcat-jdbc</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

    <!-- Oracle Database JDBC driver -->
    <dependency>
      <groupId>com.oracle.database.jdbc</groupId>
      <artifactId>ojdbc10</artifactId>
      <version>19.22.0.0</version>
    </dependency>

    ...

</dependencies>

Any help will be very much appreciated!

Best regards,
Maik

Dormer answered 28/2 at 10:3 Comment(0)
D
14

It seems to me, as if I have found the problem and could fix it. It was probably due to using Jakarta Persistence-API version 3.2.0-M1.

After changing Jakarta Persistence-API version from 3.2.0-M1 to 3.1.0 in my Maven pom.xml (according to Spring Boot migration guide, v3.1.0 is the default version supported by Spring Boot 3.2.x), the previously thrown exception concerning Spring Data JPA/Hibernate/Jakarta incompatibility no longer occurs :)

Although the jakarta.persistence-api dependency was commented out in my pom.xml, the jakarta-persistence.version set as a property in my pom.xml, apparently overwrites the value of the same property in spring-boot-starter-parent pom, which implicitly adds the appropriate jakarta.persistence-api dependency to the build.

Extracts from my current Maven pom.xml:

      <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>3.2.2</version>
      </parent>
      
      <properties>  
          <jakarta-persistence.version>3.1.0</jakarta-persistence.version>
          
          <!-- version 3.2.0-M1 does not work
          <jakarta-persistence.version>3.2.0-M1</jakarta-persistence.version>
          -->
      </properties>
      
      <!-- Already included by spring-boot-starter-data-jpa::hibernate-core -->
      <!--
      <dependency>
          <groupId>jakarta.persistence</groupId>
          <artifactId>jakarta.persistence-api</artifactId>
          <version>${jakarta-persistence.version}</version>
      </dependency>
      -->
Dormer answered 28/2 at 21:7 Comment(5)
Lifesaver! Thank you!Noumenon
This worked for me too!!, Thanks @MajestixHong
same for me, Thank you!Pondweed
Super helpful! Thank you so much!Apophysis
Thanks Majestix Finger for you post, it helped me also.Wimer

© 2022 - 2024 — McMap. All rights reserved.