javaspringspring-boothibernate-entitymanager

required a bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' that could not be found


I have a spring boot 2.4.0 application that connects to 2 different data sources. I keep getting this error. I searched for solutions all over internet. I found that I need to specify only one of my beans with @Primary, fact that I also did (so it was not my case). I will post the error and classes below. Thank you:

Error:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.> 
<Jun 14, 2021 11:07:01 AM EEST> <Notice> <Stdout> <BEA-000000> <2021-06-14 11:07:01.740 ERROR 7845 --- [ (self-tuning)'] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method entityManagerFactory in demo.Db1Config required a bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' that could not be found.


Action:

Consider defining a bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' in your configuration.> 
<Jun 14, 2021 11:07:01 AM EEST> <Error> <Deployer> <BEA-149265> <Failure occurred in the execution of deployment request with ID "430590093957351" for task "888" on [partition-name: DOMAIN]. Error is: "weblogic.application.ModuleException: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}"
weblogic.application.ModuleException: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    at weblogic.application.internal.ExtensibleModuleWrapper.start(ExtensibleModuleWrapper.java:140)
    at weblogic.application.internal.flow.ModuleListenerInvoker.start(ModuleListenerInvoker.java:124)
    at weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleStateDriver.java:237)
    at weblogic.application.internal.flow.ModuleStateDriver$3.next(ModuleStateDriver.java:232)
    at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45)
    Truncated. see log file for complete stacktrace
Caused By: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1777)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1333)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1287)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:885)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789)
    Truncated. see log file for complete stacktrace

Db1Config.java:

@Configuration
@EnableTransactionManagement
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@EnableJpaRepositories(entityManagerFactoryRef = "db1EntityManagerFactory",
        basePackages = {"demo.db1.repo"})
public class Db1Config {

    @Primary
    @Bean(name = "db1DataSource", destroyMethod="")
    @ConfigurationProperties(prefix = "db1.datasource")
    public DataSource dataSource() {
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        DataSource dataSource = dataSourceLookup.getDataSource("jdbc/JNDI_NAME_1");
        return dataSource;
    }

    @Primary
    @Bean(name = "db1EntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder, @Qualifier("db1DataSource") DataSource dataSource) {
        return builder.dataSource(dataSource).packages("demo.db1.domain").persistenceUnit("db1")
                .build();
    }

    @Primary
    @Bean(name = "db1TransactionManager")
    public PlatformTransactionManager transactionManager(
            @Qualifier("db1EntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

Db2Config.java:

@Configuration
@EnableTransactionManagement
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@EnableJpaRepositories(entityManagerFactoryRef = "db2EntityManagerFactory",
        transactionManagerRef = "db2TransactionManager", basePackages = {"demo.db2.repo"})
public class Db2Config {

    @Bean(name = "db2DataSource", destroyMethod="")
    @ConfigurationProperties(prefix = "db2.datasource")
    public DataSource dataSource() {
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        DataSource dataSource = dataSourceLookup.getDataSource("jdbc/JNDI_NAME_2");
        return dataSource;
    }

    @Bean(name = "db2EntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean barEntityManagerFactory(
            EntityManagerFactoryBuilder builder, @Qualifier("db2DataSource") DataSource dataSource) {
        return builder.dataSource(dataSource).packages("demo.db2.domain").persistenceUnit("db2")
                .build();
    }

    @Bean(name = "db2TransactionManager")
    public PlatformTransactionManager barTransactionManager(
            @Qualifier("db2EntityManagerFactory") EntityManagerFactory barEntityManagerFactory) {
        return new JpaTransactionManager(barEntityManagerFactory);
    }
}

Application.java:

@SpringBootApplication(exclude = HibernateJpaAutoConfiguration.class)
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

ServletInitializer.java:

public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        factory.setMaxFileSize(DataSize.ofMegabytes(100000L));
        factory.setMaxRequestSize(DataSize.ofMegabytes(100000L));
        return factory.createMultipartConfig();
    }
}


Solution

  • I see issue in Application.java, because you have excluded HibernateJpaAutoConfiguration.class, that auto configurer has link on JpaBaseConfiguration class in which EntityManagerFactoryBuilder creates. enter image description here After that you have two options for solving issue:

    @Bean
    public EntityManagerFactoryBuilder entityManagerFactoryBuilder() {
       return new EntityManagerFactoryBuilder(new HibernateJpaVendorAdapter(), new HashMap<>(), null);
    }
    

    P.S. I am not sure if you need following code in configs in total:

    @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})