I am moving an existing Spring boot application from Multitenancy to Database per tenant model. Some common Entities are in the Master database, whereas others will be in their respective database. These classes have been implemented and worked fine. Source to get ma started is this: https://callistaenterprise.se/blogg/teknik/2020/10/03/multi-tenancy-with-spring-boot-part3/
Classes
- MasterPersistenceConfig.java (MasterDatabaseRepository below are the JPA repositories that are gonna be in the master database)
- TenantPersistenceConfig.java
- DynamicDataSourceBasedMultiTenantConnectionProvider.java
- CurrentTenantIdentifierResolverImpl.java
- application.yml
MasterPersistenceConfig.java (MasterDatabaseRepository below are the JPA repositories that are gonna be in the master database)
@Log4j2
@Configuration
@EnableJpaRepositories(
basePackages = { "${multitenancy.base-package}" },
entityManagerFactoryRef = "masterEntityManagerFactory",
transactionManagerRef = "masterTransactionManager",
includeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MasterDatabaseRepository.class)
}
)
@EnableConfigurationProperties({DataSourceProperties.class, JpaProperties.class})
public class MasterPersistenceConfig {
private final ConfigurableListableBeanFactory beanFactory;
private final JpaProperties jpaProperties;
private final String entityPackages;
@Autowired
public MasterPersistenceConfig(ConfigurableListableBeanFactory beanFactory,
JpaProperties jpaProperties,
@Value("${multitenancy.master.entityManager.packages}")
String entityPackages) {
this.beanFactory = beanFactory;
this.jpaProperties = jpaProperties;
this.entityPackages = entityPackages;
}
@Bean
public LocalContainerEntityManagerFactoryBean masterEntityManagerFactory(
@Qualifier("masterDataSource") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setPersistenceUnitName("master-persistence-unit");
em.setPackagesToScan(entityPackages);
em.setDataSource(dataSource);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
Map<String, Object> properties = new HashMap<>(this.jpaProperties.getProperties());
properties.put(AvailableSettings.PHYSICAL_NAMING_STRATEGY, "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
properties.put(AvailableSettings.IMPLICIT_NAMING_STRATEGY, "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
properties.put(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(this.beanFactory));
em.setJpaPropertyMap(properties);
return em;
}
@Bean
public JpaTransactionManager masterTransactionManager(
@Qualifier("masterEntityManagerFactory") EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
TenantPersistenceConfig.java (Using bean of DynamicDataSourceBasedMultiTenantConnectionProvider and CurrentTenantIdentifierResolverImpl to create entityManagerFactory)
@Log4j2
@Configuration
@EnableJpaRepositories(
basePackages = {"${multitenancy.base-package}"},
entityManagerFactoryRef = "tenantEntityManagerFactory",
transactionManagerRef = "tenantTransactionManager",
includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, value = JpaRepository.class),
excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MasterDatabaseRepository.class)
)
@EnableConfigurationProperties(JpaProperties.class)
public class TenantPersistenceConfig {
private final ConfigurableListableBeanFactory beanFactory;
private final JpaProperties jpaProperties;
private final String entityPackages;
@Autowired
public TenantPersistenceConfig(
ConfigurableListableBeanFactory beanFactory,
JpaProperties jpaProperties,
@Value("${multitenancy.tenant.entityManager.packages}")
String entityPackages) {
this.beanFactory = beanFactory;
this.jpaProperties = jpaProperties;
this.entityPackages = entityPackages;
}
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean tenantEntityManagerFactory(
@Qualifier("dynamicDataSourceBasedMultiTenantConnectionProvider") MultiTenantConnectionProvider connectionProvider,
@Qualifier("currentTenantIdentifierResolver") CurrentTenantIdentifierResolver tenantResolver) {
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setPersistenceUnitName("tenant-persistence-unit");
emfBean.setPackagesToScan(entityPackages);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
emfBean.setJpaVendorAdapter(vendorAdapter);
Map<String, Object> properties = new HashMap<>(this.jpaProperties.getProperties());
properties.put(AvailableSettings.PHYSICAL_NAMING_STRATEGY, "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
properties.put(AvailableSettings.IMPLICIT_NAMING_STRATEGY, "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
properties.put(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(this.beanFactory));
properties.put(AvailableSettings.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
properties.put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
properties.put(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
emfBean.setJpaPropertyMap(properties);
return emfBean;
}
@Primary
@Bean
public JpaTransactionManager tenantTransactionManager(
@Qualifier("tenantEntityManagerFactory") EntityManagerFactory emf) {
JpaTransactionManager tenantTransactionManager = new JpaTransactionManager();
tenantTransactionManager.setEntityManagerFactory(emf);
return tenantTransactionManager;
}
@Bean
public TenantDataSource tenantDataSource(@Qualifier("dynamicDataSourceBasedMultiTenantConnectionProvider") MultiTenantConnectionProvider connectionProvider,
@Qualifier("currentTenantIdentifierResolver") CurrentTenantIdentifierResolver tenantResolver) {
return new TenantDataSource(connectionProvider, tenantResolver);
}
@Bean
public NamedParameterJdbcTemplate namedParameterJdbcTemplateRead(@Qualifier("tenantDataSource") TenantDataSource tenantDataSource) {
return new NamedParameterJdbcTemplate(tenantDataSource);
}
@Bean
@Primary
public JdbcTemplate tenantJdbcTemplate(@Qualifier("tenantDataSource") TenantDataSource tenantDataSource) {
return new JdbcTemplate(tenantDataSource);
}
}
DynamicDataSourceBasedMultiTenantConnectionProvider (Uses TenantRepository, which MasterEntityManager manages)
@Log4j2
@Component
public class DynamicDataSourceBasedMultiTenantConnectionProvider
extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl {
private static final String TENANT_POOL_NAME_SUFFIX = "DataSource";
@Autowired
@Qualifier("masterDataSource")
private DataSource masterDataSource;
@Qualifier("masterDataSourceProperties")
@Autowired
private DataSourceProperties dataSourceProperties;
@Autowired
private TenantRepository masterTenantRepository;
private Map<String, HikariDataSource> tenantDataSources = new HashMap<>();
@Autowired
private DbProperties properties;
public DynamicDataSourceBasedMultiTenantConnectionProvider() {
}
public HikariDataSource getDataSource(String code) {
// masterTenantRepository usages
}
@PostConstruct
public Map<String, DataSource> getAll() {
// masterTenantRepository usages
}
@Override
protected HikariDataSource selectAnyDataSource() {
return (HikariDataSource) masterDataSource;
}
@Override
protected HikariDataSource selectDataSource(String tenantIdentifier) {
return getDataSource(tenantIdentifier);
}
private HikariDataSource createAndConfigureDataSource(Tenant tenant) {
// Datasource build and return
}
@Override
public Connection getAnyConnection() throws SQLException {
// get connection using datasource
}
@Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
// get connection using datasource
}
}
CurrentTenantIdentifierResolverImpl (Uses TenantRepository, which MasterEntityManager manages)
@Log4j2
@Component("currentTenantIdentifierResolver")
public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {
@Autowired
private TenantRepository tenantRepository;
@Override
public String resolveCurrentTenantIdentifier() {
// tenantRepository usages
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
}
application.yml
multitenancy:
base-package: packageX
datasource-cache:
maximumSize: 100
expireAfterAccess: 1
master:
entityManager:
packages: packageX
datasource:
url: jdbc:mysql://${db-ip}:3306/master
username: root
password: password
tenant:
entityManager:
packages: packageX
datasource:
url-prefix: jdbc:mysql://${db-ip}:3306/
username: root
password: password
hikari:
maximumPoolSize: 2
minimumIdle: 0
idleTimeout: 30000
readreplica:
base-package: packageX.reports
entityManager:
packages: packageX.reports
datasource:
url-prefix: jdbc:mysql://${slave-db-ip}:3306/
username: root
password: password
hikari:
maximumPoolSize: 2
minimumIdle: 0
idleTimeout: 30000
Everything works fine until this point. Now we want to add another datasource that points to a another IP, i.e. Read replica. When I add another PersistenceConfig file such as above, the application fails to start. Below are a new class added. Stack trace is added below as well.
ReadReplicaPersistenceConfig.java
@Log4j2
@Configuration
@EnableJpaRepositories(
basePackages = {"${multitenancy.readreplica.base-package}"},
entityManagerFactoryRef = "readReplicaEntityManagerFactory",
transactionManagerRef = "readReplicaTransactionManager",
includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, value = ReportsRepository.class)
)
@EnableConfigurationProperties(JpaProperties.class)
public class ReadReplicaPersistenceConfig {
private final ConfigurableListableBeanFactory beanFactory;
private final JpaProperties jpaProperties;
private final String entityPackages;
@Autowired
public ReadReplicaPersistenceConfig(
ConfigurableListableBeanFactory beanFactory,
JpaProperties jpaProperties,
@Value("${multitenancy.readreplica.entityManager.packages}")
String entityPackages) {
this.beanFactory = beanFactory;
this.jpaProperties = jpaProperties;
this.entityPackages = entityPackages;
}
@Bean
public LocalContainerEntityManagerFactoryBean readReplicaEntityManagerFactory(
@Qualifier("dynamicDataSourceBasedMultiTenantConnectionProvider") MultiTenantConnectionProvider connectionProvider,
@Qualifier("currentTenantIdentifierResolver") CurrentTenantIdentifierResolver tenantResolver) {
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setPersistenceUnitName("read-db-persistence-unit");
emfBean.setPackagesToScan(entityPackages);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
emfBean.setJpaVendorAdapter(vendorAdapter);
Map<String, Object> properties = new HashMap<>(this.jpaProperties.getProperties());
properties.put(AvailableSettings.PHYSICAL_NAMING_STRATEGY, "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
properties.put(AvailableSettings.IMPLICIT_NAMING_STRATEGY, "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
properties.put(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(this.beanFactory));
properties.put(AvailableSettings.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
properties.put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
properties.put(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
emfBean.setJpaPropertyMap(properties);
return emfBean;
}
@Bean
public JpaTransactionManager readReplicaTransactionManager(
@Qualifier("readReplicaEntityManagerFactory") EntityManagerFactory emf) {
JpaTransactionManager readReplicaTransactionManager = new JpaTransactionManager();
readReplicaTransactionManager.setEntityManagerFactory(emf);
return readReplicaTransactionManager;
}
@Bean
public ReadReplicaDataSource readReplicaDataSource(@Qualifier("dynamicDataSourceBasedMultiTenantConnectionProvider")
MultiTenantConnectionProvider connectionProvider,
@Qualifier("currentTenantIdentifierResolver")
CurrentTenantIdentifierResolver tenantResolver) {
return new ReadReplicaDataSource(connectionProvider, tenantResolver);
}
@Bean
@Primary
public NamedParameterJdbcTemplate namedParameterJdbcTemplateRead(@Qualifier("readReplicaDataSource")
ReadReplicaDataSource readReplicaDataSource) {
return new NamedParameterJdbcTemplate(readReplicaDataSource);
}
@Bean
public JdbcTemplate readReplicaJdbcTemplate(@Qualifier("readReplicaDataSource") ReadReplicaDataSource
readReplicaDataSource) {
return new JdbcTemplate(readReplicaDataSource);
}
}
Summary of the spring.log stacktrace is . Full stacktrace can be found here: https://justpaste.it/6jwhs
[13:20:23.143] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'springAsyncConfig' of type [packageX.config.async.SpringAsyncConfig$$EnhancerBySpringCGLIB$$38910a1d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.185] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'org.springframework.retry.annotation.RetryConfiguration' of type [org.springframework.retry.annotation.RetryConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.245] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler@70516d8' of type [org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.272] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean '(inner bean)#6c13eb04' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.273] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean '(inner bean)#6c13eb04' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.276] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean '(inner bean)#18e33fe' of type [org.springframework.data.repository.core.support.PropertiesBasedNamedQueries] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.277] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean '(inner bean)#23ba6f2c' of type [org.springframework.data.repository.core.support.RepositoryFragmentsFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.278] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean '(inner bean)#23ba6f2c' of type [org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.296] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'spring.jpa-org.springframework.boot.autoconfigure.orm.jpa.JpaProperties' of type [org.springframework.boot.autoconfigure.orm.jpa.JpaProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.297] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'tenantPersistenceConfig' of type [packageX.dbframework.hibernateconfig.TenantPersistenceConfig$$EnhancerBySpringCGLIB$$f1fe8a65] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.302] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'masterDataSourceConfiguration' of type [packageX.dbframework.datasource.MasterDataSourceConfiguration$$EnhancerBySpringCGLIB$$8117359e] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.317] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'masterDataSourceProperties' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.335] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'masterDataSource' of type [com.zaxxer.hikari.HikariDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.341] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.349] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean '(inner bean)#72ffcc16' of type [org.springframework.beans.factory.config.PropertiesFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.349] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean '(inner bean)#72ffcc16' of type [java.util.Properties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.349] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean '(inner bean)#72313bde' of type [org.springframework.data.repository.core.support.PropertiesBasedNamedQueries] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.350] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean '(inner bean)#5f53b6b2' of type [org.springframework.data.repository.core.support.RepositoryFragmentsFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.350] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean '(inner bean)#5f53b6b2' of type [org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.353] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'masterPersistenceConfig' of type [packageX.dbframework.hibernateconfig.MasterPersistenceConfig$$EnhancerBySpringCGLIB$$540470ad] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:23.494] [restartedMain] [] [] [] [o.h.j.i.u.LogHelper:31] [INFO] - HHH000204: Processing PersistenceUnitInfo [name: master-persistence-unit]
[13:20:23.530] [restartedMain] [] [] [] [o.h.Version:44] [INFO] - HHH000412: Hibernate ORM core version 5.4.27.Final
[13:20:23.638] [restartedMain] [] [] [] [o.h.a.c.Version:56] [INFO] - HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
[13:20:23.735] [restartedMain] [] [] [] [c.z.h.HikariDataSource:110] [INFO] - masterDataSource - Starting...
[13:20:24.041] [restartedMain] [] [] [] [c.z.h.HikariDataSource:123] [INFO] - masterDataSource - Start completed.
[13:20:24.056] [restartedMain] [] [] [] [o.h.d.Dialect:175] [INFO] - HHH000400: Using dialect: org.hibernate.dialect.MySQL57Dialect
[13:20:24.809] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'packageX.entityListeners.SyncJobCandidateListener' of type [packageX.entityListeners.SyncJobCandidateListener] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:24.833] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'packageX.entityListeners.SyncJobListener' of type [packageX.entityListeners.SyncJobListener] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:27.154] [restartedMain] [] [] [] [o.h.e.t.j.p.i.JtaPlatformInitiator:52] [INFO] - HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
[13:20:27.162] [restartedMain] [] [] [] [o.s.o.j.LocalContainerEntityManagerFactoryBean:437] [INFO] - Initialized JPA EntityManagerFactory for persistence unit 'master-persistence-unit'
[13:20:27.165] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'masterEntityManagerFactory' of type [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:27.168] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'masterEntityManagerFactory' of type [com.sun.proxy.$Proxy164] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:27.191] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean '(inner bean)#6ada8fd3' of type [com.sun.proxy.$Proxy166] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:27.201] [restartedMain] [] [] [] [o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:350] [INFO] - Bean 'readReplicaPersistenceConfig' of type [packageX.dbframework.hibernateconfig.ReadReplicaPersistenceConfig$$EnhancerBySpringCGLIB$$759c9f91] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
[13:20:27.206] [restartedMain] [] [] [] [o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext:596] [WARN] - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'healthEndpointGroupsBeanPostProcessor' defined in class path resource [org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.class]: BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration': BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'metaDataSourceAdvisor': Cannot resolve reference to bean 'methodSecurityMetadataSource' while setting constructor argument; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through field 'customRelyingPartyRegistrationRepository'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customRelyingPartyRegistrationRepository': Unsatisfied dependency expressed through field 'samlRegistrationRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'samlRegistrationRepository' defined in packageX.auth.repository.SamlRegistrationRepository defined in @EnableJpaRepositories declared on TenantPersistenceConfig: Cannot create inner bean '(inner bean)#7a8d7a43' 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)#7a8d7a43': Cannot resolve reference to bean 'tenantEntityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'tenantEntityManagerFactory' defined in class path resource [packageXdbframework/hibernateconfig/TenantPersistenceConfig.class]: Unsatisfied dependency expressed through method 'tenantEntityManagerFactory' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dynamicDataSourceBasedMultiTenantConnectionProvider': Unsatisfied dependency expressed through field 'masterTenantRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tenantRepository' defined in packageX.dbframework.datasource.TenantRepository defined in @EnableJpaRepositories declared on MasterPersistenceConfig: Cannot resolve reference to bean 'jpaMappingContext' while setting bean property 'mappingContext'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'readReplicaEntityManagerFactory' defined in class path resource [packageXdbframework/hibernateconfig/ReadReplicaPersistenceConfig.class]: Unsatisfied dependency expressed through method 'readReplicaEntityManagerFactory' parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'currentTenantIdentifierResolver': Unsatisfied dependency expressed through field 'tenantRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'packageX.dbframework.datasource.TenantRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
But when I change readReplicaEntityManagerFactory
and readReplicaTransactionManager
in ReadReplicaPersistenceConfig to tenantEntityManagerFactory
and tenantTransactionManager
respectively, application starts. Although I have not verified the which database my application is making change to.
I'd appreciate any and all help. Thank you.
I tried using @Lazy, @DependsOn to resolve dependencies to avoid BeanCreationException, but not avail.