Skip to Content
Author's profile photo Ariel Bravo Ayala

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:

  1. The Dispatcher Package.So far, the package only contains two artefacts: The Idoc dispatcher and the value mapping with the configuration.
  2. 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(*)
  3. 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.

 

Assigned Tags

      14 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Gayathri Narayana
      Gayathri Narayana

      Nice Blog Ariel. Its really nice to see how you have used these different capabilities in CPI to achieve these use cases.

      Author's profile photo Ariel Bravo Ayala
      Ariel Bravo Ayala
      Blog Post Author

      Thanks Gayathri!

      Author's profile photo Hemachandan A S
      Hemachandan A S

      Thanks Ariel for bringing my imagination to alive based on the discussion in webinar.

      Cheers,

      Chandan

      Author's profile photo Ariel Bravo Ayala
      Ariel Bravo Ayala
      Blog Post Author

      You're welcome!

      Author's profile photo Anil Yakkali
      Anil Yakkali

      Very nice Blog, Thanks for Insights.

      Author's profile photo Ariel Bravo Ayala
      Ariel Bravo Ayala
      Blog Post Author

      Thanks Anil!

      Author's profile photo Pavan G
      Pavan G

      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

      Author's profile photo Ariel Bravo Ayala
      Ariel Bravo Ayala
      Blog Post Author

      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

      Author's profile photo Paul Canapero
      Paul Canapero

      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:

      1. In the value mappings, omit any extra pipe characters - e.g. if only 3 out of the 4 fields exist, do not add a pipe for the 4th one.
      2. Prefix the process direct address with "/" on the right hand side.
      3. The same number of parameters needs to exist for all, e.g. RCVPRN, MESTYP, IDOCTYP as shown below.  (With more coding extra parameters could be made optional).

      Hope this is helpful.

       

      Author's profile photo Jaith Ambepitiya
      Jaith Ambepitiya

      Nicely written. good pieace of work Ariel .. !!

      Author's profile photo Pavan G
      Pavan G

      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[]

      ********

      • Is there any restriction on load of IDocs being sent to CPI?
      • In case of errors, we always get the same error like internal error occurred with a suggestion to use CPI tenant URL mentioned in the RFC. We can't track the actually errors if a receiving system rejects the IDocs.

      Any Idea how do we over come such errors.

      Regards,

      Pavan

      Author's profile photo Ariel Bravo Ayala
      Ariel Bravo Ayala
      Blog Post Author

      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

      Author's profile photo kumar m
      kumar m

      Hello Experts,

      I have used same value mapping and Groovy Script I am facing below error,

      Error Details
      javax.script.ScriptException: java.lang.Exception: groovy.lang.MissingPropertyException: No such property: helperValMap for class: script1__Script@ line 24 in script1.groovy,
      cause: groovy.lang.MissingPropertyException: No such property: helperValMap for class: script1__Script
      Thanks,
      kumar
      Author's profile photo Philippe Addor
      Philippe Addor

      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.

      /MSGTYPE_IDOCTYPE_CIMTYPE

      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

      /${property.msgtype}_${property.idoctype}_${property.cimtype}

      That's it! No groovy script and VM necessary. 🙂

      Philippe