Shared multi-tenant processes configuration for JEE/CDI/Wildfly

Hi,

I have a Camunda setup on Wildfly/JEE/CDI and need to configure multi-tenancy (for potentially thousands of tenants). Each tenant will share process definitions.

In the Camunda online documentation I can find the configuration instructions for Spring, but nothing for JEE/CDI.

From the Spring config docs, it is necessary to create a custom TenantIdProvider, and configure this in the camunda.cfg.xml, which as far as I can tell is a Spring only configuration file.

Does anyone know how to do this using CDI or the JEE Process Engine Configuration?

Thanks for the help,
Franz

Hi Franz,

what documentation did you look at exactly?

Did you have a look at https://docs.camunda.org/manual/7.10/user-guide/process-engine/multi-tenancy/?
It also links to examples you can easily use in your setup.

Hope that helps!

Best,
Tobias

Hello Tobias,

Thanks, yes this is the exact page of documentation I am using.

For shared processes, the documentation explains how to create a CustomTenantIdProvider which I have done. However the CustomTenantIdProvider needs to be registered with the Process Engine Configuration during startup.

The document explains how to bootstrap this in Spring with the camunda.cfg.xml but not for the JEE environment.

I assume that I have to do this in the Wildfly standalone.xml process engine definition section:

<process-engine name="default" default="true">
  <datasource>java:jboss/datasources/ProcessEngine</datasource>
  <history-level>full</history-level>
  <properties>
<property name="jobExecutorAcquisitionName">default</property>
<property name="isAutoSchemaUpdate">true</property>
<property name="authorizationEnabled">true</property>
<property name="jobExecutorDeploymentAware">true</property>
  </properties>
</process-engine>

but I cannot find any documentation on how to do this, and also how to register the tenantIdProvider bean.

Essentially I need the equivalent JBoss/Wildfly version of the camunda.cfg.xml file:

<beans>
  <bean id="processEngineConfiguration" class="org.camunda.bpm.engine.impl.cfg.StandaloneProcessEngineConfiguration">
    <!-- ... -->
    
    <property name="tenantIdProvider" ref="tenantIdProvider" />
  </bean>
  
  <bean id="tenantIdProvider" class="org.camunda.bpm.CustomTenantIdProvider">
</beans>

Hi @Franz,

the most easy way to package the TenantIdProvider for Wildfly is to create a process engine plugin, as stated in the last sentence in the documentation.

Here is a section about adding ProcessEnginePlugins to the configuration of a shared engine in Wildfly: https://docs.camunda.org/manual/latest/user-guide/runtime-container-integration/jboss/#extend-a-process-engine-using-process-engine-plugins.

Hope this helps, Ingo

Hi Ingo,

It’s taken me some time to circle back to this issue which was on the backburner for a while but now is active again.

I’m really struggling to configure this CustomTenantIdProvider in wildfly. What I’ve tried so far:

In the process-engine subsystem in standalone.xml I have the following configured:

   <process-engines>
        <process-engine name="default" default="true">
            <datasource>java:jboss/datasources/ProcessEngine</datasource>
            <history-level>full</history-level>
            <properties>
                <property name="jobExecutorAcquisitionName">default</property>
                <property name="isAutoSchemaUpdate">false</property>
                <property name="authorizationEnabled">true</property>
                <property name="jobExecutorDeploymentAware">true</property>
            </properties>
				<plugins>
					<plugin>
					    <class>com.myproject.camunda.CustomTenantIdProvider</class>
					</plugin>
				</plugins>
        </process-engine>
    </process-engines>

Now the problem is where to locate the CustomTenantIdProvider class.
I tried putting it in my project war file, but wildfly complains on startup that it can’t find the class. The camunda documentation warns against this situation, provides a hint on how to fix it, but unfortunately not any more than that.

Module dependency of custom configuration class
If you configure the process engine in standalone.xml and provide a custom configuration class packaged inside an own module, the camunda-jboss-subsystem module needs to have a module dependency on the module providing the class.

I realise that this is probably a wildfly question, but perhaps you can provide me with some more direction please.

  • I created a jar file with just the com.myproject.camunda.CustomTenantIdProvider.class in it.
  • I then created a module.xml with:
<?xml version="1.0" ?>
<module xmlns="urn:jboss:module:1.1" name="com.myproject.camunda">
    <resources>
        <resource-root path="camunda-1.0.jar"/>
    </resources>
    <dependencies>
        <module name="org.camunda.bpm.engine"/>
    </dependencies>
</module>
  • These two files are copied into modules/com/myproject/camunda/main
  • When starting willdfly there is an error on startup which says the camunda subsystem can’t find the CustomTenantIdProvider class.
  • So I then went in to the camunda module.xml at modules/org/camunda/bpm/wildfly/camunda-wildfly-subsystem/main/module.xml and added in the following dependency:
<module name="javax.api" />
<module name="javax.transaction.api" />
<module name="javax.enterprise.api" />
<module name="javax.inject.api" />

<module name="org.jboss.staxmapper" />
<module name="org.jboss.as.controller" />
<module name="org.jboss.as.threads" />
<module name="org.jboss.threads" />
<module name="org.jboss.as.server" />
<module name="org.jboss.modules" />
<module name="org.jboss.msc" />
<module name="org.jboss.logging" />
<module name="org.jboss.vfs" />
<module name="org.jboss.jandex" />
<module name="org.jboss.weld.spi" />
<module name="org.jboss.weld.api" />
<module name="org.jboss.weld.core" />
<module name="org.jboss.as.weld" />
<module name="org.jboss.as.naming" />
<module name="org.jboss.as.connector" />
<module name="org.jboss.as.ee" />
<module name="org.jboss.as.ejb3" />
<module name="org.jboss.metadata" />
<module name="org.jboss.as.web" />
<module name="org.jboss.as.web-common" />
<module name="org.jboss.invocation" />

<module name="org.camunda.bpm.camunda-engine" />
<module name="org.camunda.bpm.identity.camunda-identity-ldap" />
<module name="org.camunda.bpm.camunda-engine-plugin-spin" services="import" />
<module name="org.camunda.bpm.camunda-engine-plugin-connect" />

<module name="org.camunda.bpm.camunda-engine-plugins" optional="true" />

<!-- for LDAP plugin only -->
<module name="sun.jdk" />
<module name="com.myproject.camunda" />	
  • Still no luck starting wildfly - fails with a org.camunda.bpm.engine module load error.

Any ideas welcome please. I’m not even sure if I’m on the right track here, because this level of config is getting really messy just to support multi-tenancy in camunda.
Thanks

I’ve now also tried putting the CustomTenantIdProvider into a Process engine plugin:

public class CustomTenantIdProviderProcessEnginePlugin extends AbstractProcessEnginePlugin {

    public void preInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
        processEngineConfiguration.setTenantIdProvider(new CustomTenantIdProvider());
    }

    public void postInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
    }
}

and configuring it in standalone.xml like:

        <process-engine name="default" default="true">
            <datasource>java:jboss/datasources/ProcessEngine</datasource>
            <history-level>full</history-level>
            <properties>
                <property name="jobExecutorAcquisitionName">default</property>
                <property name="isAutoSchemaUpdate">false</property>
                <property name="authorizationEnabled">true</property>
                <property name="jobExecutorDeploymentAware">true</property>
                <!-- this doesnt work! property name="tenantIdProvider">com.myproject.camunda.CustomTenantIdProvider</property -->
            </properties>
				<plugins>
					<plugin>
						<!--class>com.myproject.camunda.CustomTenantIdProvider</class-->
						<class>com.myproject.camunda.CustomTenantIdProviderProcessEnginePlugin</class>							
					</plugin>
				</plugins>
        </process-engine>

The module.xml is:

<module xmlns="urn:jboss:module:1.1" name="com.myproject.camunda">
    <resources>
        <resource-root path="camunda-1.0.jar"/>
    </resources>
    <dependencies>
		<module name="org.camunda.bpm.model.camunda-engine" services="import"/>
    </dependencies>
</module>

I also add the following to the camunda-engine-plugins module.xml

<module xmlns="urn:jboss:module:1.0" name="org.camunda.bpm.camunda-engine-plugins">
  <dependencies>
    <!-- Add custom engine plugins here -->
    <!-- <module name="org.camunda.bpm.camunda-custom-engine-plugin" export="true" /> -->
	    <module name="com.myproject.camunda" export="true"/>	
  </dependencies>
</module>

But when starting wildfly I get the errors:

16:07:19,916 WARN  [org.jboss.modules.define] (ServerService Thread Pool -- 85) Failed to define class com.myproject.camunda.CustomTenantIdProviderProcessEnginePlugin in Module "com.myproject.camunda" from local module loader @74c79fa2 (finder: local module finder @1e0f9063 (roots: C:\programs\wildfly-16.0.0.Final\wildfly-16.0.0.Final\modules,C:\programs\wildfly-16.0.0.Final\wildfly-16.0.0.Final\modules\system\layers\base,C:\programs\wildfly-16.0.0.Final\wildfly-16.0.0.Final\modules\system\add-ons\ispn)): org.jboss.modules.ModuleLoadError: org.camunda.bpm.model.camunda-engine
        at org.jboss.modules.Module.addPaths(Module.java:1266)
        at org.jboss.modules.Module.link(Module.java:1622)
        at org.jboss.modules.Module.getPaths(Module.java:1583)
        at org.jboss.modules.Module.getPathsUnchecked(Module.java:1606)
        at org.jboss.modules.Module.loadModuleClass(Module.java:726)
        at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:247)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
        at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
        at java.base/java.lang.ClassLoader.defineClass1(Native Method)
        at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
        at org.jboss.modules.ModuleClassLoader.doDefineOrLoadClass(ModuleClassLoader.java:423)
        at org.jboss.modules.ModuleClassLoader.defineClass(ModuleClassLoader.java:555)
        at org.jboss.modules.ModuleClassLoader.loadClassLocal(ModuleClassLoader.java:339)
        at org.jboss.modules.ModuleClassLoader$1.loadClassLocal(ModuleClassLoader.java:126)
        at org.jboss.modules.Module.loadModuleClass(Module.java:731)
        at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:247)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
        at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController.createInstance(MscManagedProcessEngineController.java:224)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController.addProcessEnginePlugins(MscManagedProcessEngineController.java:189)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController.startProcessEngine(MscManagedProcessEngineController.java:175)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController$2.run(MscManagedProcessEngineController.java:131)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController$2.run(MscManagedProcessEngineController.java:129)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.util.Tccl.runWithTccl(Tccl.java:53)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.util.Tccl.runUnderClassloader(Tccl.java:45)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController.startInternal(MscManagedProcessEngineController.java:129)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController$1.run(MscManagedProcessEngineController.java:90)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1348)
        at java.base/java.lang.Thread.run(Thread.java:834)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.JBossThread.run(JBossThread.java:485)

16:07:19,931 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 85) MSC000001: Failed to start service org.camunda.bpm.platform.process-engine.default: org.jboss.msc.service.StartException in service org.camunda.bpm.platform.process-engine.default: org.jboss.modules.ModuleLoadError: org.camunda.bpm.model.camunda-engine
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController$1.run(MscManagedProcessEngineController.java:97)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1348)
        at java.base/java.lang.Thread.run(Thread.java:834)
        at org.jboss.threads@2.3.3.Final//org.jboss.threads.JBossThread.run(JBossThread.java:485)
Caused by: org.jboss.modules.ModuleLoadError: org.camunda.bpm.model.camunda-engine
        at org.jboss.modules.Module.addPaths(Module.java:1266)
        at org.jboss.modules.Module.link(Module.java:1622)
        at org.jboss.modules.Module.getPaths(Module.java:1583)
        at org.jboss.modules.Module.getPathsUnchecked(Module.java:1606)
        at org.jboss.modules.Module.loadModuleClass(Module.java:726)
        at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:247)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
        at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
        at java.base/java.lang.ClassLoader.defineClass1(Native Method)
        at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
        at org.jboss.modules.ModuleClassLoader.doDefineOrLoadClass(ModuleClassLoader.java:423)
        at org.jboss.modules.ModuleClassLoader.defineClass(ModuleClassLoader.java:555)
        at org.jboss.modules.ModuleClassLoader.loadClassLocal(ModuleClassLoader.java:339)
        at org.jboss.modules.ModuleClassLoader$1.loadClassLocal(ModuleClassLoader.java:126)
        at org.jboss.modules.Module.loadModuleClass(Module.java:731)
        at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:247)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
        at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController.createInstance(MscManagedProcessEngineController.java:224)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController.addProcessEnginePlugins(MscManagedProcessEngineController.java:189)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController.startProcessEngine(MscManagedProcessEngineController.java:175)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController$2.run(MscManagedProcessEngineController.java:131)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController$2.run(MscManagedProcessEngineController.java:129)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.util.Tccl.runWithTccl(Tccl.java:53)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.util.Tccl.runUnderClassloader(Tccl.java:45)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController.startInternal(MscManagedProcessEngineController.java:129)
        at org.camunda.bpm.wildfly.camunda-wildfly-subsystem@7.10.0//org.camunda.bpm.container.impl.jboss.service.MscManagedProcessEngineController$1.run(MscManagedProcessEngineController.java:90)

I found the problem, I had

instead of

in my module.xml.

Wildfly is now starting without errors. I now have to test if the CustomIdProvider works…

Hi @Franz , were you able to make it run, I am struggling with exact same issue - we are trying to customize the vanila camunda docker image, which is running camunda in tomcat… I would very much appreciate any help on this topic