Questions
If you have met these kinds of problems and the tool at hand is PCS, then you probably ran in (some of) the following questions:- Why don't we try to solve this in SOA CS or possibly ICS?
- Where are the script tasks we have in BPM Suite? (Sorry, this is an obvious one, but still)
- How to count the elements of a list? Or, where are the functions in PCS?
- How to add elements to a list?
- Etc.
Many of these things we ran into are actually orchestration issues. And as with the all-time discussions on when to use SOA and when BPM, we advise doing complex service orchestration (with message processing) in SOA CS, or if possible in ICS. But when we started with this project, the tools we were given were PCS and ICS. And where ICS lacked the more advanced logic processing in the orchestration integrations, at the time (it's improved over time). And sometimes it really is fun to try to accomplish things that were mentioned not being possible. Go where no man has gone before, that sort of stuff.
Script tasks? I guess PCS Product Management gets tired of answering this question. But the real thing is: we do need to do determinations based on the outcome of services. But also doing logic before doing an activity. In the input data association of an activity, you can only assign into the input-arguments of the activity. You can't update process variables. You can do that in the output data-association. But not all activities have a output-data-associations. And there are cases where you don't have an applicable previous activity. For instance in loops.
The case
Let's get into a case. Let's say you have a list of product-subscriptions that your customer has acquired from you. And for some reason some of those products need a review. In our case the customer faces a takeover, and is part of a hierarchy. So you want to fetch all the applicable products in the company hierarchy and add all of those in a list of Review Product Tasks.The list of products is acquired by calling an ICS service that fetches a list of products from SalesCloudService and calls Oracle Policy Automation to filter the applicable products from the list. That's the list we need to add to the list that should contain the Review Product Tasks for products acquired from all the companies in the hierarchy. The result list looks like:
The part of interest of the process is:
- I don't have an other activity with an output data-association in the loop to do calculations to base my test upon.
- Again, we don't have script tasks with functions. So I miss-use a decision function as a script task. Which does the job quite well by the way.
- Oh, and the nice thing of the Business Rules Engine (the same as used in SOASuite and BPM Suite) is that it does have functions. But we'll get into the magic of that in a minute.
Within the response message we have a list of products, but of course, those are in the structure of the service definition. We need to copy the elements over to the input of the decision function.
The input of the Add Review Product Task decision function looks like:
The output is:
So in goes the list of products and the product to add. The Decision Functions results into an updated list.
But, how to do that?
First, let's look in to the input data association:
The first rule is to copy the reviewProductTasksDO (the list we're building) to the corresponding input argument. Then the particular product is created by entering the different elements. As said, some where in the structure of the response message of the ICS service, we have a list of products. Using the productIdx variable we select one if the products and that indexed product is copied element by element.
Now, the rule is:
The first 2 conditions are actually declarations of identifiers we refer to in the rest of the rule: reviewProductTask, being the single object as input and reviewProductTaskList containing the list of reviewProductTasks. Then we only want to add the reviewProductTask if it does not exist, to prevent the rule getting into a infinite loop. Since reviewProductTaskList is in fact an object that has an attribute being a list of reviewProductTask elements, that list contains a set of functions. One of those is the contains() function:
reviewProductTaskList.reviewProductTask.contains(reviewProductTask)
The goal of this function is quite obvious, it returns true() or false(). If the contains() function returns true, then a a call action is performed. And there the magic happens:
reviewProductTaskList.reviewProductTask.append
The reviewProductTaskList.reviewProductTask list also has an append() function. The input of that is the reviewProductTask object variable, the same that went into contains() as a parameter. The real nice thing? This also works in BPM Suite and SOA Suite! Remember? The Business Rules Engine in those products is the exact same thing! To me this was a bit of a revelation. I wasn't aware of the list functions in BRE.
So, now the rule is fired and the list is extended. We need to assign the result to the particular DataObject. So the output data association is:
Quite obvious, again, but the output argument, being the reviewProductTasksOut object, needs to be assigned to the reviewProductTasksDO Data Object. But also the productIdx needs to be increased.
The Decision Function activity loops back to the Exclusive Gateway. How to determine if we're done? Remember we don't have a count() function in the expression builder? The trick is done in the No-transition:
The condition is:
getCriticalProductsResponseMessage4TakeOverCpyDO.data.products.product[productIdx] == nullWhen the productIdx is increased and it gets a value greater then the number of product elements in the list, then indexing that (non-existent) product will lead to null. And that can be tested.
And again, it's too obvious, and yet it took me a while to get to this.
The check if we need to get another company in the hierarchy is comparable, only it is indicated by the ICS service. If it is the top-level company, then it has no reference to a parent:
getCriticalProductsResponseMessage4TakeOverCpyDO.data.parentAccountPartyId != null
Conclusion
It might seem so obvious when you read this. And I suppose it is. But, some of those constructs and tests/conditions are not so apparent from the UI. So I hope I have been able to get some of you at the right track.In one of the follow-up blog-posts I'd like to address Correlations.
2 comments :
Nicely done ,thanks for the details. Any updates on when they will introduce Script tasks ?
Hi,
Recently a datamapper activity is added to the Integration cloud: http://kettenisblogs.blogspot.nl/2018/04/oracle-integration-cloud-data-mapper.html
Regards,
Martien
Post a Comment