cancel
Showing results for 
Search instead for 
Did you mean: 

Multi tenancy support

feldmani
Champ in-the-making
Champ in-the-making
Hi,
I would like to install the Activiti engine embedded in an application that supports multi-tenant environment (offering a Software As A Service for several customers on the same DB).
Is there a way / somebody who already did this?

thanks,
Nir
31 REPLIES 31

jbarrez
Star Contributor
Star Contributor
That's not supported out of the box.
It might be we look into this in the near future, but nothing is decided in that direction yet.

frederikherema1
Star Contributor
Star Contributor
The alfresco-integration has some notion of multi-tennancy. It prefixes all process-definitions keys with a certain tennant domain. When fetching all possible workflows to start, these are filtered out, based on the domain of the logged in user. All other functionality is covered by alfresco (eg. user's, content, …), so nothing as Joram says, there is currently no out-of-the box support.

jpalomaki
Champ in-the-making
Champ in-the-making
Related to multitenancy, how does Activiti run a process? Does a process only advance within a user transaction (submit start form or task data) on the current thread, or can processes advance asynchronously?

I'm asking this because we've implemented DB multitenancy using a DataSource wrapper that can route DB queries (including those executed by Activiti) to tenant-specific DataSources (DBs). Would such a DataSource wrapper work with Activiti? Simply put, we store tenant information in a thread local which is then inspected by the DataSource wrapper in order to decide which tenant DataSource to route queries to…

If asynchronous process execution is possible, we could probably also set tenancy (for the current thread) manually by calling Java methods via expressions #{tenancyResolver.setTenancy("tenant1")} in the particular asynchronous step in the process? Obviously this would require us to store tenant-information in process variables when it is first start up (within a user transaction).

Thanks,
Jukka

heymjo
Champ on-the-rise
Champ on-the-rise
I'm interested in this as well, see http://forums.activiti.org/en/viewtopic.php?f=6&t=1593

My conclusion then was that we cannot keep strictly separate different organizations on the same activiti database. Even if you have a routing or proxying datasource the underlying datasources would still need to be present in the app server and could still be looked up from jndi by the application AFAICT. And even if your appserver has policies where you secure and link a datasource to an application then consider that this datasource still has access to the complete schema and with simple SQL statements could peek in other workflows' data. In short, we went for the one-schema-per-application approach.

Jorg

frederikherema1
Star Contributor
Star Contributor
Activiti's timers and jobs are executed asynchronously. If you have a datasource that is tenant-aware, you could always add an extra interceptor to the commandExecutor activiti uses internally, which get called before any request to the activiti DB is done.

As heymjo states, using a proxy still "exposes" your datasource somewhere in your app-server or spring-context, which gives you no guarantees. Off course, if you have full control of what runs on your server, imho this is perfectly acceptible.

jpalomaki
Champ in-the-making
Champ in-the-making
Thanks for your responses.

Just for the record, we are building a multitenant application that would utilize Activiti BPMS (vs. sharing an Activiti instance by multiple unrelated applications).

@heymjo: We would have separate (Activiti) databases for each tenant. Activiti just happens to query the right one when a process is initiated or updated (via the DataSource wrapper/proxy). And we do have full control of the applications that utilize Activiti and which are run on our server. So we should not have any trouble there.

@frederikhermans: Thanks for the tip, using an interceptor (vs. explicit tenant-related expressions) sounds right to me. However, we would still need to know which tenant DB to forward the request to, so we would most likely need to put tenant information in process metadata anyways, and have the interceptor read that?

Cheers,
Jukka

frederikherema1
Star Contributor
Star Contributor
Indeed, your interceptor should be aware of the current user (can do that using the Authentication object in activiti) and potentially inspect all commands it will execute, for tenant-specific data…

jpalomaki
Champ in-the-making
Champ in-the-making
Further question,

If we use a routing DataSource wrapper to achieve multitenancy (as described above), will we run into any trouble with caching within the Activiti engine?

For instance, say, if user details were cached in-memory, we might run into trouble when two tenants had a user with the same username (in which case a cached lookup for that user might return invalid user information).

What does the Activiti engine cache (if anything)?

Thanks,
Jukka

jbarrez
Star Contributor
Star Contributor
The engine only caches process definitions. So if you make sure there are no clashes related to process ids/keys you're all safe.