Hi ,
I am trying to Multi Tenancy support Implementation using Spring Web MVC Project with multiple Processing engine against the Separate Schema,
Following is “BPM-Platform.xml” file:
<?xml version="1.0" encoding="UTF-8"?> default org.camunda.bpm.engine.impl.cfg.StandaloneProcessEngineConfiguration<datasource>java:jdbc/ProcessEngine</datasource>
<properties>
<property name="databaseTablePrefix">TENANT1.</property>
<property name="history">full</property>
<property name="databaseSchemaUpdate">update</property>
<property name="authorizationEnabled">true</property>
<property name="jobExecutorDeploymentAware">true</property>
<property name="jobExecutorActivate">true</property>
</properties>
<plugins>
<!-- plugin enabling Process Application event listener support -->
<plugin>
<class>org.camunda.connect.plugin.impl.ConnectProcessEnginePlugin</class>
</plugin>
<plugin>
<class>org.camunda.bpm.application.impl.event.ProcessApplicationEventListenerPlugin</class>
</plugin>
<plugin>
<class>org.camunda.spin.plugin.impl.SpinProcessEnginePlugin</class>
</plugin>
default
org.camunda.bpm.engine.impl.cfg.StandaloneProcessEngineConfiguration
java:jdbc/ProcessEngine
<properties>
<property name="databaseTablePrefix">TENANT2.</property>
<property name="history">full</property>
<property name="databaseSchemaUpdate">update</property>
<property name="authorizationEnabled">true</property>
<property name="jobExecutorDeploymentAware">true</property>
<property name="jobExecutorActivate">true</property>
</properties>
<plugins>
<!-- plugin enabling Process Application event listener support -->
<plugin>
<class>org.camunda.connect.plugin.impl.ConnectProcessEnginePlugin</class>
</plugin>
<plugin>
<class>org.camunda.bpm.application.impl.event.ProcessApplicationEventListenerPlugin</class>
</plugin>
<plugin>
<class>org.camunda.spin.plugin.impl.SpinProcessEnginePlugin</class>
</plugin>
Below is Application Context File(i.e. LoanApplicationContext .Java) :
@Configuration
@ComponentScan(“org.camunda.bpm.getstarted.loanapproval”)
@EnableWebMvc
public class LoanApplicationContext implements ApplicationContextAware {
@Autowired
private Environment env;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private Tenant tenant;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Bean
SpringBeansResolverFactory springBeansResolverFactory() {
return new SpringBeansResolverFactory(this.applicationContext);
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(“org.postgresql.Driver”);
//dataSource.setUrl(“jdbc:h2:mem:process-engine;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE”);
dataSource.setUrl(“jdbc:postgresql://localhost:5432/camunda-database-demo”);
dataSource.setUsername(“postgres”);
dataSource.setPassword(“postgres”);
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public SpringProcessEngineConfiguration engineConfiguration(
DataSource dataSource,
PlatformTransactionManager transactionManager,
@Value(“classpath*:*.bpmn”) Resource[] deploymentResources) {
SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration();
configuration.setProcessEngineName("engine");
configuration.setDataSource(dataSource);
configuration.setTransactionManager(transactionManager);
configuration.setDatabaseSchemaUpdate("true");
configuration.setJobExecutorActivate(false);
configuration.setDeploymentResources(deploymentResources);
configuration.setApplicationContext(this.applicationContext);
return configuration;
}
@Bean
public ProcessEngineFactoryBean engineFactory(SpringProcessEngineConfiguration engineConfiguration) {
ProcessEngineFactoryBean factoryBean = new ProcessEngineFactoryBean();
factoryBean.setProcessEngineConfiguration(engineConfiguration);
return factoryBean;
}
@Bean
public Tenant tenant(){
Tenant tenant = new Tenant();
tenant.setId(env.getProperty(“tenant.id”));
return tenant;
}
@Bean
public ProcessEngine processEngine(ProcessEngineFactoryBean factoryBean) throws Exception {
return factoryBean.getProcessEngineConfiguration().buildProcessEngine();
/*CommandContext commandContext = Context.getCommandContext();
Tenant tenant = tenant();
System.out.println("#########################TenantId: "+ tenant.getId()+"###########################");
if (commandContext == null) {
return getProcessEngineByTenantId("tenant1");
} else {
// used within the process engine (e.g. by the job executor)
return commandContext.getProcessEngineConfiguration().getProcessEngine();
}*/
}
private ProcessEngine getProcessEngineByTenantId(String tenantId) {
if (tenantId != null) {
ProcessEngine processEngine = BpmPlatform.getProcessEngineService().getProcessEngine(tenantId);
if (processEngine != null) {
return processEngine;
} else {
throw new ProcessEngineException(“No process engine found for tenant id '” + tenantId + “'.”);
}
} else {
throw new ProcessEngineException(“No tenant id specified. A process engine can only be retrieved based on a tenant.”);
}
}
@Bean
public RepositoryService repositoryService(ProcessEngine processEngine) {
return processEngine.getRepositoryService();
}
@Bean
public RuntimeService runtimeService(ProcessEngine processEngine) {
return processEngine.getRuntimeService();
}
@Bean
public TaskService taskService(ProcessEngine processEngine) {
return processEngine.getTaskService();
}
@Bean
public HistoryService historyService(ProcessEngine processEngine) {
return processEngine.getHistoryService();
}
@Bean
public ManagementService managementService(ProcessEngine processEngine) {
return processEngine.getManagementService();
}
@Bean
public Starter starter() {
return new Starter();
}
@Bean
public CalculateInterestService calculateInterestService()
{
return new CalculateInterestService();
}
}
Following is “process.xml” file :
<process-archive name="All">
<process-engine>default</process-engine>
<properties>
<property name="isDeleteUponUndeploy">false</property>
<property name="isScanForProcessDefinitions">true</property>
<property name="resourceRootPath">tenants/all</property>
</properties>
</process-archive>
<process-archive name="German" tenantId="tenant1">
<process-engine>tenant1</process-engine>
<properties>
<property name="resourceRootPath">classpath:tenants/de/</property>
<property name="isDeleteUponUndeploy">false</property>
<property name="isScanForProcessDefinitions">true</property>
<!-- <property name="resourceRootPath">tenants/de</property>-->
</properties>
</process-archive>
<process-archive name="French" tenantId="tenant2">
<process-engine>tenant2</process-engine>
<properties>
<property name="resourceRootPath">classpath:tenants/fr/</property>
<property name="isDeleteUponUndeploy">false</property>
<property name="isScanForProcessDefinitions">true</property>
<!-- <property name="resourceRootPath">tenants/fr</property>-->
</properties>
</process-archive>
I have created Two against my local Database with Schema “Tenant1” & “Tenant2” and put their entries into the “tenant” table as well.
While deploying the “*.war” file I ma observing below error on Tomcat ,
SLF4J: Found binding in [jar:file:/C:/Softwares/Tomcat-9/lib/slf4j-jdk14-1.7.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See SLF4J Error Codes for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.JDK14LoggerFactory]
04-Jun-2020 13:46:52.497 INFO [main] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
04-Jun-2020 13:46:52.559 INFO [main] org.springframework.web.context.ContextLoader.initWebApplicationContext Root WebApplicationContext: initialization started
04-Jun-2020 13:46:52.648 INFO [main] org.springframework.web.context.support.AnnotationConfigWebApplicationContext.prepareRefresh Refreshing Root WebApplicationContext: startup date [Thu Jun 04 13:46:52 IST 2020]; root of context hierarchy
04-Jun-2020 13:46:52.739 INFO [main] org.springframework.web.context.support.AnnotationConfigWebApplicationContext.loadBeanDefinitions Successfully resolved class for [org.camunda.bpm.getstarted.loanapproval.LoanApplicationContext]
04-Jun-2020 13:46:52.971 WARNING [main] org.springframework.web.context.support.AnnotationConfigWebApplicationContext.refresh Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.camunda.bpm.getstarted.loanapproval.LoanApplicationContext]; nested exception is java.lang.IllegalStateException: Failed to introspect annotated methods on class org.camunda.bpm.getstarted.loanapproval.LoanApplicationContext
04-Jun-2020 13:46:52.988 SEVERE [main] org.springframework.web.context.ContextLoader.initWebApplicationContext Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.camunda.bpm.getstarted.loanapproval.LoanApplicationContext]; nested exception is java.lang.IllegalStateException: Failed to introspect annotated methods on class org.camunda.bpm.getstarted.loanapproval.LoanApplicationContext
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:183)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:272)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:92)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:524)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:443)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:325)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4690)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5151)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)
Caused by: java.lang.IllegalStateException: Failed to introspect annotated methods on class org.camunda.bpm.getstarted.loanapproval.LoanApplicationContext
at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:163)
at org.springframework.context.annotation.ConfigurationClassParser.retrieveBeanMethodMetadata(ConfigurationClassParser.java:385)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:319)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:247)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:200)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:169)
… 39 more
Caused by: java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
org/camunda/bpm/getstarted/loanapproval/LoanApplicationContext.engineFactory(Lorg/camunda/bpm/engine/spring/SpringProcessEngineConfiguration;)Lorg/camunda/bpm/engine/spring/ProcessEngineFactoryBean; @10: invokevirtual
Reason:
Type ‘org/camunda/bpm/engine/spring/SpringProcessEngineConfiguration’ (current frame, stack[1]) is not assignable to ‘org/camunda/bpm/engine/impl/cfg/ProcessEngineConfigurationImpl’
Current Frame:
bci: @10
flags: { }
locals: { ‘org/camunda/bpm/getstarted/loanapproval/LoanApplicationContext’, ‘org/camunda/bpm/engine/spring/SpringProcessEngineConfiguration’, ‘org/camunda/bpm/engine/spring/ProcessEngineFactoryBean’ }
stack: { ‘org/camunda/bpm/engine/spring/ProcessEngineFactoryBean’, ‘org/camunda/bpm/engine/spring/SpringProcessEngineConfiguration’ }
Bytecode:
0x0000000: bb00 1b59 b700 1c4d 2c2b b600 1d2c b0
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.getDeclaredMethods(Class.java:1975)
at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:152)
... 44 more
04-Jun-2020 13:46:52.992 SEVERE [main] org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start. Full details will be found in the appropriate container log file
04-Jun-2020 13:46:52.997 SEVERE [main] org.apache.catalina.core.StandardContext.startInternal Context [/loanapproval-spring] startup failed due to previous errors
04-Jun-2020 13:46:53.019 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [C:\Softwares\Tomcat-9\webapps\ROOT]
04-Jun-2020 13:46:54.678 INFO [main] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
04-Jun-2020 13:46:54.692 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [C:\Softwares\Tomcat-9\webapps\ROOT] has finished in [1,673] ms
04-Jun-2020 13:46:54.697 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler [“http-nio-8080”]
04-Jun-2020 13:46:54.707 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [10,982] milliseconds
I have also try to change the change the Configuration tag “BPM-Platform.xml” to “SpringProcessEngineConfiguration” but it gets failed with error “NullPointerException” for “SpringBeanResolverFactory” class as “ApplicationContext” coming as “null” there.
I have also tried to create a Bean of “SpringBeanResolverFactory” in my ApplicationContext & set its ApplicationContext by implementing “ApplicationContextAware” Interface but it also not work.
Could anyone please let me know to resolve above issue as I need “Spring Based” Workflow Engine with the Multi Tenancy support with separate schema for each Process Engine & how I can get a handler of Process Engine as per the “TenantId” I have & do deployment against it.
Please correct me if I am doing anything wrong.
Thanks in advance for you help.
Best Regards,
Satish.