Spring Boot: how to initialize runtime DataSources?

Viewed 283

I'm trying to design a Multitenant Datasource using AbstractRoutingDataSource. The problem that I'm facing is that only the default dataSource is being initialized with the creation/update of the entities' tables. All the other dataSources seem to not be initialized at all. After some reasearch I also tried with a DataSourceSchemaCreatedEvent but without success.

This is the code of my RoutingDataSource:

public class TenantDataSource extends AbstractRoutingDataSource {
    private final TenantResolver tenantResolver = new TenantResolver();

    public TenantDataSource(ApplicationContext applicationContext) {
        super();

        // Default DataSource
        PGSimpleDataSource defaultDS = new PGSimpleDataSource();
        defaultDS.setURL("jdbc:postgresql://localhost:5432/organization");
        defaultDS.setDatabaseName("organization");
        defaultDS.setCurrentSchema("default");
        defaultDS.setUser("default");
        defaultDS.setPassword("default");

        applicationContext.publishEvent(new DataSourceSchemaCreatedEvent(defaultDS));

        this.setDefaultTargetDataSource(defaultDS);

        // Secondary DataSource
        PGSimpleDataSource secondaryDS = new PGSimpleDataSource();
        engDS.setURL("jdbc:postgresql://localhost:5432/organization");
        engDS.setDatabaseName("organization");
        engDS.setCurrentSchema("secondary");
        engDS.setUser("secondary");
        engDS.setPassword("secondary");

        applicationContext.publishEvent(new DataSourceSchemaCreatedEvent(secondaryDS));

        // DSs
        Map<Object, Object> targetDataSources = new ConcurrentHashMap<>();
        targetDataSources.put("DEFAULT", defaultDS);
        targetDataSources.put("SECONDARY", secondaryDS);

        this.setTargetDataSources(targetDataSources);
    }

    @Override
    protected Object determineCurrentLookupKey() {
        String tenant = this.tenantResolver.resolve();
        return tenant;
    }

    @Override
    protected DataSource resolveSpecifiedDataSource(Object dataSource) throws IllegalArgumentException {
        return super.resolveSpecifiedDataSource(dataSource);
    }

    @Override
    protected DataSource determineTargetDataSource() {
        DataSource dataSource = super.determineTargetDataSource();

        return dataSource;
    }
}

and this is my Configuration class:

@Configuration
@RequiredArgsConstructor
@EnableJpaRepositories(
        basePackages = "eu.project.organization.repository.isolated",
        entityManagerFactoryRef = "isolatedEntityManagerFactory",
        transactionManagerRef = "isolatedTransactionManager"
)
public class IsolatedDatabaseConfiguration {
    public static final Class<Driver> PSQL_DRIVER = Driver.class;
    private final ApplicationContext applicationContext;

    @Bean
    public DataSource isolatedDataSource() {
        return new TenantDataSource(this.applicationContext);
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean isolatedEntityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(this.isolatedDataSource());

        String isolatedEntitiesPackage = Employee.class.getPackageName();
        em.setPackagesToScan(isolatedEntitiesPackage);

        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(adapter);

        HashMap<String, Object> properties = new HashMap<>();
        properties.put("hibernate.hbm2ddl.auto", "update");
        properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
        em.setJpaPropertyMap(properties);

        return em;
    }

    @Bean
    public TransactionManager isolatedTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        EntityManagerFactory entityManagerFactory = this.isolatedEntityManagerFactory().getObject();
        transactionManager.setEntityManagerFactory(entityManagerFactory);
        return transactionManager;
    }
}

With this setup when I try to get a list of entities from the secondaryDS I get that the corresponding relation does not exist. The same request is working fine with the defaultDS. What's that I'm missing?

0 Answers
Related