15

I have an existing Java EE 6 application (deployed in Glassfish v 3.1) and want to support multiple tenants. Technologies/APIs I'm currently using in my app are

  • EJB (including the EJB timer service)
  • JPA 2.0 (EclipseLink)
  • JSF 2.0
  • JMS
  • JAX-RS
  • I plan to use CDI as well

As far as I know, adding multi-tenancy support affects only the persistence layer. My question: Has anybody done this before? What are the steps to convert the application? Will this affect other layers other than persistence?

There will be a high number of tenants, therefore, all data will reside in the same DB schema.

Theo
  • 3,074
  • 7
  • 39
  • 54
  • 2
    This question presumes that 'multi-tenant' is a completely well-defined term of art. It is not. There are many degrees of separation, security, and whatnot that trade off against each other, and plenty of coding approaches that make all of them easier or harder. – bmargulies Jul 03 '11 at 17:42
  • The question already states that there will be a high number of tenants and that all data should/can reside in the same DB schema. I'd think that's specific enough to come up with a few approaches (one or two). – Theo Jul 06 '11 at 20:46
  • please provide fully information of your question and others that you want . – Rahul Mandaliya Jul 06 '11 at 13:18
  • Sorry, didn't get that. What information do you need? – Theo Jul 06 '11 at 20:47
  • In addition to what user Damo has provided, I strongly recommend you refer to this [document](http://msdn.microsoft.com/en-us/library/aa479086.aspx) – Aravind Yarram Jul 06 '11 at 03:34

4 Answers4

4

Persistence Layer

Start with the persistence layer. Roll upwards through your architecture once you have that done.

The Schema that you are proposing would have an ID that identifies the tenant (eg. TenantId). Each table would have this ID. In all of your queries you would have to ensure that the TenantId matches the logged in User's TenantId.

The difficulty with this is that it is a very manual process.

If you go with Hibernate as your JPA provider then there are some tools that will help with this; namely Hibernate Filters.

These are commonly used to restrict access on multi-tenant Schemas (see here and here for some more)

I haven't used EclipseLink but it does look like it has good support for Multi-Tenancy as well. The DiscriminatorColumn looks like a very similar concept to Hibernate Filters.

Service Layer

I assume that you're using JAX-RS and JMS for a Service Layer. If so then you will also need to think about how you are going to pass the tenantId around and authenticate your Tenants. How are you going to prevent one tenant from accessing the REST service of another? Same thing for JMS.

UI Layer

You are going to have to hook up your login in your UI to a Bean (Hibernate or Eclipselink) that sets the TenantId for the Filter/Discriminator.

Community
  • 1
  • 1
Damo
  • 11,410
  • 5
  • 57
  • 74
0

Tell us about the number and the degree of separation and customization necessary for different tenants.

If you have a small number of tenants, I would propose to create a customizable "white-label" product. This gives you the opportunity to create some specific things for one tenant without overcomplexing matters. Plus, separating the applications per tenant helps you in maintenance. We did this for a product with a handful of different tenants.

If you have many tenants, this is of course no longer practical. We did a generic version of the same product. All we did then was distinguish tenants by id after login, thus separating the data from others. But still, there was nothing to do in terms of changing the application or a layer within, the id was all what was needed to separate the data and the workflow is automatically separated by having different instances of beans or other managed objects.

Alexander Rühl
  • 6,769
  • 9
  • 53
  • 96
  • There will be no tenant-specific customization. But how would the "white-label" approach would work, though? What exactly do you mean? Regarding the tenant-id: so that means all I have to do is include the tenant ID column into every JPA entity. I guess the tenant ID needs to be part of the primary key, right? – Theo Jun 28 '11 at 09:40
  • 1
    White-label means in that case that you create a software without any logos, special design and customer specific features. Then you customize it per tenant, so it looks like their own. In your case, when you say you don't need cusomization, you only need to clearly separate the data of each tenant. For that you have several possibilities, one would be to add tenant ID to certain (surely not all) JPA entities. It does not necessarily have to be in the primary key (since I prefer having technical primary keys), you can also add a foreign key to some root objects and go on from their. – Alexander Rühl Jun 29 '11 at 14:12
0

There's several ways you can go with this, depending on the level of separation you want to achieve and how many concurrent tenants you want to support. At one extreme, you can create a new schema for each tenant and therefore ensure database-level isolation of data. For most practical purposes it's usually sufficient to have a logical partitioning of your data by assigning a tenant_id to every entity in your domain model and maintaining foreign-key constraints. Of course this means you'll probably want to always pass in your current session's tenant_id to every query / finder method so that it can restrict the data set based on that. You'll want to make sure that users cannot access another tenant's data by entering a tenant id (or a entity id) that does not belong to them in url.

Abdullah Jibaly
  • 53,220
  • 42
  • 124
  • 197
0

Go message oriented.

If you choose messaging as the strategic approach and refactor (if necessary) business logic around JMS, then other options remain viable and locally applicable.

With this approach, you pay a specific fixed cost (refactor) in your existing (single tenant) system. You then can apply approaches of various degrees of complexity, ranging from simple sharding (@Geziefer's id based association) to a full blown shared-core-schema + extended-tenant-specific-schemas approach, without impacting system architecture and additional refactoring.

You will further have orthogonal control over your system data flows via the messaging layer (applying routers, filters, special processing paths, etc.)

[edit per request]

There is nothing per se in M.T. that explicitly suggests message orientation. But as a general problem, we are looking at widening interfaces, and enriched data flows. Per an API based approach, you would need to carefully inject the appropriate the tenant discriminant in all required interfaces (e.g. methods). A message based (or alternatively a context based API approach) allows for a normative (stable) interface (e.g. message.send()) and at the same allows for explicit specialized data flows. If switching to a message based backbone is not on the table, you are strongly suggested to consider injecting a uniform context (e.g. "RequestContext") param in your APIs. This single extension should cover all your future specialization needs.

alphazero
  • 27,094
  • 3
  • 30
  • 26
  • Benefit of message based architecture in context of shared memory architectures and multi-core is an additional bonus. – alphazero Jul 03 '11 at 17:01
  • Can you please elaborate. How does JMS or a message-oriented system help me with multi-tenancy? – Theo Jul 03 '11 at 21:13
  • @alphazero I agree with Theo. What has JMS to do with multi-tenancy? – Theo Jul 06 '11 at 20:50
  • Messaging, Pete, not JMS. JMS since he already uses it. I disagree that MT is merely a matter of persistence. That logic applies to your entire domain as well but you will note you have other matter besides a DB involved. As for why messaging, see post edit above. – alphazero Jul 07 '11 at 00:15