IDOC Dispatching – Use case for the ProcessDirect Adapter
In February this year (2018), SAP released the new “ProcessDirect” adapter for CPI. An excellent explanation and some cases of use can be found on Meenakshi´s blog post. Whilst reviewing this and another news during the past “What’s new webinar Q2/2018”, one of the attendees proposed a question regarding an option to use a single port to direct all the Idocs to CPI, instead of having a single port and destination for each Idoc. SAP may well present some elegant way of addressing this problem in the future, but in the meantime I am creating this post to offer an alternative solution based on the use of the “ProcessDirect” adapter and value mappings.
In short, the proposal is to have a single and “fixed” iFlow that carries out the distribution tasks and that, based on data from the control segment, is able to redirect the idoc to the corresponding iflow. After deploying and configure this iFlow, the only extra configuration to do each time you want to include a new Idoc, is to include a new value-mapping entry with the key-pair Idoc->ProcessDirect.
In this post I won’t be including information about stuff such us basic configurations as there are available several post talking about this.
About the proposed solution:
- The Dispatcher Package.So far, the package only contains two artefacts: The Idoc dispatcher and the value mapping with the configuration.
- The dispatcher Iflow:Is quite simple: receives a generic Idoc, the control´s segment is analysed and compared against a value mapping, then it sets the receiver ProcessDirect address using a property. It also catch exceptions.
The core of Groovy Script://Get runtime parameters - IDOC def controlSegmentFieldsStr = helperValMap.getMappedValue(runtimeAgency, 'PARAMETER', 'controlSegmentFields' , runtimeAgency, 'VALUE'); if (controlSegmentFieldsStr == null){ throw new Exception("NF: Control Segment Fields") } def controlSegmentFieldsArr = controlSegmentFieldsStr.tokenize(fieldSeparator); //Analyse Idoc Control Segment def body = msg.getBody(); def xml = new XmlSlurper().parseText(body); def keySender = []; controlSegmentFieldsArr.each{ keySender.add(xml.IDOC.EDI_DC40."${it}".text()); } keySender = keySender.join(fieldSeparator); //Get Receiver Address def keyReceiver = helperValMap.getMappedValue(srcAg, 'SENDER', keySender , tgtAg, 'RECEIVER'); //Set Property - Receiver Address def map = msg.getProperties(); msg.setProperty("receiverAddr", keyReceiver);
This iFlow is configurable and among others, it includes the following parameters:
- The address for the incoming Idoc
- Authentication mechanism
- The default ProcessDirect to invoke if any exception is catch(*)
- The Value Mapping.Fist, you will need to configure the relevant fields to consider when routing an Idoc. In my case, the sender port number, message type, idoc type and idoc extension will work as a key.
Secondly, you will need to include the “keys” and associate them with the ProcessDirect Address.
Let’s try it!
-To do not end up with a huge post, I’ll be using the values described in the previous images 🙂
1.- I’m creating three dummy iFlows to receive Idocs. The ProcessDirect address are IDOC_001, IDOC_002 and IDOC_ERR (for the exceptions).
2.- Set up a unique Idoc Port:
3.- Finally, send some Idocs!
- a.- Key exists, redirected to iFlow 01
- b.- Key exists, redirected to iFlow 02
- c.- Key do not exists, redirected to iFlow Exception
I have uploaded the proof of concept to my GitHub repository for anyone who wants to download and freely use it, it is the complete package that you can directly import in your own CPI subscription. I have plans to enhance this further for the XI adapter as well.
(*) To catch these exceptions could be a two double-edged sword. As the Idoc adapter uses a SOAP IDOC port, errors are captured and a new error status is append to the original Idoc at the sender system. If you want to maintain this feature, simply place an inexistent ProcessDirect address.
Note: I couldn’t find a blog with a subject similar to this one, but if it exists (which is likely), I apologise for the crosspost.
Nice Blog Ariel. Its really nice to see how you have used these different capabilities in CPI to achieve these use cases.
Thanks Gayathri!
Thanks Ariel for bringing my imagination to alive based on the discussion in webinar.
Cheers,
Chandan
You're welcome!
Very nice Blog, Thanks for Insights.
Thanks Anil!
Hi Ariel Bravo Ayala
Thanks for such informative blog.
I am trying to replicate the same scenario in my POC. But the interface is failing with the below error upon triggering the IDOC:
**********
java.lang.NoSuchMethodException: No signature of method: org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.processData() is applicable for argument types: (com.sap.gateway.ip.core.customdev.processor.MessageImpl) values: [com.sap.gateway.ip.core.customdev.processor.MessageImpl@587a58ce]
**********
I am not able to find any error in the groovy. Is there anything missing in the groovy ?
Regards,
Pavan G
Hi Pavan,
My mistake was to put only a snippet of the script, it is not a "copy-paste" script. Can you verify? Will try to find the original code 🙂
Ariel
Thank you very much for this post.
I would just like to add a couple of things which I needed to change for this to process in our (Cloud Foundry) CPI system:
Hope this is helpful.
Nicely written. good pieace of work Ariel .. !!
Hi Ariel Bravo Ayala ,
We are using this approach quite a long. But, recently we are facing error with the below log though we have maintained the value mappings correctly.
Error Log:
*********
com.sap.esb.camel.error.handler.ErrorEventException: Error Event Exception
org.apache.camel.component.directvm.DirectVmConsumerNotAvailableException: No consumers available on endpoint: {Value from Value Mapping}. Exchange[]
********
Any Idea how do we over come such errors.
Regards,
Pavan
Hi Pavan,
Sorry, I just saw this message. The error looks like an issue with the value of your process direct endpoint. Did you manage to solve this?
Bests,
Ariel
Hello Experts,
I have used same value mapping and Groovy Script I am facing below error,
Hi Ariel,
Good post! However, I don't think a value mapping is necessary in most cases. Usually, if there is only one (IDoc specific) receiver IFlow per IDoc type, it's enough for the routing to name the process direct addresses according to the IDoc key fields. E.g.
or similar. Then you simply need a Content Modifier that sets the values of these three control record fields into properties using XPath. Then, you use these properties to dynamically create the address in the process direct receiver channel, like
That's it! No groovy script and VM necessary.
Philippe