CDI Crud Multi “Tenancy”

Just added an example of multi tenancy to our cdi-crud example, now Car and Movie tables are in different datasources. In fact our example is not truly multi tenancy where you have the same boundaries but different schemas so you can have multiple clients on the same application and each one using its database, see [1] and [2] for eclipse link and hibernate native support for multi tenancy respectively.The example below is a simple approach to switch between datasources using CDI. Although with some changes in our TenantController like eg: use of SystemProperty to define tenant or use alternatives like [3] could add some more ‘tenantness’.

As usual there are some arquillian integration tests here.

I will summarize the idea as i’m out of time(also as usual), here are the steps:

Changed entityManager resolution in our Crud/GenericDao/NanoService/whatever class FROM:

@PersistenceContext
EntityManager em;

public Entitymanager getEntityManager(){
    return em;
}

TO:

@Inject
TenantController tenantController;
TenantType tenantType;

public Entitymanager getEntityManager(){
    return tenantController.getTenant(tenantType);
}

WHERE TenantController simple has all entityManagers injected and decide which one to return using TenantType:

public class TenantController {

	@PersistenceContext(unitName="CarPU")
	EntityManager carEm;

	@PersistenceContext(unitName="MoviePU")
	EntityManager movieEm;

	public EntityManager getTenant(TenantType type){
		switch (type) {
		case CAR:
			return carEm;
		case MOVIE:
			return movieEm;
			default:{
				Logger.getLogger(getClass().getCanonicalName()).info("no tenant provided, resolving to CarPU");
				return carEm;//force error, we dont want to resolve it by "accident"
			}
		}
	}

}

TenantType is passed via Annotation to each service:

@Stateless
@Tenant(TenantType.MOVIE)
public class MovieService extends CrudService<Movie> {

}

via injection point into Generic Crud:

@Stateless
@Tenant(TenantType.MOVIE)//not a qualifier just an inherited annotation
public class MovieService extends CrudService<Movie> {

@Inject
@Tenant(TenantType.CAR)
Crud<Car> carCrud;//becareful to not pass wrong entity in generics, see this test:<a href="https://github.com/rmpestano/cdi-crud/blob/master/src/test/java/com/cdi/crud/test/MultiTenantIt.java#L93" target="_blank">https://github.com/rmpestano/cdi-crud/blob/master/src/test/java/com/cdi/crud/test/MultiTenantIt.java#L93</a>

}

Or programmatically:

@Stateless
public class MovieService extends CrudService<Movie> {

public void someMethod(){
   super.crud(TenantType.CAR).listAll();
  }
}

I’m not producing qualified entityManagers just to not have qualified Crud.java neither qualified Services.

Thats it, and how about you, how do you deal with multiple databases in your applications?

[1]http://wiki.eclipse.org/EclipseLink/Development/Indigo/Multi-Tenancy
[2]http://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch16.html
[3]http://antoniogoncalves.org/2014/05/25/switch-datasource-with-cdi-alternatives-and-stereotypes/
[4]http://lambda-et-al.eu/multi-tenancy-with-jee-and-jboss/

Advertisements

2 thoughts on “CDI Crud Multi “Tenancy”

  1. Pingback: CDI Generic Dao | Rafael Pestano
  2. Pingback: Some Words on JavaEE, REST and Swagger | Rafael Pestano

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s