Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
vadimklimov
Active Contributor

Intro


During development of scenarios with Quality of Service = Exactly Once In Order and involving polling sender adapter types (e.g. SFTP, File/FTP, JDBC, Mail, REST in polling mode), as well as some other adapter types (REST in push mode), it is required to set queue name / sequence ID dynamically, based on data contained in the processed message. Standard functionality of such adapters provides support for fixed queue name that is specified in configuration of a sender communication channel (which means, all messages processed by this communication channel, will be sequenced using a single queue / serialization context, which is often not acceptable / optimal), but it lacks functionality of setting queue name dynamically at runtime. In order to fulfil such described requirement, commonly used solution is to develop a custom adapter module. The approach is based on overwriting sequence ID of a processed XI message using standard API of Adapter Framework of Advanced Adapter Engine (refer to SAP JavaDocs for class com.sap.engine.interfaces.messaging.api.Message), and setting the required sequence ID (commonly, its value is based on value of some payload element that can be accessed using XPath). A custom adapter module has to be placed before the XI message reaches Messaging System (which translates to adding this custom module before standard adapter module CallSapAdapter is called in the module processing sequence of a communication channel).

 

In this blog, I’m not going to dive into details of this approach, since it has already been well described by other SCN community members in the past and examples of corresponding adapter modules have been provided and can be found on SCN – here are just few links and references to materials that have good outlook at this approach and its implementation:

 

Observation of many materials which describe this requirement and solution, and some degree of repeated development in this field undertaken by different teams, motivated me for writing this blog, which aim is to prepare an adapter module that is capable of fulfilling majority of requirements raised in the described area and collected from SCN blogs and forums, as well as those originating from projects I was involved in. Intention is to share with the community the adapter module that is generic enough to be re-used in various projects facing similar requirements, and enable reduction of repeated development efforts.

Adapter module configuration


Module name: Custom_AF_Modules/SetSequenceIdBean.

Below is a list of adapter module parameters. Note that only parameter used to specified XPath expression, is mandatory - all others are optional. Majority of optional parameters are used to further customize determined sequence ID and can be combined in order to achieve the required pattern of the determined sequence ID.





































































Parameter name Description Possible values Default value / behaviour Mandatory or optional
xpath XPath expression that shall extract required payload element’s value for dynamic sequence ID String value containing valid XPath Mandatory
error.terminate Terminate execution of the module if sequence ID cannot be set, causing also termination of further message processing by a channel. Not recommended to be disabled if dynamic sequence ID generation is a must Boolean or Boolean equivalents (case insensitive):

  • true, yes, 1 – to enable

  • false, no, 0 – to disable


true (enabled) Optional
sequenceId.deleteLeadingCharacter Delete leading characters from the extracted value for the specified XPath expression Boolean or Boolean equivalents (case insensitive):

  • true, yes, 1 – to enable

  • false, no, 0 – to disable


false (disabled) Optional
sequenceId.leadingCharacter Leading character String value containing 1 character Optional
sequenceId.replaceInvalidCharacters Replace all invalid (not alphanumeric) characters from the constructed sequence ID with underscore symbol ('_') Boolean or Boolean equivalents (case insensitive):

  • true, yes, 1 – to enable

  • false, no, 0 – to disable


false (disabled) Optional
sequenceId.truncate Truncate constructed sequence ID so that its length does not exceed restrictions applicable for sequence ID (which is, 16 characters) – truncation can be either done to trim beginning of the value or its end. If the value retrieved using the specified XPath, is object identifier (e.g. customer number, sales order number, employee ID) that is iteratively increased for every subsequent instance of an object (e.g. sender system uses number range object for it), then truncation from start may be preferable, leaving a value part varying between closely following instances of objects Below values are accepted (case insensitive), all others are ignored:

  • start – to truncate beginning of the value

  • end – to truncate end of the value


(disabled) Optional
sequenceId.prefix Fixed prefix value for a constructed sequence ID, which will be delimited from remaining sequence ID value part with uderscore symbol ('_'). Shall not normally contain many characters since it may negatively impact overall length of the constructed sequence ID - optimum is 2-3 characters. From perspective of impact on total sequence ID value length, it is not recommended to use prefix and suffix at the same time. Note that if truncation is enabled for start of the value, prefix may become truncated String value (disabled) Optional
sequenceId.suffix Fixed suffix value for a constructed sequence ID, which will be delimited from remaining sequence ID value part with uderscore symbol ('_'). Shall not normally contain many characters since it may negatively impact overall length of the constructed sequence ID - optimum is 2-3 characters. From perspective of impact on total sequence ID value length, it is not recommended to use prefix and suffix at the same time. Note that if truncation is enabled for end of the value, suffix may become truncated String value (disabled) Optional


Usage


In all examples below, in the sender communication channel, Quality of Service = Exactly Once In Order was selected and queue name = 'DEMO' was provided:



XPath expression is the only mandatory parameter for the developed adapter module - so let me start with the basic configuration involving only that parameter:



Following payload of the incoming message, against which XPath is applied, is used in this example:

 

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>
<Object>
<ID>00012345</ID>
<Text>Test message</Text>
</Object>
</test:GenericObjects>














 

As it can be seen, at runtime, the fixed sequence ID ('DEMO') was overwritten by the one determined based on the message payload ('00012345'):



Next example demonstrates combined usage of several additional parameters to fine tune sequence ID determination more precisely:



Following payload of the incoming message, against which XPath is applied, is used in this example:

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>
<Object>
<ID>0000012345:test-obj</ID>
<Text>Test message</Text>
</Object>
</test:GenericObjects>





When executed at runtime, this leads to the following sequence ID determination and overwriting:



To give feeling of impact of various other module parameters, some more examples of determined sequence ID based on module parameterization and message payload, are given in the table below. Please note that for parameters expecting Boolean values, I used various acceptable values (true/false, True/False, yes/no, 1/0) in sake of demonstration of different possible alternatives to provide configuration for them - in scenarios, it is advisable to select consistent value alternatives and use them for all Boolean parameters configuration (e.g. only true or false, only yes or no, etc.) in order to make adapter module configuration more readable.
























































































































Module parameterization Incoming message payload Determined sequence ID / error Comments
(no module parameterization provided)

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>

  <Object>

    <ID>00012345</ID>

    <Text>Test message</Text>

  </Object>

</test:GenericObjects>
ModuleException: One or several required adapter module parameters are missing or incorrect Mandatory parameter 'xpath' is missing
error.terminate = 0

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


DEMO Mandatory parameter 'xpath' is missing, but termination on error is disabled, so channel default configuration (fixed queue name) is used
xpath = /GenericObjects/ID

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


ModuleException: Failure while attempting to set sequence ID Application of the specified XPath to message payload didn't yield to extraction of any value
xpath = /GenericObjects/Object/ID

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


00012345
xpath = /GenericObjects/Object/ID

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00000000000000012345</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


ModuleException: Failure while attempting to set sequence ID Constructed sequence ID length is larger than acceptable limit (16 characters)


xpath = /GenericObjects/Object/ID

error.terminate = False

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00000000000000012345</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


DEMO Constructed sequence ID length is larger than acceptable limit (16 characters), but termination on error is disabled, so channel default configuration (fixed queue name) is used
xpath = /GenericObjects/Object/ID

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345</ID>


    <Text>Test message</Text>


  </Object>


  <Object>


    <ID>00098765</ID>


    <Text>Test message 2</Text>


  </Object>


</test:GenericObjects>


ModuleException: Failure while attempting to set sequence ID Multiple different (distinct) values were retrieved from the message’s payload using specified XPath


xpath = /GenericObjects/Object/ID

multipleValues.error = no

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345</ID>


    <Text>Test message</Text>


  </Object>


  <Object>


    <ID>00098765</ID>


    <Text>Test message 2</Text>


  </Object>


</test:GenericObjects>


00012345 Multiple different (distinct) values were retrieved from the message’s payload using specified XPath, but termination for such cases is disabled, so the first of those values was used when constructing sequence ID


xpath = /GenericObjects/Object/ID

sequenceId.deleteLeadingCharacter = true

sequenceId.leadingCharacter = 0

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


12345

xpath = /GenericObjects/Object/ID


sequenceId.deleteLeadingCharacter = true


sequenceId.leadingCharacter = 00



<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


00012345 Leading characters were not deleted, because incorrect value was specified in parameter 'sequenceId.leadingCharacter' (multiple characters instead of an expected one leading character)

xpath = /GenericObjects/Object/ID


sequenceId.deleteLeadingCharacter = true



<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


00012345 Leading characters were not deleted, because leading character was not specified was not specified (parameter 'sequenceId.leadingCharacter' missing)


xpath = /GenericObjects/Object/ID

sequenceId.truncate = start

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


00012345 Determined sequence ID value is already less than 16 characters long, so its truncation is not required and was skipped


xpath = /GenericObjects/Object/ID

sequenceId.truncate = end

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>TEST_OBJECT_123456789</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


TEST_OBJECT_1234


xpath = /GenericObjects/Object/ID

sequenceId.truncate = begin

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>TEST_OBJECT_123456789</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


ModuleException: Failure while attempting to set sequence ID Incorrect value specified for parameter 'sequenceId.truncate' (only 'start' and 'end' are valid values)

xpath = /GenericObjects/Object/ID


sequenceId.replaceInvalidCharacters = true



<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>TEST%OBJECT-01</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


TEST_OBJECT_01

xpath = /GenericObjects/Object/ID


sequenceId.prefix = v



<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


V_00012345

xpath = /GenericObjects/Object/ID


sequenceId.suffix = r2



<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


00012345_R2


xpath = /GenericObjects/Object/ID

sequenceId.deleteLeadingCharacter = yes

sequenceId.leadingCharacter = 0

sequenceId.prefix = v

sequenceId.suffix = r2

sequenceId.truncate = start

<test:GenericObjects xmlns:test='urn:doc.com/Test' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>


  <Object>


    <ID>00012345_TEST_OBJECT</ID>


    <Text>Test message</Text>


  </Object>


</test:GenericObjects>


5_TEST_OBJECT_R2 Even though set initially, prefix, as well as part of the original value retrieved using XPath expression, are truncated, because truncation from start was enabled and constructed sequence ID value after deleting leading symbols and adding prefix and suffix turned to be longer than 16 characters


Source code and deployable


Source code of the adapter module and corresponding accompanying development artifacts are available at

GitHub repository for SetSequenceIdBean

 

Compiled and built latest version of the adapter module, assembled into deployable EAR file, is available at

Latest release of SetSequenceIdBean

 

The adapter module has been compiled in compliance to JDK 1.6, and has been successfully tested in PO 7.31 and PO 7.4 systems.

Outro


I will highly appreciate your feedback left in comments to this blog and encourage you sharing ideas about demanded, but yet missing functionality of this adapter module. This will help a lot on the way of enriching future versions of the module with new features based on your suggestions, and increasing module’s re-usability.

25 Comments
Labels in this area