Workflow variables data types
Is there any documentation regarding how the workflow variables are being stored?
e.g. two workflows use similar form property types (term), but one is stores as an ArrayList, while the other is stored in a String
Class of impactedDST is class java.lang.String
Class of dataElement is class java.util.ArrayList
arthurburkhardt
Posted 5 years ago · Edited 1 year ago·Last reply 3 years ago
15 comments
arthurburkhardt
OP3 years ago · EditedThere are two things you can do:
In any case, you need to programmatically start the workflow:
payload = { "workflowDefinitionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "businessItemIds": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ], "businessItemType": "ASSET", "formProperties": { "additionalProp1": "string", "additionalProp2": "string", "additionalProp3": "string" }, "guestUserId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "sendNotification": true } r = c.post('workflowInstances', json=payload)Print log lines related to the script
You can poll for new log lines continuously. There are some issues with the API though:from collibra import Console import time co = Console() try: max_timestamp = '' while true: lines = co.get(f'log/service/85a195a8-b519-483e-9ba0-823d6f896d30/content?filename=dgc.log&lines=200&_=1667911772639').json() for line in lines: if line[:23] > max_timestamp: print(line) max_timestamp = line[:23] time.sleep(3) #poll every 3 seconds except KeyboardInterrupt: print("Stopped polling logs")Introspect workflow task form data
You can query tasks and update them with API calls:

Using APIs, it would even be possible to build test scripts and automatically test workflows whenever new deployment occur.
rostislav
·5 years ago · EditedFollowing this discussion, we’ve added a Class of stored value column to the Form property types documentation.
arthurburkhardt
OP5 years ago · EditedThis is really great, thanks @rostislav.andriciuc.collibra.com!
arthurburkhardt
OP5 years ago · EditedYay, I completed the remaining steps in 30min this morning. That’s a nice way to start the week
I was afraid I’d have to compile an extension for Eclipse, but it turns out there’s a simple
Run External toolscommand, that allows to easily configure with project variables.So now, indeed, I can just left click to package + upload.
Last step: add the execute (with optional passing messages if there’s a user task) + logging.
Tom Friesen
·5 years ago · EditedThis looks pretty cool, Arthur. Kudos!
Are you willing to share your scripts?
arthurburkhardt
OP5 years ago · EditedI’m ok to explain the bits and pieces, the business logic, though.
cherifahmed_el_abass5e9509
·4 years ago · EditedHello Arthur,
I would be really interested to know the ideas used in your python script for packaging (the business logic…etc)
Thank you.
arthurburkhardt
OP4 years ago · EditedWell, it’s quite easy and basic:
If you start from a folder containing the .bpmn file and the .groovy files, you just have to open the groovy files and merge the content into the .bpmn files (which is an xml)
I added some stuff, including the possibilities to use “//REMOVE” keywords to remove pieces of code (that I use for instantiating the apis) and “//INSERT” to add reusable snippets (though I should probably use the “groovy-lib” magic folder instead)
bpmn = {} scripts = {} conf_vars = set() for filepath in input_folder.iterdir(): if filepath.suffix == '.bpmn': with filepath.open(encoding='utf-8') as f: e = etree.parse(f) process_id = e.find('ns:process', namespaces=NSMAP).attrib['id'] conf_vars = {(x.attrib['id'],x.attrib['default']) for x in e.xpath('//ns:startEvent/ns:extensionElements/activiti:formProperty', namespaces=NSMAP) if 'default' in x.attrib} if process_id in bpmn: raise Exception(f"Conflict: multiple bpmn files provided with same id - {process_id}") bpmn[process_id] = {} bpmn[process_id]['definition'] = e bpmn[process_id]['script_tasks'] = {x.attrib['id']:x for x in e.xpath('//ns:scriptTask', namespaces=NSMAP)} print(f"script tasks: {bpmn[process_id]['script_tasks'].keys()}") elif filepath.suffix == '.groovy': script_lines = [f'def prefix = "[{filepath.stem}] "'] for line in _filter_comments(filepath.open().readlines()): script_lines.append(line) if line.startswith('//INSERT'): """insert predefined function from a file""" for import_file in [(project_path/x.strip()).resolve() for x in line.split(' ', maxsplit=1)[1].split(',')]: script_lines += _filter_comments(import_file.open().readlines()) scripts[tuple(filepath.stem.split('-'))] = '\n'.join(script_lines) for (process_id, script_task_id), script_text in scripts.items(): script_task = bpmn[process_id]['script_tasks'][script_task_id] for x in script_task.getchildren(): script_task.remove(x) script = etree.SubElement(script_task, f'{{{NSMAP["ns"]}}}script') script.text = script_textcherifahmed_el_abass5e9509
·4 years ago · EditedThank you Arthur. This is a time saver.
arthurburkhardt
OP5 years ago · EditedBTW, @alvin.useree.lloydsbanking.com, after our discussion, I realized I needed to accelerate the feedback loop beetween IDE and workflow engine, I’m halfway through it, shouldn’t be too long to finish it.
In the IDE, my project structure is like this
e.g.

Now for the grand finale:
So, one click to package + deploy, then one click to execute and get results (without useless stacktrace) directly in Eclipse!
Are you interested in any of that? Do you have also good practices to recommend?
shubhamgattani
·3 years ago · EditedHi @arthur.burkhardt
BIG Fan of your creative workarounds… It has been helping me (am sure many others) a lot.
Just wondering: Were you able to implement this? (getting the collibra log results in eclipse console ) . I am excited to know about it and could not find that in your following replies hence the query
arthurburkhardt
OP3 years ago · EditedWell, it’s relatively easy to do, but I did not do it yet.
Happy to give pointers though
shubhamgattani
·3 years ago · Edited@arthur.burkhardt Your pointers would really be very helpful.
Former User
·5 years ago · EditedHey mate,
For that specific case, I’m going to go out on a limb and say that it depends on whether you’ve set the multiValue form value as true, false or not set it at all
If set true, then the returned class is an Array of strings for each UUID if set to false or not set then it returns the UUID in string format.
Outside of that example I 100% agree with this point, I haven’t been able to find documentation on the returned classes so I generally run a getClass() and log it to the console to remind myself of the class which is a seriously inefficient way to this!
Also there a some hidden gotchas that could easily be mitigated with this documentation. For example, if you use a textarea, you can’t use the outputs of the textarea for anything unless you cast it as a string first, when I train people on workflows, these are the types of things I package as “just remember this as a rule” which frankly isn’t the best look!
If you find the documentation, give me a nudge mate!
Cheers!
Alvin Useree
arthurburkhardt
OP5 years ago · EditedThanks a lot for the reply!
After checking many details based on your feedback, I found the culprit!!!
I had incorrectly declared the namespace as
https://www.collibra.com/apiv2instead ofhttp://www.collibra.com/apiv2(notice the extra s).So it did not register the workflow as using the api v2 and apparently, “term” was a java.lang.String in apiV1, but java.lang.ArrayList in api V2.
Mystery solved!
Indeed, working with workflows requires quite a lot of trial and error…