Posts

User Defined Functions in SAP PI mappings

User Defined Functions (UDF) are functions defined by a programmer, which can be used in SAP PI graphical mappings. UDFs are defined in Java programming language and allow running any custom code on XML field mapping stage, significantly extending possibilities of message field and value mapping.

UDFs are represented by one block in graphical mappings. They can be utulised to simplify implementation of logic, that requires using multiple standard mapping blocks:

udf-01

UDF can be created by clicking the icon in lower-left corner of graphical mapping editor window:

udf-02

In the simplest caase it is enough to provide some basic data – function’s name and title, and its input arguments. Arguments’ value can be assigned in the same way as for standard mapping blocks – using arrows on function’s input and output:

udf-02a

The next step is implementation of function in Java programming language. Input and output are handled in the same fashion as other Java functions or methods – through arguments and return statement. The below screen shows a UDF function, that works in the same way that the graphical mapping above.

udf-03

UDF Parameters

Configuration values can be assigned as UDF parameters. They will be passed to the function as arguments, too, but their values are defined in graphical mapping editor.

udf-04

udf-05

UDF Testing

After saving the function, it can be used in graphical mapping, connecting inputs and output. Similarly to standard mapping blocks, after running a test case, a queue of arguments and returned values can be viewed under Display Queue:

udf-06

In the above example, UDF has been utilised to simplify value mapping implementation. Depending on needs, a programmer can use a variety of Java language features to implement more complex mappings, than standard mapping blocks allow.

Overview of new features in SAP Process Integration 7.31

Limitations of earlier version: SAP PI 7.11

  • Idoc and HTTP adapters are not available for Integrated Configuration
  • Multimapping (1:n) is not possible in ICO
  • Content based interface routing in ICO is not possible

New Advanced Adapter Engine connectivity options

IDOC_AAE

  • Idoc packaging is possible (not for outbound)
  • Adapter modules can be added to Idoc configuration
  • ALEAUDIT is supported

HTTP_AAE

  • New features: POST and Multipart document

SFTP adapter

  • add-on available from PI 7.11 SP08

Integrated configuration improvements

Multimapping possible in ICO

  • 1:n mappings
  • Content based selection of inbound interface

PI 7.31 ICO Multimapping

Monitoring tools

  • Idoc Message Monitor (it replaces IDX5)

PI 7.31 Idoc Monitor

  • Metadata Monitor

PI 7.31 Metadata Monitor

  • New message monitor

PI 7.31 Message Monitor

 

  • Ping option
    • Check connectivity
    • User/password
    • Authorizations (e.g. ftp access)
    • Connectivity (e.g. firewall settings)

PI 7.31 Ping 1

 

PI 7.31 Ping 2

User Defined Message Search

  • No need to use TREX
  • Usually used to search by key fields (Order Number, Partner ID)
  • A filter is defined per interface
  • Allows search by defined key that can be configured as:
    • XPATHXPATH 
    • Dynamic Header

      Dynamic Header
  • Indexing possible for messages processed prior to defining filter
  • Index is deleted when the message is archived

 

 

XSLT mapping to a flat file

In certain cases it is required to send an output mapping file as a flat file with specified field lengths. When the file adapter is used it is recommended to use standard File Content Conversion. However, in case of i.e. calling web service using SOAP adapter the best option is XSLT transformation. For the sample input file:

[codesyntax lang=”xml” lines=”normal”]

<Order>
   <Header>
      <DocumentNumber>001</DocumentNumber>
      <Date>20140401</Date>
   </Header>
   <Line>
      <ItemNumber>1</ItemNumber>
      <Material>1203040</Material>
      <Quantity>10</Quantity>
      <UOM>PCE</UOM>
   </Line>
   <Line>
      <ItemNumber>2</ItemNumber>
      <Material>2349040</Material>
      <Quantity>20</Quantity>
      <UOM>PCE</UOM>
   </Line>
</Order>

[/codesyntax]

After using XSLT transformation that creates a new line for each occurrence of a <Line> element and sets field lengths to: 20, 20, 3, 20, 5, 5:

[codesyntax lang=”xml” lines=”normal”]

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="text" indent="yes" encoding="UTF-8" />
   <xsl:variable name="DocumentNumber">
      <xsl:call-template name="padRightSide">
         <xsl:with-param name="stringToPad" select="Order/Header/DocumentNumber" />
         <xsl:with-param name="totalLength" select="20" />
      </xsl:call-template>
   </xsl:variable>
   <xsl:variable name="Date">
      <xsl:call-template name="padRightSide">
         <xsl:with-param name="stringToPad" select="Order/Header/Date" />
         <xsl:with-param name="totalLength" select="20" />
      </xsl:call-template>
   </xsl:variable>
   <xsl:template match="/Order">
      <xsl:for-each select="Line">
         <!-- Repeat header data -->
         <xsl:copy-of select="$DocumentNumber" />
         <xsl:copy-of select="$Date" />
         <!-- Item data -->
         <xsl:call-template name="padRightSide">
            <xsl:with-param name="stringToPad" select="ItemNumber" />
            <xsl:with-param name="totalLength" select="3" />
         </xsl:call-template>
         <xsl:call-template name="padRightSide">
            <xsl:with-param name="stringToPad" select="Material" />
            <xsl:with-param name="totalLength" select="20" />
         </xsl:call-template>
         <xsl:call-template name="padRightSide">
            <xsl:with-param name="stringToPad" select="Quantity" />
            <xsl:with-param name="totalLength" select="5" />
         </xsl:call-template>
         <xsl:call-template name="padRightSide">
            <xsl:with-param name="stringToPad" select="UOM" />
            <xsl:with-param name="totalLength" select="5" />
         </xsl:call-template>
         <!-- End Line -->
         <xsl:text />
      </xsl:for-each>
   </xsl:template>
   <xsl:template name="padRightSide">
      <xsl:param name="totalLength" />
      <xsl:param name="padChar" select="' '" />
      <xsl:param name="stringToPad" />
      <xsl:param name="padBuffer" select="concat($padChar,$padChar,$padChar,$padChar,$padChar, $padChar,$padChar,$padChar,$padChar,$padChar )" />
      <xsl:variable name="vNewString" select="concat($stringToPad, $padBuffer)" />
      <xsl:choose>
         <xsl:when test="not(string-length($vNewString) &gt;= $totalLength)">
            <xsl:call-template name="padRightSide">
               <xsl:with-param name="stringToPad" select="$vNewString" />
               <xsl:with-param name="totalLength" select="$totalLength" />
               <xsl:with-param name="padChar" select="$padChar" />
               <xsl:with-param name="padBuffer" select="$padBuffer" />
            </xsl:call-template>
         </xsl:when>
         <xsl:otherwise>
            <xsl:variable name="output">
               <xsl:value-of disable-output-escaping="no" select="substring($vNewString,1,$totalLength)" />
            </xsl:variable>
            <xsl:value-of select="$output" />
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

[/codesyntax]

we get:
001 20140401 1 1203040 10 PCE
001 20140401 2 2349040 20 PCE

 

Portfolio Items