How to create a new custom extension in Process

Hi all!

I’m continuing to work with bpmn-js, trying to create custom properties. I’ve done a couple of them for tasks, and I’m trying to create a custom Property in a Pool/Participant. But what I really need is that the property, saved as a bpmn2:extension, needs to be saved as extension of the process itself, not as an exception of the participant.

I’ll try to explain myself. I can do this:

<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
  <bpmn2:message id="Message_144bdea" name="Yeah!" />
  <bpmn2:collaboration id="Collaboration_0iod4d2">
    <bpmn2:participant id="_participant" name="Generic Participant" processRef="_appointment_process_test">
      <bpmn2:extensionElements>
        <dm:userExtension username="Someone">
        </dm:userExtension>
      </bpmn2:extensionElements>
    </bpmn2:participant>
  </bpmn2:collaboration>
  <bpmn2:process id="_process_test" name="This is a test" isExecutable="false">
      ...
  </bpmn2:process>

But what I really want is this:

<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
  <bpmn2:message id="Message_144bdea" name="Yeah!" />
  <bpmn2:collaboration id="Collaboration_0iod4d2">
    <bpmn2:participant id="_participant" name="Generic Participant" processRef="_appointment_process_test">
    </bpmn2:participant>
  </bpmn2:collaboration>
  <bpmn2:process id="_process_test" name="This is a test" isExecutable="false">
      <bpmn2:extensionElements>
        <dm:userExtension username="Someone">
        </dm:userExtension>
      </bpmn2:extensionElements>
      ...
  </bpmn2:process>

Is it possible to do something like this?

EDIT (Sep 19th 2018): I’m actually have an answer to this and it is, yes, I can do that. I know that because the software Camunda Modeler actually does that in its BPMN Modeler. Which is why I change my own question to: HOW can I do that?

What do you try right now to accomplish this? This helps us to understand where to best pick you up.

Thanks @nikku for your reply.

What I’m trying to do is to create a custom extension in a custom tab, called userExtension (label: allow only these users) on participant, because I need to select a specific user to do that specific process.

workflow%20extension

The problem happens, as explained in my first post, when I generate the XML. This extension is saved as a child of the participant node, what I need is to store that extension as a child of the process node, for further use.

In case is needed, this is the userTaskProprs.js I created for this purpose.

function getUserData(element) {
	return getExtensionElement(element, "dm:UserExtension");
}

export default function(group, element, bpmnFactory) {
	const userSelectorEntry = entryFactory.textField({
		id: "user-input",
		label: "Allow only these users",
		modelProperty: "username",

		get: function(element, node) {
			const userDataExtension = getUserData(element);
			if (!userDataExtension) {
				return {
					username: null,
				};
			}
			const storedValue = userDataExtension.get("username");
			return {
				username: storedValue,
			};
		},

		set: function(element, values, node) {
			const userDataExtension = getUserData(element);
			if (!userDataExtension) {
				return createExtensionElement(
					element,
					"dm:UserExtension",
					{
						username: values.username,
					},
					bpmnFactory
				);
			} else {
				return cmdHelper.updateBusinessObject(element, userDataExtension, {
					username: values.username,
				});
			}
		},
	});
	group.entries.push(userSelectorEntry);
}

I realize that the createExtensionElement method set the extension to the element passed as argument. I looking for the parent property, searching for the root, the businessObject, but none helped me do the trick.

A work collegue of mine showed me that the Camunda Software Modeler (run the program, create a new BPMN, add a participant/pool, setting a name/value in exception) set the extension from participant straight to process.

Hope it’s more clear now. I realize I’m quite new in this world, so I might not using the best approach. But thanks for any help offered.

In case element is a bpmn:Participant we use the ParticipantHelper to retrieve the actual process and update it.

So the solution is something along these lines:

var processBo = getBusinessObject(element).get('processRef');

// use other cmdHelper methods as needed, too
// just pass the processBo rather than the participant businessObject
// as the second argument
return cmdHelper.updateBusinessObject(element, processBo, properties);

That should do the trick.

Thank you @nikku! I didn’t know of ParticipantHelper, so I’ll study it a little more and try again. Much appreciated, again!

hey @carbammato could you help me understand what getExtensionElement() and createExtensionElement() does? are you importing it? if yes could you specify the path?

Thanks

I don’t remember if there were included in an older version of BPMN-js (I was using the 3.4.1 version till a couple of weeks ago) or a colleague of mine created it since these are functions that we use a lot in our custom properties.

getExtensionElement(element) is actually a shorthand to quickly get the extension of a defined element:

export function getElementExtensions(element) {
	const bo = getBusinessObject(element);
	return bo.get("extensionElements");
}

the createExtensionElement(element, type, value, bpmnFactory) is another shorthand to get the extensionElements and then uses the and the cmdHelper and elementHelper classes to create the commands of update/creation/delete of extension and elements (respectively). The value property represent the value you actually want to set in your extension.

I hope it helps.

Thanks @carbammato,
i am currently trying to add tag inside bpmn:ScriptTask Tag (what the user inputs)
Here is the link which explains the problem i am trying to solve:

Could you help me understand how i could achieve this?

Thanks

i was able to get it to work, thanks @carbammato for your reply.

Mind sharing your solution, so someone else would benefit from it in the future?

Solution: