Duplicate Process Definition

Hi,

after spending some time with Camunda the time has come to ask my first question.

I have an inline ProcessDefinition (BpmnModelInstance) using the Bpmn.createProcess() Builder. On Application startup, I use the RepositoryService to deploy the process definition:

public void deployProcessDefinition() {
  repositoryService
    .createDeployment(processApplication.getReference())
    .enableDuplicateFiltering(true)
    .name("issue-process-name")
    .source("issue-process-source")
    .addModelInstance("issue-process.bpmn", issueProcessModel())
    .deploy();
}

I use enableDuplicateFiltering but nevertheless a new deployment is created every time the application starts. I already set the camundaVersionTag(“1”) in the generated BpmnModelInstance.

How can I prevent a duplicate deployment?

Hi @cachescrubber,

welcome to our forums. :cake:

The passed model is serialised to XML and stored in the database. The duplicate filtering compares the stored with the passed XML and if it is equal, the deployment gets skipped.

How do you make sure that issueProcessMode() is always serialised to an equal XML representation?

Cheers,
Tassilo

Good morning @tasso94

That may be the right question. I generate the BpmnModelInstance using the Java Builder Api. My Source code is not changing at all, so something in the builder is probably generating random ids, for example, which in turn does not pass the equality check. The question would then be: How to make sure to generate the same Xml from a BpmnModelInstance generated by the Java builder unless I change my source code?

best,
Lars

Hi @cachescrubber,

you are absolutely right. The Camunda Model API generates random ids. This is the reason why the process models are considered as different.

What about using an already serialised BPMN XML model (*.bpmn)?

Cheers,
Tassilo

Hi @tasso94,

it is an exercise in how to avoid a xml process model for a simple embedded process.

Why don’t use the camundaVersion attribute to aid in the equality check? This is the workaround I found:

public void deployProcessDefinition() {
  ProcessDefinition deployedDefinition = repositoryService.createProcessDefinitionQuery()
    .processDefinitionKey("issue-process")
    .latestVersion()
    .singleResult();

  BpmnModelInstance bpmnModelInstance = issueProcessModel();
  Process process = bpmnModelInstance.getModelElementById("issue-process");

  if (null == deployedDefinition || deployedDefinition.getVersionTag().compareTo(process.getCamundaVersionTag()) < 0) {
    repositoryService
      .createDeployment()
      .name("issue-process-name")
      .source("issue-process-source")
      .addModelInstance("issue-process.bpmn", issueProcessModel())
      .deploy();
  }
}

Hi @cachescrubber,

please feel free to raise a feature request in our issue tracker [1].

Cheers,
Tassilo

[1] https://app.camunda.com/jira/secure/CreateIssue!default.jspa

Hello.

I still had no time to look into a feature-request…

I identified a related problem. My workaround is to call repositoryService.deploy() only when my custom logic identified a change in the process definition.

In combination with the deployment aware feature of the jobExecutor

camunda.bpm.job-execution.deployment-aware=true

we now see the following behaviour. After a restart of the application without changes to the model, the JobExecutor won’t pick up jobs for started process-instances.

How do I connect the Engine to my previous deployment?

Hi,
I believe each engine node maintains an in memory register of deployments which feed into the job executor. If you restart a node, you need to trigger re-registration of deployments. (I should point out this is automatic on some typical app server config such as shared engine on Tomcat for example)…

Have a look at the ManagementService.registerDeploymentForJobExecutor(String deploymentId)

regards

Rob

1 Like

Hi,

Thx. I implemented the following method:

public void redeploy() {
    List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery()
      .processDefinitionKey("issue-process")
      .list();
    for (ProcessDefinition processDefinition : processDefinitions) {
        managementService.registerDeploymentForJobExecutor(processDefinition.getDeploymentId());
        managementService.registerProcessApplication(processDefinition.getDeploymentId(), processApplication.getReference());
    }
}

Do you know if managementService.registerProcessApplication() includes functionality of registerDeploymentForJobExecutor()? Or dow I have to call both?

1 Like

I am adding 1 more question here.
I am having Heterogeneous Cluster setup. Now I deployed some process applications through modeler. So the process engine will maintain in memory about new deployments.
But If I am restarting my node. I will not able to identify which all deployments have been pushed through this node as this information doesn’t persist anywhere.
If I am trying to do something like repositoryService.createProcessDefinitionQuery().list();
It will give me whole processDefinitions related information as database is same.
So How can I identify which all deployments was linked to this node?

This is important as jobExecutor only pick deployment Id related job when application setup is deployment-aware.

Hi,

I am using it with .bpmn but still everytime service gets restarted, it gets a new deployment and new version.

        repositoryService.createDeployment()
        .name("abc_Workflow")
        .source("abc_Workflow")
        .enableDuplicateFiltering(true)
        .tenantId("xyz")
        .addClasspathResource("bpmn/abc_Workflow.bpmn")
        .deploy();

I had same bpmn for multiple tenants.

The query that executes to return the existing deployments is :

select B.* from ACT_GE_BYTEARRAY B inner join (select B.NAME_, MAX(D.DEPLOY_TIME_) DEPLOY_TIME_ from ACT_GE_BYTEARRAY B inner join ACT_RE_DEPLOYMENT D on B.DEPLOYMENT_ID_ = D.ID_ where D.NAME_ = 'abc_wf' and D.SOURCE_ = 'Workflow_Engine' and B.NAME_ in ( 'abc_wf.bpmn' ) group by B.NAME_) LAST_RESOURCE on B.NAME_ = LAST_RESOURCE.NAME_ inner join ACT_RE_DEPLOYMENT D on B.DEPLOYMENT_ID_ = D.ID_ and D.DEPLOY_TIME_ = LAST_RESOURCE.DEPLOY_TIME_ and D.NAME_ = 'abc_wf' and D.SOURCE_ = 'Workflow_Engine' and D.TENANT_ID_ = 'xyz' order by B.ID_ asc

It doesnt have the filter of tenant in the first join, but have that in second filter. Because of that records couldnt be found with max deployment time.

I fixed this by appending the tenantid to wf-source and name. That way it doesnt pick the records of different tenant in the first join itself.