About Markus Eisele

Markus is a principal technology consultant working for msg systems ag in Germany. Markus is a software architect, developer and consultant. He also writes for IT magazines. Markus is speaking at different conferences about his favorite topics. He is also part of the Java EE 7 expert group.

Sneak peak at Java EE 7 – Multitenant Examples with EclipseLink

The Aquarium is a great source of inspiration and most recent information about Java EE progress across all relevant specifications and reference implementations. They picked up a presentation by Oracle’s Shaun Smith (blog/twitter) about the status and future of EclipseLink as an open source project. He covers all the new features which are going to be in EclipseLink 2.4 which will be availabke along with the June Eclipse Juno Release. In detail these are REST, NoSQL and Multitenancy. (details refer to the complete slide-deck (PDF) from the marsjug event.)

I like to see that EclipseLink still is the center of innovation in Java persistence and they are trying hard to adopt latest buzz timely. Working for a more conservative industry in general the main new feature I am looking for is multitenancy. What you can guess from the slides is, that something in this field should already be working with latest EclipseLink 2.3.0.

What is Multitenancy going to look like?
Let’s start looking at what Oracle’s Linda DeMichiel announced at last years JavaOne (compare blog-post) and also let’s look at what the early draft (PDF) of the JPA 2.1 specification has to offer. The easier part is the early draft. Not a single line mentions “Multitenan[t|cy]” in any context. So, this is obviously still a big to do for further iterations. A bit more could be found in the JavaOne Strategy Keynote (Slides 41,42) and the JavaOne Technical Keynote (PDF) (Slide 25). The general Java EE 7 approach will be to have support for separate isolated instances of the same app for different tenants. The mapping should be done by the container and be available to apps in some way. This is all very vague until today and the only concrete code examples available from the slides refer to some obvious JPA related examples using two annotations @Multitenant and @TenantDiscriminatorColumn. Hmm. Doesn’t this look familiar to you?

What is possible today?
It does! EclipseLink (as of 2.3.0 – Indigo) supports shared multitenant tables using tenant discriminator column(s), allowing an application to be re-used for multiple tenants and have all their data co-located. All tenants share the same schema without being aware of one another and can use non-multitenant entity types as per usual. But be aware of the fact, that this is only one possible approach to multitenancy for data. This is commonly referred to as “dedicated database” because all tenant’s data go into one single db! The basic principles for the following are:
- application instances handle multiple tenants
- caching has to be isolated for every tenant by JPA
You can look at all the details on a dedicated EclipseLink wiki page. Want to give it a test drive? let’s start. Prerequisites as usual (NetBeans, GlassFish, MySQL, compare older posts if you need more help.). Make sure to have the right EclipseLink dependencies (at least 2.3.0)! Create a new entity via the wizard, setup your datasource and persistence.xml and call it e.g. Customer.

@Entity
public class Customer implements Serializable {
//...
}

If you start your app you see EclipseLink creating something like this in your database.

Let’s make this a multitenant entity. Add the following annotations:

@Entity
@Multitenant
@TenantDiscriminatorColumn(name = "companyId", contextProperty = "company-tenant.code")
public class Customer implements Serializable {
//...
}

There are multiple usage options available for how an EclipseLink JPA persistence unit can be used in an application with @Multitenant entity types. Since different tenants will have access to only its rows the persistence layer must be configured so that entities from different tenants do not end up in the same cache. If you compare the detailed approaches (Dedicated PC, PC per tenant, PU per tenant) in more detail, you see, that as of today you end up having two possible options with container managed injection of either the PC or the PU. Let’s try the simplest thing first.

Dedicated Persistence Unit
In this usage there is a persistence unit defined per tenant and the application/container must request the correct PersistenceContext or PersistenceUnit for its tenant. There is one single persistence unit and nothing is shared. Go with the above example and add the following property to your persistence.xml:

<property name="company-tenant.code" value="TENANT1" />

Give it a try and compare the tables.

As you can see, you now have your companyId column. If you insert some data it will always be filled with the property value you assigned in the persistence.xml. Use either a @PersistenceContext or a @PersistenceUnit to access your entities. Using this approach you have a shared cache as usual for your application.

@PersistenceContext with Shared Cache (Source: S.Smith)

Persistence Context per Tenant
If you don’t want to have a single tenant per application you could decide to have a single persistence unit definition in the persistence.xml and a shared persistence unit (EntityManagerFactory and cache) in you application. In this case the tenant context needs to be specified per EntityManager at runtime. In this case you have a shared cache available for regular entity types but the @Multitenant types must be protected in the cache. You do this by specifying some properties:

@PersistenceUnit
EntityManagerFactory emf;
Map props = new HashMap();
props.put("company-tenant.code", "TENANT2");
props.put(PersistenceUnitProperties.MULTITENANT_SHARED_EMF, true);
EntityManager em = emf.createEntityManager(props);
Shared @PersistenceUnit per tentant (Source: S.Smith)

Discriminator Approaches
The above examples work with a single discriminator tenant column. You can add the discriminator column to the PK by specifying a primaryKey attribute like the following:

@TenantDiscriminatorColumn(name = "companyId", contextProperty = "company-tenant.code", primaryKey = true)

It’s also possible to have multiple tenant discriminator columns using multiple tables if you do something like this:

@Entity
@SecondaryTable(name = "TENANTS")
@Multitenant
@TenantDiscriminatorColumns({
    @TenantDiscriminatorColumn(name = "TENANT_ID", contextProperty = "company-tenant.id", length = 20, primaryKey = true),
    @TenantDiscriminatorColumn(name = "TENANT_CODE", contextProperty = "company-tenant.code", discriminatorType = DiscriminatorType.STRING, table = "TENANTS")
})

This leads to a secondary tenants table.

Additional Goodies
As always you can do the complete configuration within your persistence.xml only, too. For a reference please look at the already mentioned wiki page. One last thing is of interest. You could also map the tenant discriminator column with your entity. You simple have to make sure it isn’t updated or inserted.

@Basic
   @Column(name = "TENANT_ID", insertable = false, updatable = false)
   private int tenantId;
 
   public int getTenantId() {
       return tenantId;
   }

Looking at the debug output you can see what is happening behind the scenes:

INFO: Getting EntityManager
INFO: Inserting Test Customer
FEIN: INSERT INTO CUSTOMER (ID, TENANT_ID) VALUES (?, ?)
bind => [1, 2]
FEIN: INSERT INTO TENANTS (ID, TENANT_CODE) VALUES (?, ?)
bind => [1, TENANT2]
FEIN: SELECT t0.ID, t1.TENANT_CODE, t0.TENANT_ID, t1.ID FROM CUSTOMER t0, TENANTS t1 WHERE (((t1.ID = t0.ID) AND (t1.TENANT_CODE = ?)) AND (t0.TENANT_ID = ?))
bind => [TENANT2, 2]

Curious for more Java EE 7 and JPA 2.1 goodies? Keep updated with the development status wiki page for the EclipseLink JPA 2.1 project.

Reference: Sneak peak at Java EE 7 – Multitenant Examples with EclipseLink from our JCG partner Markus Eisele at the Enterprise Software Development with Java blog.

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

Leave a Reply


five − 1 =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

15,153 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books