@Deployment deploy BPMN/DMN with tenant ID in unit test

Hi,

Our process definition has a business rule task.
The deployment descriptor(processes.xml) has the tenant set as “Tenant1”

In the BPMN we’re assigning camunda:decisionRefTenantId=“Tenant1”, and the process works fine.

However while running the unit tests(using Camunda Assert and JUnit), we’re running into the following error: Exception while closing command context: no decision definition deployed with key ‘DMN_Key’ and tenant-id ‘Tenant1’: decisionDefinition is null

Our DMN with id “DMN_Key” has no tenant id assigned to it.
When we remove the camunda:decisionRefTenantId=“Tenant1” from the BPMN the tests pass.

We’re deploying or BPMN and DMN for testing using @Deployment annotation, and we do not use any explicit config files for Camunda.

Is there a way we can solve this?

Request you to please point us in the correct direction.

Hello @NehaPandey ,

the first idea that comes to my mind is installing a plugin in your test configuration that sets the tenant id of your deployment to the desired one.

The Plugin:

package com.camunda.consulting.training.plugin;

import java.util.ArrayList;

import org.camunda.bpm.engine.impl.cfg.AbstractProcessEnginePlugin;
import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.camunda.bpm.engine.impl.persistence.deploy.Deployer;

public class RegisterDeploymentInTenantPlugin extends AbstractProcessEnginePlugin
{
	@Override
	public void preInit(ProcessEngineConfigurationImpl processEngineConfiguration)
	{
		if (processEngineConfiguration.getCustomPreDeployers() == null)
		{
			processEngineConfiguration.setCustomPreDeployers(new ArrayList<Deployer>());
		}
		processEngineConfiguration.getCustomPreDeployers().add(new TenantBoundDeployer());
	}
}

the Deployer:

package com.camunda.consulting.training.plugin;

import org.camunda.bpm.engine.impl.persistence.deploy.Deployer;
import org.camunda.bpm.engine.impl.persistence.entity.DeploymentEntity;

public class TenantBoundDeployer implements Deployer
{

	@Override
	public void deploy(DeploymentEntity deployment)
	{
		deployment.setTenantId("my-pretty-tenant-for-testing");
	}

}

Register in camunda.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="processEngineConfiguration"
		class="org.camunda.bpm.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">

		...
		<property name="processEnginePlugins">
			<list>
				...
				<ref bean="registerDeploymentInTenantPlugin" />
			</list>
		</property>
		...
	</bean>
	...
	<bean id="registerDeploymentInTenantPlugin"
		class="com.camunda.consulting.training.plugin.RegisterDeploymentInTenantPlugin" />
    ...
</beans>

Hey @jonathan.lukas,

Thanks for your quick response.

However, as I mentioned, we’re not using any explicit “cfg” files for Camunda.

Is there a way without using one?

Right now I’m using below code in the @Before block as a work around:
repositoryService()
.createDeployment()
.tenantId(“Tenant1”)
.addClasspathResource(“DMN.dmn”)
.deploy();

Would you say this is a good approach?

Hello @NehaPandey ,

this serves the purpose I think. Yet, our @Deployment annotation is powerful as it also undeploys the diagram (and cleans up process data related to this deployment). If you do not use a camunda.cfg.xml, where do you configure your Engine? Exactly there, you should be able to register the plugin.

Jonathan

@jonathan.lukas,

I agree with your thoughts on the @Deployment, hence would want to use that.

We’re using the embedded process engine through Spring boot starter, with processes.xml as the deployment descriptor and default process engine.

We’re using application.properties file for other configuration like default serialization format and such.

Also, the approach you are suggesting, is it only for Test context or would you suggest we make these changes to our application in general.

Hello @NehaPandey ,

sounds to me like you are using a @SpringBootTest. Is that correct? In this case, you would create a @Configuration Class inside src/test/java and register the ProcessEnginePlugin provided above as @Bean method.

The @SpringBootTest should pick up this @Bean and use the plugin from there.

This simple implementation would fit for testing purpose, for production, I would think about a more complex solution.

Jonathan

Hey @jonathan.lukas,

Actually our test class is extending the class AbstractProcessEngineRuleTest, and the we’re modifying the configuration, if any, using processEngine.getProcessEngineConfiguration().

Ok @NehaPandey , in this case, just use the content of the plugin method to register the Deployer.
This could also work, although I am not sure whether a Deployer can be registered after the Engine was built. But give it a try.

1 Like

@jonathan.lukas,

It actually worked.

processEngine.getProcessEngineConfiguration()
.setCustomPreDeployers(new ArrayList() {{add(new TenantBoundDeployer());}})

Thanks for your response.

Just a few more questions, will this approach be then handling the un-deployment of resources automatically, and is it okay to create a Deployer only for Testing?

Hello @NehaPandey ,

if you use this Deployer, you will be able to use the @Deployment annotation (I guess). This one will handle your Deployment lifecycle.

Jonathan

Okay @jonathan.lukas athan.lukas.

And is it okay to create a Deployer only for Testing?

Hello @NehaPandey ,

as you mentioned, you set the tenant in your processes.xml for runtime. This deployer simulates this behaviour for your tests. So this should be fine.

Jonathan

@jonathan.lukas,

False alarm, it’s not working.
As you suggested, I think a Deployer cannot be registered after the Engine was built.

Any other suggestions would be welcome.

Also, are there any specific cons to using the workaround?
repositoryService()
.createDeployment()
.tenantId(“Tenant1”)
.addClasspathResource(“DMN.dmn”)
.deploy();

Hello @NehaPandey ,

you will then need to find a possibility to register the plugin before creating the engine. I would talk to the Person who created the abstract test class whether there is a possibility to add plugins to the test engine.

The workaround has no specific cons as far as I can see right now, except that you are doing double work.

Jonathan

2 Likes

@jonathan.lukas ,

Thanks a ton!

Really appreciate your help.

:vulcan_salute:

1 Like