We developed a data driven application within Liferay 6.0 for a client recently utilizing JPA, and everything was running quite smoothly. So smoothly, that the client wanted to template the application for a second tenant, with the potential for additional tenants. Fortunately, the application was running in its own schema and was tied only loosely to the Liferay DB.

JPA is commonly configured through a persistence.xml file, which is essentially a static reference. While the multiple persistence units could be defined in the persistence.xml file, this would require jar file changes every time a new tenant was created.

Instead, utilizing our persistence base class, we implemented a dynamic override of the persistence.xml defined properties based upon the current tenant context creating an entity manager factory and entity manager for the tenant.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-default", getConfig(tenant));
EntityManager em =  emf.createEntityManager();

We were using application server configured DB connections via JNDI, so the following would change the DB connection utilized for the tenant.

private Map<String, Object> getConfig(String tenant) {
Map<String, Object> configOverrides = new HashMap<String, Object>();
configOverrides.put(“javax.persistence.nonJtaDataSource”, getJdbcName(tenant));
configOverrides.put("eclipselink.logging.file", tenant + “.log”));
return configOverrides;
}

This allowed us to override the JDBC connection used for a tenant as we looked up the JDBC driver by JNDI name. The JNDI name was, by convention, the same as the tenant name, simplifying configuration across the board.

As we were using EclipseLink, this approach also allowed us to split out tenant log files into individual logs per tenant, greatly easing debugging and monitoring of each tenant’s activities.

This same approach can be used with other JPA providers for the configurable vendor specific properties that they expose as well as all the standard JPA properties.

This solution allowed us to clone the entire application instance and bring up a second application with a different target audience with only a small investment in time. Additional applications using the current solution are envisioned and can be brought up with no further development effort, giving a great return on the software and placing our client far in the lead in their market.

Share This