How to deploy two CUBA apps in one tomcat instance

Hi

We manage multi-tenancy with our clients by providing an app+database for each one of them, but in a single tomcat in order to avoid multiplying public IPs.

I try to deploy 2cuba apps on the same tomcat on 2 different contexts but when deploying the 2nd one I have errors when trying to register mbeans, so the deployment stops.

org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [com.haulmont.addon.admintools.core.tomcat.TomcatCore@2a038721] with key 'cuba-at:type=TomcatCore'; nested exception is javax.management.InstanceAlreadyExistsException: cuba-at:type=TomcatCore
at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:628)
at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:550) 

I guess that I have to change mbean configuration in some way but I’m not sure how.

Plus, I’m quite sure that I will have to change other config items for the 2nd app, and guidance would be much appreciated in order not to miss one. Both apps must be hermetically segregated.

Regards
Michael

Hi,

  1. At one change the name from app to another in “Module prefix” from PROJECT PROPERTIES->ADVANCED
  2. Run buildWar and generate the new file war with new name.
  3. Put the file generated in step 1 on webapps tomcat directory server and connect to http://yourserver:8080/“new name from first step”

We need to automate the process, so let me explain what we have for now.

In the single-war-web.xml we have introduced new properties files specific to client/tenant local.{core,web}-app.properties.

    <context-param>
        <description>List of app properties files for Web Client</description>
        <param-name>appPropertiesConfigWeb</param-name>
        <param-value>classpath:com/busy/app/web-app.properties
            classpath:com/busy/app/busy-app.properties
            /WEB-INF/local.app.properties
            /WEB-INF/local.web-app.properties</param-value>
    </context-param>
    <context-param>
        <description>Web resources version for correct caching in browser</description>
        <param-name>webResourcesTs</param-name>
        <param-value>${webResourcesTs}</param-value>
    </context-param>
    <!-- Middleware parameters -->
    <context-param>
        <description>List of app properties files for Middleware</description>
        <param-name>appPropertiesConfigCore</param-name>
        <param-value>classpath:com/busy/app/app.properties
            classpath:com/busy/app/busy-app.properties
            /WEB-INF/local.app.properties
            /WEB-INF/local.core-app.properties</param-value>
    </context-param>

In addition we have an additional properties file for each client/tenant. We have a created a ‘distrimake’ task in build.gradle that generates a war for each client/tenant with specific configuration.

In this war, 3 files are generated in WEB-INF: local.app.properties (global), local.web-app.properties, local.core-app.properties.

For instance for one client/tenant named ‘tenant’ we have
local.app.properties

cuba.logDir = tenant_home/logs
cuba.confDir = tenant_home/${cuba.webContextName}/conf
cuba.tempDir = tenant_home/${cuba.webContextName}/temp
cuba.dataDir = tenant_home/${cuba.webContextName}/work
cuba.dataSourceJndiName = jdbc/CubaDS
cuba.download.directories = ${cuba.tempDir};${cuba.logDir}
cuba.dbDir = web-inf:db
cuba.automaticDatabaseUpdate = false
reporting.openoffice.path = /opt/openoffice4/program
cuba.connectionUrlList = http://localhost:8080/ibusy-core-tenant
cuba.useLocalServiceInvocation = true
cuba.logFile = tenant

local.core-app.properties

cuba.webContextName = ibusy-core-tenant

local.web-app.properties

cuba.webContextName = ibusy-tenant

With all of that normally we should not have any clashes between tenant and, e.g tenant2.

But It seems that for JMX there is additional specific configuration needed for tenant, could you provide guidance on this ?

Hi,

Just for clarity. Do you understand that one single OutOfMemoryError will ruin all your apps simultaneously? Moreover, you will not be able to update Tomcat without downtime for all clients.

It is possible to set up Tomcat as you wish, but there are more advanced techniques for deployment, for instance Docker containers.

Hi Yuriy

Indeed. More precisely the current case is 1 customer with several companies, and the plan is to have 1 single tomcat instance for the client but with 1 app+database per company (currently 2, a 3rd one is coming). For cost reasons client is ok with 1 instance and its consequences.

I have Docker+uberjar in mind for mid-term future, this is our target, but I don’t know how it works yet. So in the meantime, if you could provide guidance on setting up tomcat as intended, that would be great.

EDIT : by guidance I mean how to avoid JMX exception mentionned in OP and any other guidelines you may provide

Hi Michael,

The problem is with the Admin Tools add-on. It’s MBean registration is written in such a way that doesn’t consider the cuba.webContextName property and hence prevents from using multiple times in a single JVM.
We’ll fix it ASAP, see the issue.

1 Like

Thanks Konstantin. I reached the same conclusion and deactivated the mbean in the meantime.