Technology Blog Posts by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
nunocpereira3
Explorer
0 Likes
819

I’ll break this article into:

  • Problem/Context 
  • Our approach (this link)
  • Git into Partner Directory
  • Generic iflow
  • Automated unit testing
  • Limitations and Future plans

Requirements

Just to remember these were our requirements

requirements.png

Our approach

Architecture.png

Summary

Idea would be to create some configuration files offline, upload them into git, synchronize them with partner directory and finally having a generic iflow that is prepared to read those parameters from partner directory (inspired in what SAP TPM iflows are doing). We support executions of decisions defined inside SAP BPA (optionally) in case we want to use some rule defined there to define some configuration level. 

Details

We start by identifying which fields from payload need to be considered on decision making to do a transformation, routing or both. In this example it is the Region, Process and Country (we call it levels of configuration or lookups). We also need to consider different combinations and defaults for these key fields.

Let’s start by defining a name for this scenario that others can relate, think of a good name such as when you’re thinking for a package name on CI. This will be the interface/scenario ID which will tell the generic code which configuration files to load. For this sample scenario I just name it NUPEBPAPOC (to respect our guidelines for POCs) since NUPE is my initials, BPA just for my reference so that I know it uses SAP BPA and POC since it’s a proof of concept.

Let’s start with a blank directory on your filesystem and by defining the default values on a text file named NUPEBPAPOC.txt with the following content:

 

 

 

 

 

LookupRules=lookup_rules.xml
SAP_COM_REC_Adapter_Type=HTTP
SAP_IDOC_REC_Address=https://testnupeglobal.free.beeceptor.com
SAP_IDOC_REC_HTTPMethod=POST
SAP_IDocProxyType=internet
SAP_IDocAuthMethod=None

 

 

 

 

 

Explaining what we just did, we just defined that by default if no other rules match, we just sent it via POST to the testnupeglobal default url part of the requirement 5 with the HTTP options configured here on this file. 

Now we need to consider the other key fields so let’s define a lookup_rules.xml with this content:

 

 

 

 

<rules>
    <lookups>
        <lookup>
            <bpa_decision id="a2d0983a5146a9649345817559bc7bda" output="result">
                <name>Batch</name>
                <value type="xpath">//batch</value>
                <name>Country</name>
                <value type="xpath">//country</value>
            </bpa_decision>
        </lookup>
        <lookup>
            <xpath>//process</xpath>
        </lookup>
        <lookup>
            <xpath>concat(//Process,//Region)</xpath>
        </lookup>
    </lookups>
</rules>

 

 

 

 

 

What are we declaring with this? A list of rules that would be parsed by our generic iflow and iterated one by one from top to bottom.

On the first level of configuration we’re executing a BPA decision rule that is prepared to receive Batch and Country. It would not be needed for the sake of this demo, but just to prove a point that we could call BPA decisions whenever we want. This would be defined on BPA as follows:

bpa_rule.png

If we now would execute the first payload according to the first lookup defined, the code is fetching the //batch from the supplied payload and injecting it into the BPA rule on the Batch parameter. Same for parameter Country //country from the payload into the Country of the rule. Our generic iflow (that will be explained on part 3) will then perform this internal call into BPA:

 

 

 

 

 

{
  "RuleServiceId": "a2d0983a5146a9649345817559bc7bda",
  "Vocabulary": [
    {
      "Batch": "1",
      "Country":"CH"
    }
  ]
}

 

 

 

 

 

As result from BPA we would have this value for the first payload:

 

 

 

 

 

{
    "Result": [
        {
            "result": "ANY"
        }
    ]
}

 

 

 

 

 

Now we try to find if there’s some specific settings defined for this level. How do we do that? We search on partner directory on partner id NUPEBPAPOC~ANY. Do we find anything there? Any update of the url? Any transformation to apply on this level? We'll later check how do we sync files from our filesystem into partner directory but for now let's assume nothing is there for this level, we keep the default configurations loaded from the previous step.

Now let’s assume that instead of receiving country CH as part of the second payload example we receive PT on the country field such as below:

 

 

 

<?xml version="1.0" encoding="UTF-8"?>
<root>
	<process>CreateBatch</process>
	<region>EMEA</region>
	<prod_date>20240730</prod_date> <!-- format of dates in S4 is yyyymmdd -->
	<quantity>1000</quantity>
	<batch>1</batch>
	<batchplant>PT01</batchplant>
	<material>12345678901</material>
	<country>PT</country>
	<!-- other fields not relevant for this demo -->
</root>

 

 

 

 

 

 

 

 

 

 

{
  "RuleServiceId": "a2d0983a5146a9649345817559bc7bda",
  "Vocabulary": [
    {
      "Batch": "1",
      "Country":"PT"
    }
  ]
}

 

 

 

 

As result from BPA we would have this value for the first payload

 

 

 

 

{
    "Result": [
        {
            "ResultCountry": "Portugal"
        }
    ]
}

 

 

 

 

Now let’s fulfill requirement 3:

If Batch is <5 and country is PT then we return ‘Portugal’ as you see below

bpa_rule.png

Now we need to create NUPEBPAPOC~Portugal.txt since we want to double the quantities for this specific scenario therefore our content for this file would be:

 

 

 

 

XsltTransformation=ChangeQuantity.xslt

 

 

 

 

The change quantity xslt looks like this:

 

 

 

 

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="root">
        <root>
            <xsl:copy-of select="process"/>
            <xsl:copy-of select="region"/>
            <xsl:copy-of select="prod_date"/>
            <quantity>
                <xsl:value-of select="quantity * 2"/>
            </quantity>
            <xsl:copy-of select="batch"/>
            <xsl:copy-of select="batchplant"/>
            <xsl:copy-of select="country"/>
            <xsl:copy-of select="material"/>
        </root>
    </xsl:template>
</xsl:stylesheet>

 

 

 

 

Quantities are doubled whenever Country is PT so requirement 3 was fulfilled.

Let’s now go to the second level which is a lookup by process. On this one we execute the xpath that is on the second lookup which is //process. With that on the first payload we get the value CreateBatch. Now we define a new text file named NUPEBPAPOC~CreateBatch and we load the following into it:

 

 

 

 

SAP_IDOC_REC_Address=https://testnupeglobalbatch.free.beeceptor.com
XsltTransformation=FormatDate.xslt

 

 

 

 

What do we have here? If the process is the create batch, we’re redefining the url into more specific one for this process. Everything else is inherited from the previous level (defaults). Besides a change on the url, if the process is create batch we want to format a date according to an xslt file named FormatDate.xslt existing on the same directory with contents below:

 

 

 

 

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/root">
        <batch>
            <ProductionDate><xsl:value-of select="concat(substring(prod_date, 1, 4), '-', substring(prod_date, 5, 2), '-', substring(prod_date, 7, 2))"/></ProductionDate>
            <BatchNumber>
                <xsl:value-of select="batch"/>
            </BatchNumber>
            <Quantity>
                <xsl:value-of select="quantity"/>
            </Quantity>
			<Region><xsl:value-of select="region"/></Region>
			<Process><xsl:value-of select="process"/></Process>
        </batch>
    </xsl:template>
</xsl:stylesheet>

 

 

 

 

With this we've formatted the date into the yyyy-MM-dd expected format according to requirement 1 and 2. 

Now let’s tackle the other part of formatting quantity of requirement 2. This we only apply for EMEA and for CreateBatch, so we need a lookup by process and region. This is what the last lookup specifies:

 

 

 

 

<lookup>
    <xpath>concat(//Process,//Region)</xpath>
</lookup>

 

 

 

 

What we do with this is fetching the process and region from current payload and concatenate it as part of the xpath evaluation. For second payload example this would return “CreateBatchEMEA”. If we now create a new file NUPEBPAPOC~CreateBatchEMEA.txt we can define settings that should only apply whenever the process and region matches this exact combination:

 

 

 

 

SAP_IDOC_REC_Address=https://testnupeemeabatch.free.beeceptor.com
XsltTransformation=FormatQuantityEMEA.xslt

 

 

 

 

Here we define again an overwrite of url to a specific one for EMEA and we format  the quantity into European format by creating a FormatQuantityEMEA.xslt with the contents below:

 

 

 

 

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:decimal-format name="european" decimal-separator="," grouping-separator="."/>
    
    <xsl:template match="/batch">
        <batch>
            <ProductionDate>
                <xsl:value-of select="ProductionDate"/>
            </ProductionDate>
            <BatchNumber>
                <xsl:value-of select="BatchNumber"/>
            </BatchNumber>
            <Quantity>
                <xsl:value-of select="format-number(Quantity, '#.###,00', 'european')"/>
            </Quantity>
        </batch>
    </xsl:template>
</xsl:stylesheet>

 

 

 

 

You might question that for EMEA we shall also format the date. You’re right and this was done whenever we processed the NUPEBPAPOC~CreateBatch level which was executed before a part of the second rules iteration "//process".

Ok, so now all configuration is done. If everything was done properly we'll have a directory with all config.

dynamic_intf_cfg.png

We just need a url to send it to our customers to use and test this. The url is https://<cloudintegrationrturl>/http/TestpackageNUPE/FER_DynamicInterfaceTransformAndRoute/NUPEBPAPOC

Now with your eagle eye you spotted that NUPEBPAPOC is part of the url as well. This is how we can have a single generic iflow that is prepared to receive or deal with multiple interface scenarios. So that interface needs to match with the filenames defined above. Another thing you might notice is that for this demo I'm showing a generic iflow that is on a test package. Reason for this is that BPA integration into it is quite new and we want to test it deeply before integrating into the main code.

In this part we checked everything that is needed in design time, it looks like a lot of work, but it isn't. I demoed that we can call BPA (though it was not necessary for this case since we could simply have created NUPEBPAPOC~PT and I've explained how the rules are processed.

Feel free to comment with ideas, suggestions, problems or your own approach to this problem 

Next chapter we'll check how to deploy it