Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Table per tenant not working(Problems with table per tenant in EclipseLink)
Table per tenant not working [message #1809043] Sun, 07 July 2019 18:26 Go to next message
ercan celik is currently offline ercan celikFriend
Messages: 3
Registered: February 2010
Junior Member
I am trying to implement table per tenant solution using Eclipselink 2.7.4 with Spring Boot 2.1.5.

Although I set tenant information to EntityManager before the transaction starts, EclipseLink tries to query the other tenant's table which i have to set in application.properties file.

Here is my JPA configuration

@Configuration
@EnableTransactionManagement
public class JpaConfiguration extends JpaBaseConfiguration {

    protected JpaConfiguration(DataSource dataSource, JpaProperties properties, ObjectProvider<JtaTransactionManager> jtaTransactionManager, ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
        super(dataSource, properties, jtaTransactionManager, transactionManagerCustomizers);
    }

    @Override
    protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
        return new EclipseLinkJpaVendorAdapter();
    }

    @Override
    protected Map<String, Object> getVendorProperties() {
        return new HashMap<>(0);
    }

    @Bean("transactionManager")
    public PlatformTransactionManager createTransactionManager(EntityManagerFactory entityManagerFactory) {
        TenantAwareJpaTransactionManager txManager = new TenantAwareJpaTransactionManager();
        txManager.setEntityManagerFactory(entityManagerFactory);

        return txManager;
    }
}


And this is the Transaction Manager
@Slf4j
public class TenantAwareJpaTransactionManager extends JpaTransactionManager {

    @Override
    protected void doBegin(Object transaction, TransactionDefinition definition) {
        super.doBegin(transaction, definition);

        final EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(getEntityManagerFactory());
        final EntityManager em = emHolder.getEntityManager();

        String tenant = TenantContext.getCurrentTenant();
        if (StringUtils.isEmpty(tenant)) {
            throw new NoTenantProvidedException();
        }
        log.info("{} is set to EntityManager", tenant);
        em.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, tenant);
    }

    class NoTenantProvidedException extends RuntimeException {

        public NoTenantProvidedException() {
            super("No tenant identifier could be resolved instance.");
        }
    }
}


And this is the service

@Slf4j
@Service
public class CustomerService {
    @PersistenceContext
    EntityManager entityManager;

    private final CustomerRepository customerRepository;

    public CustomerService(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }

    @Transactional
    public Customer add(Customer customer) {
        setTenant();
        return this.customerRepository.save(customer);
    }

    @Transactional
    public Customer update(Long customerId, Customer customer) {
        setTenant();

        Optional<Customer> temp = this.customerRepository.findById(customerId);
        if (temp.isPresent()) {
            temp.get().setFirstName(customer.getFirstName());
            temp.get().setLastName(customer.getLastName());
            return temp.get();
        }
        return null;
    }

    @Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
    public List<Customer> getAll() {
        setTenant();

        return this.customerRepository.findAll();
    }

    @Transactional
    public void delete(Long customerId) {
        setTenant();

        Optional<Customer> temp = this.customerRepository.findById(customerId);
        if (temp.isPresent()) {
            this.customerRepository.delete(temp.get());
        }
    }

    private void setTenant(){
        log.info("Current tenant : {}", TenantContext.getCurrentTenant());
        this.entityManager.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, TenantContext.getCurrentTenant());
    }
}


You could find all the other related classes here -> https://github.com/ercancelik/eclipselink-multitenant

I am using shared Entity Manager. Do I need to use separate EntityManager per tenant?

Note:
After running the project, you should execute the ddls in src/main/resources/ddl.sql file in H2 console -> http://localhost:8080/console/login.jsp.

After that you can run the curl command to see the error. Although I set TENANT2 to the request headers, it tries to query TENANT1's table.
 curl -X GET http://localhost:8080/customers -H 'Accept: application/json' -H 'X-TenantID: TENANT2'
Re: Table per tenant not working [message #1809898 is a reply to message #1809043] Thu, 25 July 2019 11:43 Go to previous messageGo to next message
ercan celik is currently offline ercan celikFriend
Messages: 3
Registered: February 2010
Junior Member
It is very sad for me that anyone has not answered the question or made any comment on the question. This is the official community of the product but I couldn't get any answer. If the question is not clear, please let me know.
Re: Table per tenant not working [message #1810182 is a reply to message #1809898] Fri, 02 August 2019 10:17 Go to previous messageGo to next message
Sara  Rüegg is currently offline Sara RüeggFriend
Messages: 2
Registered: July 2019
Junior Member
This forum seems utterly dead :( I can't even post my question... it needs to be approved by someone which it hasn't in several days (or there is a bug in the forum)
Re: Table per tenant not working [message #1810485 is a reply to message #1810182] Mon, 12 August 2019 15:44 Go to previous messageGo to next message
Denis Roy is currently offline Denis RoyFriend
Messages: 484
Registered: October 2004
Location: Ottawa, Ontario, Canada
Senior Member

Sara, sorry for the delay. Your messages were posted.

Denis Roy
Eclipse Webmaster -- webmaster@eclipse.org
Re: Table per tenant not working [message #1811162 is a reply to message #1810485] Wed, 28 August 2019 03:21 Go to previous message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1389
Registered: July 2009
Senior Member

The code only seems to set the tenant setting in doBegin, how does Spring treat that readOnly=true flag on the get? Turn on logging and debugging and see what is printed off, and maybe add some debugging to see what is set on the EntityManager before executing the query.
Previous Topic:EclipseLink with Java 9+
Next Topic:Migration from Toplink to Eclipselink
Goto Forum:
  


Current Time: Fri Apr 26 07:04:31 GMT 2024

Powered by FUDForum. Page generated in 0.03391 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top