Debatching SAP BAPI Transaction Requests

This post has been republished via RSS; it originally appeared at: New blog articles in Microsoft Tech Community.

Introduction

 

This article is the second installment of a series on the scenario used in SAP BAPI Transactions Walkthrough, which should be read before this blog post.

 

Here, instead of receiving a pre-determined number of BAPI transaction requests one at a time, the orchestration expects a single document containing a batch of requests, as well as the desired outcome (commit or rollback). Debatching of XML messages into single BAPI transaction requests is done inside the orchestration by calling the default XMLReceive pipeline. General documentation regarding this orchestration feature may be found at How to Use Expressions to Execute Pipelines

 

The choice of in-orchestration pipeline processing over direct processing in the receive port is mostly arbitrary. It allows us to keep this presentation focused on a single place where the different stages are integrated. The orchestration is well-suited for a workflow of multiple actions and custom error handling. There are pros and cons mentioned in the literature regarding both options and it would take another post to cover them in detail.

It is worth mentioning that with in-orchestration pipelines:

- Transforms can happen before debatching, which in some cases could be a hard requirement;

- It is possible to enumerate over messages of different types;

- Failures result in exceptions being thrown rather than messages being suspended by the pipeline (see for instance Error Handling for failure behavior in the pipeline stage). The thrown exceptions can be handled in a catch block within the calling orchestration, which could allow for graceful error handling with BAPI_TRANSACTION_ROLLBACK.

 

Debatching with Receive Pipeline

 

Pipeline processing of messages containing batches of orders can summarized as :

 

Article2PipelineMessageProcessing.PNG

 

Envelope Schema

 

The first step for using a debatching pipeline is to define an envelope schema to represent multiple orders. This is done according to the following process, initially documented in Calling a pipeline inside an orchestration.

 

  1. Add a new schema file to the project.
  2. Change the root node name to "Orders".
  3. In the properties window for the <schema> treeview node: (a) change the Envelope property to Yes, and (b) import the Order schema.
  4. In the properties window for the "Orders" root node, set the Body XPath property to /*[local-name()='Orders' and namespace-uri()='<namespace of the schema here'
  5. Insert a child record under the root node.
  6. In the child record properties, set the data structure type field to Order. As a result, the Order definition will appear under Orders.

 

CreateEnvelopeSchemaREDUX.png

 

IsCommit is a promoted property which is used later on for deciding whether to commit or rollback the transaction batch. Orders corresponds to the envelope schema imported into RequestsInfo. The Orders element is extracted by a transform shape into a message called SalesOrders.

Note: the RequestsInfo schema could also be an envelope schema for Order, instead of the Orders schema.

 

Implementing the Pipeline

 

Before using the pipeline, the following dependencies must be added to the BizTalk project:

  • Microsoft.XLANGs.Pipeline.dll
  • Microsoft.BizTalk.Pipeline.dll

The pipeline must be inside a scope of type Atomic because it is of non-serializable type. As a result, the orchestration has to be of type "Long running". Inside the atomic scope, the first expression starts the pipeline execution:

 

PipelineOutputMessageVar = Microsoft.XLANGs.Pipeline.XLANGPipelineManager.ExecuteReceivePipeline(typeof(Microsoft.BizTalk.DefaultPipelines.XMLReceive), SalesOrders);

 

where PipelineOutputMessageVar is a variable of type Microsoft.XLANGs.Pipeline.ReceivePipelineOutputMessages and is used to iterate in a loop shape with the expression:

 

PipelineOutputMessageVar.MoveNext()

 

Inside the loop shape, a message of type Order, CurrentOrder, is assigned as follows:

 

CurrentOrder = null; PipelineOutputMessageVar.GetCurrent(CurrentOrder);

 

CurrentOrder is then mapped to a message (BAPIMessage) of type BUS2032.CREATEFROMDAT2.

 

The figure below shows the entire pipeline stage:

 

AnnotatedPipelineREDUX.png

 

Caching BAPIMessages

 

Ideally, the BAPIMessages should be sent to the SAP server from within the pipeline, by using the send-receive port connected to SAP. However, an atomic scope may not contain both the send and the corresponding receive (see a detailed explanation here); in our case, the SAP adapter port needs to be bidirectional because the orchestration needs the document id contained in the response and which is used later on to query the transactions status. To work around this limitation, BAPIMessages are saved in a list object to be used outside the pipeline scope:

 

TempXmlData = BAPIMessage; BAPIOrders.AddFromXMLString(TempXmlData);

 

where TempXmlData is a variable of type XmlDocument, and BAPIOrders is of custom type BAPIOrderList added in a helper library.

 

namespace SapBAPITxClientDebatching { [Serializable] public class BAPIOrdersList : List<CREATEFROMDAT2> { public BAPIOrdersList() { } public void AddFromXMLString(XmlDocument document) { MemoryStream stream = new MemoryStream(); document.Save(stream); stream.Flush(); stream.Position = 0; XmlSerializer reader = new System.Xml.Serialization.XmlSerializer(typeof(CREATEFROMDAT2)); StreamReader st = new StreamReader(stream); this.Add((CREATEFROMDAT2)reader.Deserialize(st)); st.Close(); } public CREATEFROMDAT2 Get(int index) { return this[index]; } public int OrdersCount() { return this.Count; } } }

 

The helper library also contains C# classes corresponding to the BAPI transactions schemas generated by running the xsd.exe utility on the BAPI schemas generated in Visual Studio.

 

Processing the debatched BAPI Transactions

 

Once all Order elements have been debatched, the orchestration exits the pipeline atomic scope and iterates over the list of BAPI transaction messages to serialize and send to the send-receive port (LOBPort) connected to the SAP server. This stage is identical to Stage 2 in SAP BAPI Transactions Tutorial except that here, BAPI transaction requests are provided by the orchestration variable BAPIOrders.

 

DebatchingStage2AnnotatedREDUX.png

 

The Global Picture

 

Subsequent stages of the orchestration are presented in detail in SAP BAPI Transactions Tutorial. In Stage 3, the action to take (Commit/Rollback) is determined by the IsCommit promoted property mentioned earlier.

 

DebatchingOrchestrationREDUXS1.png

DebatchingOrchestrationREDUXS2.png

DebatchingOrchestrationREDUXS3.png

DebatchingOrchestrationREDUXS4.png

 

Concluding Remarks

 

The aim of this post was to extend the BAPI tutorial scenario by showing BAPI transactions working with known BizTalk patterns such as debatching. Another pattern to consider is Scatter-Gather, of which debatching is the first step. This will be the topic of another blog post.

 

All code used in this article is attached.

 

References

 

SAP BAPI Transactions Tutorial

Calling a pipeline inside an orchestration

Debatching in orchestration

Performance study of debatching within an orchestration

Different techniques of debatching in orchestration

How to Use Expressions to Execute Pipelines

Error Handling in Pipelines

 

For more general info on the SAP Adapter:

Operations on BAPIs in SAP

Run BAPI Transactions in SAP using BizTalk Server

Message Schemas for BAPI Operations

SAP Adapter documentation

Registry setting to enable BAPI transactions

Get Metadata for SAP Operations in Visual Studio

Browse, search, and retrieve metadata from SAP for BAPI operations

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.