Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Q: How to implement a modulith where each module saves data into its own schema in a single shared database? #63

Open
tomastulka opened this issue May 10, 2019 · 1 comment

Comments

@tomastulka
Copy link

We are trying to follow the idea of moduliths, a modular monolithic applications.

We migrate dour legacy Enterprise Applications (EAR deployment in Glassfish 3) to Spring framework, all running under a single Spring Boot Application (formerly 6 EARs). We talk about "compoments" as successors to EARs.

Several components use JPA (EclipseLink) for persistence, others use JDBC directly. Each module saves data into its own database schema in a single shared database.

Formerly, there was a single Data Source configured by the J2EE Container and so we have it now in the Spring Boot Application as well. Each component has its own Persistence Context / Persistence Unit. A configuration example follows:

// Component "A"

@Bean("puA")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource) {
    return builder.dataSource(dataSource)
            .persistenceUnit("puA")
            .mappingResources("META-INF/orm-puA.xml")
            .packages("com.example.moduleA.model")
            .build();
}

// Component "B"

@Bean("puB")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource) {
    return builder.dataSource(dataSource)
            .persistenceUnit("puB")
            .mappingResources("META-INF/orm-puB.xml")
            .packages("com.example.moduleB.model")
            .build();
}

That's different from the Modulith idea, where Entities of a single Persistence Context are distributed across multiple modules.

Now, we need a Transaction Manager that supports such a scenario: multiple Persistence Contexts, a single Data Source.
The JpaTransactionManager does not do so: a dedicated Transaction Manager must be defined per Persistence Context and a DataSource per DB schema:

// Component "A"

@Bean(name = "tmA")
@Primary
public PlatformTransactionManager transactionManager(@Qualifier("puA") LocalContainerEntityManagerFactoryBean emf) {
    JpaTransactionManager tm = new JpaTransactionManager(emf.getObject());
    tm.setPersistenceUnitName("puA");
    tm.afterPropertiesSet();
    return tm;
}

// Component "B"

@Bean(name = "tmB")
public PlatformTransactionManager transactionManager(@Qualifier("puB") LocalContainerEntityManagerFactoryBean emf) {
    JpaTransactionManager tm = new JpaTransactionManager(emf.getObject());
    tm.setPersistenceUnitName("puB");
    tm.afterPropertiesSet();
    return tm;
}

Single Data Source and multiple Persistence Units

Does Spring framework support this scenario?

@odrotbohm
Copy link
Collaborator

I wonder if that technical separation on the persistence context level has to be put in place as it clearly complicates the picture. The JPA @Table annotation allows to declare the schema an entity is supposed to live in. Using that and strictly governing that aggregates in one module must only refer to other aggregates by identifier, you should be able to get pretty far.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants