Project setup for a complex multi tenant application

I am considering using your product for a new project. I would like to ask you to illustrate how I can implement our requirements. I follow up on your pet store examples and add the requirements to this.

Let’s say we have a vanilla version of a pet store. We are planning to have around 10 pet stores within the next 2 years. Each pet store will be a “copy” of the vanilla version with some adjustments (customizing). Each copy can have different screens, screen flows, reports, etc. A new pet store (based on the vanilla version) should be available within weeks depending on the complexity (programming new screens, extending the domain model etc).

The end user will select a pet store, logs in and is guided through the application. The user experience is the same across all stores with different deviations. E.g. buying a horse requires more information, feedback cycles, etc. than buying a mouse.

The following questions arise:

  1. How do I best create a pet store based on a vanilla version in Cuba Studio (e.g. copy/paste the vanilla project adjusting the DB-Connection parameter etc.)

  2. How do I best implement multi-tenancy (Cuba Studio Multi tenancy, Oracle VPD, Oracle Multitenant) in connection with question 1.

  3. The domain model (DB schema) must be the same for all pet stores (multi tenant). Although not all pet stores will use the full functionality. The UI-logic can be a copy of the vanilla version, but they all use the same domain (business) objects.

The objective is to have a Java-Project setup with CI-Integration etc. which is cost effective and not to complex to maintain and to support (Java-update, re-test, Cuba updates, staging, schema-updates etc.). The UI-Logic for each pet store should be maintained in the Java project somehow in a separate subproject. Each pet store should be a deployable unit (war file).

Thanks for a feedback and guiding us into the right direction.

Wern

Hi Werner,

first of all welcome to the world of CUBA. Great to E-meet you :=)

Let’s see if I can answer your question from my understanding of your situation:

First I recap what you wrote just to double-check I understand you correct:


You would like to have multiple wars of the petclinic that are similar but not 100% the same. And the adjustments that you want to do are more like the 20% differences, whereas the “core” of 80% or the application is the same, right?

But you would also like to not have a maintenance nightmare and therefore not just copy & paste the complete java code all the time, correct?

Furthermore, you would like to deploy those different petclinic applications in different processes (WARs) (different processes). Should they use the same database or should they have a different one for each “installation”?


So good news: it seems to be totally achievable what you want to do with CUBA.

Here are two blog posts that talk about that situation:

More concretely what would probably a suitable solution is that you can create an application component. This can either be something like an addon (e.g. the data-import or it can also be the “core” part of your project. In the above-mentioned blog post, I called it " 3. Product customizations".

This way you only have the source code of the petclinic once.

Then you create for each customization another app, that only contains the difference. But it is still possible to override the standard behavior of the “core” application. Like Spring beans or also JPA Entities and Screens.

If you have any further questions or need an example - feel free to reach out!

Cheers
Mario

1 Like

Hi Mario

Thanks for the fast feedback and the precise summary, which is absolutely correct!

I think our setup would be like your sherlock product. I like the Extension approach and I think that’s the way to go. The business people would like to have the EAV approach, but I see more the disadvantages.

However, regarding having different databases and WAR files: Like in your Sherlock project we will have a base product but only one customization level for around 10 different products. Each product should be a tenant. I prefer one database and one WAR file. We won’t have to many users (around 300-500 at peak time entering values, attachments etc.).

  1. Would a Cuba based multi tenant based solution be the way to go?
  2. Where can the user decide which tenant to use - at the login screen or afterwards?
  3. A user must be able to choose any tenant (back office user, applicant etc.). This means he always logs in with the same id and password. What does that mean regarding registering the users (we will use idp or SSO etc.)?
  4. You mentioned an example. I would highly appreciate to get one.

Best
Wern

vs.

This is a contradiction, isn’t it? :wink:

But if you have multiple product customizations, how should it work if you have only one database schema? Imagine product customization 1 changes the core module to do X and product customization 2 changes the core module to Y where X and Y incompatible changes? This might be the case for business logic but also for DB schemas and entities.

Do you mean the addon here: Multitenancy – CUBA Platform ?

Which way of multi-tenancy you need depends on do you need 1 vs. multiple wars and also if you need 1 vs. multiple DB schemas / DB servers.

The multitenancy addon is for the situation of 1 war and 1 DB schema from the deployment perspective.
But the multitenancy addon is more focused on the question of separating the data between tenants. It is not a solution for putting 10 different product variants into one war necessarily.

Perhaps you describe a little bit more in the concrete where you would want to do regarding the product customizations. This way we can propose better what a proper solution would be. Perhaps it is going into a tenant direction or perhaps it is more the question of how do you modularize your app.

Cheers
Mario

Hi Mario
I probably I did not fully understood all the points. Let me summarize what I learnt now:

  1. We will develop in a base component as a Cuba Extension which includes Domain Objects, Screens, Reports, Navigation Logic etc.
  2. If we have 10 stores I will have 10 Cuba-based Java projects which uses/references our base component. Each project will override/extend whatever is required.
  3. The schema is generated and each store will have its own DB schema and a WAR file

Let me know if my understanding is correct so far. Anyway, if I have more information I will approach you soon.

Best Wern

Yes, this is exactly how you can use application components. The article I linked from the CUBA blog contains the old wording of “Extensions”. Nowadays they are called “application components” - but the mechanism is the same. Take a look at the docs: CUBA application components.

Probably I misunderstood you before where you said: “I prefer one database and one WAR file.”. You mean you would prefer one DB and one WAR for each store, right?

That being said: It is also possible to run in different modes. E.g. where you have only one DB for all your shops. This would be more the situation for the Multitenancy addon.

Where can the user decide which tenant to use - at the login screen or afterwards?

A user must be able to choose any tenant (back office user, applicant etc.). This means he always logs in with the same id and password. What does that mean regarding registering the users (we will use idp or SSO etc.)?

Regarding login, this will become a little bit more complicated when you have multiple wars, as you basically have multiple applications that are independent at runtime. But CUBA has also support for such an SSO case. See the docs here.

I will prepare an example based on the Petclinic project later so that you can take a look at how it works.

Cheers
Mario

Hi Mario
Thanks a lot for your effort! I am looking forward for the example.
Wern

Hi @werner.schnedl1,

I have added the following example: GitHub - mariodavid/cuba-petclinic-product-customizations: CUBA example that shows how to use application components for creating Product customizations
If you want to run a particular application, you have to download the git repository and then open one of the projects of the corresponding subdirectories.

In the README you find information about the project.

The idea is the following:

There are three directories, petclinic-core and two apps that are using the petclinic and extend that with customizations: rocky-mount-petclinic and lancaster-petclinic.

90% of the logic sits in the petclinic-core project. The adjustments are made in the different customer-specific apps.

When a change is needed on the petclinic-core project the following workflow should be used:

  1. start the petclinic-core project as a CUBA app
  2. make the changes required
  3. test the changes (manually / automated)
  4. perform a gradlew install to update the SNAPSHOT release in your local maven repository

As the apps use the snapshot versions directly, next time you start the different applications, you will see the changes in the apps.

Both applications for lancaster and rocky-mount are running totally independent form each other. You can create for each project a war file. Each of them are using a dedicated database schema. With that the data of the two applications is completely isolated from each other.

I hope this helps to understand how conceptually the concept of application components works.

Cheers
Mario

1 Like

Hi Mario,

Is it possible for cuba framework to have single instance of application and host multi-tenant not only with different data but also with different model (e.g. dynamically decide which extended class should be use by tenant) ?

Hi,

what do you mean in the concrete by “different model”? Are you talking about different tenant-specific sub-classes of a concept (like Customer or Order) or are you talking about totally different entities?

Generally speaking: yes, this is possible. There are different solutions to such a situation. There is the possibility when using the multi-tenancy addon to programmatically determine which tenant is currently active. This way it is possible to differentiate in the source code which screens to show, which entities to create etc.

Furthermore, there is the possibility to use dynamic attributes to store different information without defining those in the source code.

So it seems possible but requires more invasive integration into your own app source code.
It has also not very much to do with application components, as those are static by nature.

Cheers
Mario

Hi Mario,

Sorry for my bad explanation XD. I describe the circumstances again by sample code may be more clear.

If my application serve two tenants: T1 and T2.
T1 need a customized column ‘Column1’ on ‘User’, but T2 need ‘Column2’, so I create two classes that extends ‘User’:

@Entity(name = "ext$User1")
@Extends(User.class)
public class ExtUser1 extends User {
    @Column(name = "COLUMN1", length = 100)
    private String column1;
}

@Entity(name = "ext$User2")
@Extends(User.class)
public class ExtUser2 extends User {
    @Column(name = "COLUMN2", length = 100)
    private String column2;
}

I wonder if it is possible for cuba framework to dynamically create different ‘User’ instance for different tenants, such as:

User user = metadata.create(User.class); // it returns ExtUsers1 for T1 and ExtUsers2 for T2

Greg

Hi,

Yes this is possible. But you can use standard entity inheritance for that.

Here you can read about general entity inheritance here: https://www.cuba-platform.com/guides/data-modelling-entity-inheritance

@Extends is only used if you want to replace one entity completely in your app that comes from the platform or an app components. You can only use it once for a given entity.

Perhaps you describe a more detailed example scenario and then I can provide you an example app showing how I would solve it.

Cheers
Mario