Hi there AppWorks fans,
Welcome to a new installment of AppWorks tips.
Boy-O-Boy…do I see people struggle with BPMs at projects!? What do you do once ^%#&^%# starts to hit the fan?…Well, you do a debug session on the BPM template!…Right? 🤗 WRONG! 😕 You follow this post and go beyond debugging like the pros would do! 💪
Let get right into it…
Time to get our hands dirty after starting the AppWorks platform and diving into your workspace with the developer account.
Create yourself a first BPM…Simple like this AND set the correct (default) monitoring level for the long-lived type of process.
Quick jump on short-lived/long-lived as there seems to be a circulating story of uncertain or doubtful truth (aka “rumor”) that each only-services-BPM should always be short-lived; A wrong assumption if you ask me! This is my standard rule: Always start with a long-lived process and switch to short-lived ONLY when performance is lacking OR when you need direct feedback in runtime (because of a rule) AND when you don’t have any holds (like manual tasks, delays or waiting for message input)…With those last examples it’s not even possible to make it short-lived without publication error!
…
Let’s also answer a follow-up question: When a BPM is dependent on external services can we make it short-lived? Yes, if you lack the implementation of failing external services to an administration task to solve it. The answer is off-course NO…Always fail-save yourself on external applications; You’re not in control, and they will eventually fail somewhere…Nothing is 100% up and running.
Enough of all the sidenotes…Let’s continue and have some services injected from the context-menu of a BPM activity:
You see me playing with the ‘GetAllUsers’ webservice, but this is just to generate some sample data to play with; Be smart and have a look at the process properties (later) for the current username which make things much simpler, but that’s not the point of this post!
I also leave the names of the activities as they are after attaching a service; This way you know which service is behind it; Normally you rename them to readable activities for your fellow low-code developers!
Don’t change anything (for now)! Do a save to bpm_demo
with a publication and do a run from the context menu of the BPM template.
Now have look at the Process Instance Manager (PIM) artifact for an “Aborted” BPM instance (as expected!). Mark it to have a look at the messagemap:
You have a messagemap option available because of the monitoring settings. If the level of monitoring is too less; Please, don’t make the mistake to update it in the BPM and republish!…Why not? Well, you’ll forget to revert it from the commit (after concentration lost). It’s better to customize the BPM template from the ‘Deployed Process Models’ artifact which you can also remove again once done.
This post is all about useful tips in all the extra comment blocks! 🤣
…
Let’s continue…You have a failing BPM, you have looked at the root cause (which is a failed ‘ReadUser’ activity), but you have no idea how to solve it…Time to start the debugger on the BPM?…NOPE!
Watch the messagemap again and look at the bottom tab with name ‘All View’…Hit it and ‘Copy’ the full messagemap (including the error!):
Save it somewhere (like in notepad) but be aware of the result of the ‘GetAllUsers’ output…This first activity works smoothly with a solid list of users; You will also conclude that ‘FindUserByName’ is not getting any input! So, no wonder our ‘ReadUser’ is failing!
…I know that the example is a simple use-case, but continue the read…
So, jump into the message map of the BPM template (at the bottom), click the ‘FindUserByName’, attach the target ‘Name’ of the service, set the ‘Replace Content With Expression’, and hit the ‘Expression Editor’:
We can now create a fancy xPath expression to get the input for our ‘FindUserByName’ service call; We already know it should be awdev@awp
, but where can we receive this information!? YES, my friend…See the copied messagemap in your notepad! AND when you copy it into the expression editor (under the XML tab!) you can even play with this live data; #OMG 😮:
ns2:GetAllUsersOutput/ns2:GetAllUsersResponse/ns4:User
will (for example) return all the users:
BUT we only need the second entry returning the name:
ns2:GetAllUsersOutput/ns2:GetAllUsersResponse/ns4:User[2]/ns5:Name/text()
OR you reuse the process properties and play with some functions:
substring-before(substring-after(instance:instanceProperties/instance:currentOwner/text(), 'cn='), ',cn=')
OR go viral with expressions like these:
1 | ns2:GetAllUsersOutput/ns2:GetAllUsersResponse/ns4:User[./UserId = substring-before(substring-after(//instance:instanceProperties/instance:currentOwner/text(), 'cn='), ',cn=')]/ns5:Name/text() |
Watch closely on the
./
and//
options! You read about it here
Ohwww YEAH! 😎 A “DONE”. This post brings you back on track to solve the most complex issues in your BPM craftsmanship journey. Comment me on any thoughts of how you do your BPM tricks. There is more to cover, but this is the most crucial one to understand very well as a low-code developer. It will help you to build xPath expressions faster, gives insight on the correctness of the data flow, and is easier and faster to work with compared to the debugger. To be honest, in my 5+ years of BPM knowledge I can count the number of BPM debug session on 2 hands (with still 5 fingers on each one of them). Have a great BPM weekend; CU next week…
Don’t forget to subscribe to get updates on the activities happening on this site. Have you noticed the quiz where you find out if you are also “The AppWorks guy”?