Multi module Springboot

i am creating multi module springboot project in which i have common-library and admin service are different modules and common-library contains all entity and repository class and interface and admin-service is implementing common-library as a dependency, i have used gradle and when i build the project , its building successfully using \

"./gradlew clean build -x test"

and when i try to run admin-service module using
"./gradlew :admin-service:bootRun"

i got exception. can someone please help me to solve this. Please have a look at my code below.

//Admin service main class file.

package com.zaihamm.admin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableAsync;

@EnableAsync
@SpringBootApplication(scanBasePackages = "com.zaihamm.common", exclude =  
{DataSourceAutoConfiguration.class })
@EntityScan("com.zaihamm.common.entity")
@EnableJpaRepositories(basePackages = {"com.zaihamm.common.repository"})
public class AdminServiceApplication {

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

}

and common-library is like enter image description here

My Admin service gradle is like this enter image description here

and when i run i got this exception enter image description here

 Exception encountered during context initialization - cancelling 
refresh attempt: 
org.springframework.beans.factory.BeanCreationException: Error 
creating bean with name 'addressRepository' defined in 
com.zaihamm.common.repository.AddressRepository defined in 
@EnableJpaRepositories declared on AdminServiceApplication: 
Cannot create inner bean '(inner bean)#35ef439e' of type 
[org.springframework.orm.jpa.SharedEntityManagerCreator] while 
setting bean property 'entityManager'; nested exception is 
org.springframework.beans.factory.BeanCreationException: Error 
creating bean with name '(inner bean)#35ef439e': Cannot resolve 
reference to bean 'entityManagerFactory' while setting 
constructor argument; nested exception is 
org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No bean named 'entityManagerFactory' available

enter image description here

enter image description here


In your AdminServiceApplication class you have excluded DataSourceAutoConfiguration.class. That is probably the cause you are having missing entity manager. You'll have to configure your own custom dataSource class and then inject it.

Follows an example that worked for me in the past when I needed 2 datasources and also needed to exclude DataSourceAutoConfiguration.class. You will have to modify it to make it work for you:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "myEntityManagerFactory",
        transactionManagerRef = "myTransactionManager",
        basePackages = "com.example.my_package.repository"
)
public class MyDataSourceConfig {

    @Autowired
    private Environment env;

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean myEntityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(customDataSource());
        em.setPersistenceUnitName("myPU");
        em.setPackagesToScan(new String[]{"com.example.main_package"});
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setDatabasePlatform(env.getProperty("spring.jpa.database-platform"));
        vendorAdapter.setShowSql(Boolean.getBoolean(env.getProperty("spring.jpa.show-sql")));
        em.setJpaVendorAdapter(vendorAdapter);
        
        HashMap<String, Object> properties = new HashMap<>();
        properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
        properties.put("hibernate.physical_naming_strategy", env.getProperty("spring.jpa.hibernate.naming.physical-strategy"));
        properties.put("hibernate.implicit-strategy", env.getProperty("spring.jpa.hibernate.naming.implicit-strategy"));
        properties.put("hibernate.dialect", env.getProperty("spring.jpa.database-platform"));
        em.setJpaPropertyMap(properties);
        return em;
    }

    @Bean
    @Primary
    public DataSource customDataSource() {
        return DataSourceBuilder.create()
                .driverClassName(env.getProperty("spring.datasource.driver-class-name"))
                .url(env.getProperty("spring.datasource.url"))
                .username(env.getProperty("spring.datasource.username"))
                .password(env.getProperty("spring.datasource.password"))
                .build();
    }

    @Bean
    @Primary
    public PlatformTransactionManager myTransactionManager() {
      JpaTransactionManager tm = new JpaTransactionManager();
      tm.setEntityManagerFactory(myEntityManagerFactory().getObject());
      return tm;
    }
}

When I've used this, I've also excluded other spring classes:

DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class

If you want to inject entityManager manually you'll do someting like this:

@Autowired
@Qualifier("myEntityManagerFactory")
private EntityManager myEntityManager;

Here is another simpler example from spring-data github repository https://github.com/spring-projects/spring-data-examples/blob/main/jpa/multiple-datasources/src/main/java/example/springdata/jpa/multipleds/customer/CustomerConfig.java