Hi there AppWorks fans,
Welcome to a new installment of AppWorks tips.
It’s happening again…I learned something new! It’s just a small little thing, but highly valuable once you know how to use it.
Use-case: You’re building a great BPM flow which triggers some service resulting to a list of items. You need to grab one of these items for further processing, but the input for the selection criteria derives from another element within the flow. So, the input is dynamic!
Keep on reading; you really want to know about this one…
Let get right into it…
Spin up your VM | system | environment | cloud | or wherever you’re working on and dive into your most favorite project (or create a new one!?)
Build yourself a nice folder structure like we always explain and create a new entity in the entities
folder of the project. I name it project
with just one property prj_name
and generate all the default building blocks for fast prototyping. Make it all nice (like we also learned by now) and do a first test in runtime to create some instances. Make it more than three instances (Test001
, Test002
, and Test003
) to make it look real. 😁
Next step is to apply the ‘Web service’ BB and add a new find operation with name get_all_projects
:
Save the changes and do another publication. You should know the drill by now! With this ‘Web service’ BB, we also require a new service container of type ‘Application Server Connector’…bla-bla-bla, see also here at the end of the post.
When the service container is available, you can quickly evaluate the webservice via the ‘Web Service Interface Explorer’:
Also, you will eventually retrieve your crafted result…Next!
Create BPM and play with xPath
Back in your ‘Workspace Documents’ artifact where we jump into the bpms
folder of our project. From this folder we’ll create a new document of type ‘Business Process Model’ which ends into a new modal screen where we start with a 2-step flow like this:
Now right-click the first activity and insert the webservice operation get_all_projects
. The activity will inherit the service name, but feel free to modify it to your own naming convention. After this, we jump in the ‘Message Map’ tab at the bottom of the panel. Here we define an input
message with a related name
element in the ‘Process Specific Messages’ section:
We will use this message as ‘Trigger Type’ in the properties of the green ‘Start’ construct in the BPM. Like this:
This makes sure we get a modal input message popup once we initiate the BPM manually. You can trigger this in the context menu of the model itself (Execution > Run). Try it out yourself after a save with name bpm_xpath
, and do a publication…
Check the ‘Process Instance Manager’ (PIM) artifact for your BPM instance and grab yourself a copy of the full messagemap:
Time to go back to our BPM modal panel. Select the second activity and open the ‘Message Map’ tab at the bottom again. Make sure you are in the ‘Assignments’ of the second activity where we start to create a helper element / variable (like we created the input
message). We use this one to save information to the target (otherwise we can’t create an assignment!)
Playtime!…Change the use-option ‘Replace content With Fixed Value’ to ‘Replace Content With Expression’ and open the ‘Expression Editor where the fun will start. Here we start by pasting the copied messagemap (from our previous BPM instance) into the ‘XML’ tab. This makes sure we can use ‘real’ data when playing with xPath expressions:
Hit ‘No’ on the question: *”Do you want to ignore the mapped prefix names…”*
Back on the ‘Tree’ tab, we start to use our first xPath (you can just select the correct element from the tree). Hit the ‘Validate’ and ‘Test’ for a first result:
For you the copy from:
ns2:get_all_projectsOutput/ns2:get_all_projectsResponse/ns4:project/ns4:project-id/ns4:ItemId/text()
For our next step we don’t want to retrieve all three results, we only require the second result! How to do this? Well, have a look at this xPath:
1 | `ns2:get_all_projectsOutput/ns2:get_all_projectsResponse/ns4:project[ns4:prj_name = 'Test002']/ns4:project-id/ns4:ItemId/text()` |
Nice…Our one-result is received! Now what? This is hard-coded stuff, and we want to avoid it. Well, we’ve just crafter a nice input message with a name
element! Let’s use it like this as replacement for 'Test002'
:
1 | `ns2:get_all_projectsOutput/ns2:get_all_projectsResponse/ns4:project[ns4:prj_name = bpm:input/bpm:name/text()]/ns4:project-id/ns4:ItemId/text()` |
Right?…WRONG!!
To make this trick work, we need to add two extra //
…Like this:
1 | ns2:get_all_projectsOutput/ns2:get_all_projectsResponse/ns4:project[ns4:prj_name = //bpm:input/bpm:name/text()]/ns4:project-id/ns4:ItemId/text() |
NICEEEEE…That’s all! 😉
WAIT, that’s not all…I’ve been flown back on the ‘double-forward-slash’ trick! Why? When you have a fairly large XML in progress (mine is rather small), it’s better to move up the tree and grab the variable value from the root node. The xPath looks like this (which is better for your performance!):
1 ns2:get_all_projectsOutput/ns2:get_all_projectsResponse/ns4:project[ns4:prj_name = ../../../bpm:input/bpm:name/text()]/ns4:project-id/ns4:ItemId/text()…
Yes, my friends…You see I also learn on the fly. Thx you for tipping me!
The rest of the BPM? Well, that’s up to you whatever you want to do after this…The possibilities are endless.
This //
trick passed by in my own project and will help others in their own xPath solutions. I didn’t know it was possible like this, but now we all know…”DONE”! We even learned how to reuse ‘real’ messagemap data from a running BPM instance during our BPM craftsmanship. Have another great xPath week to play around, and I see you in the next post.
For the “smart”-people: We could off-course create a webservice
get_all_projects_by_input
on the entity, but that was not the point of this post! 🙃
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”?