Acknowledgements in BizTalk

Acknowledgements in BizTalk

Acknowledgements in BizTalk

Today I want to talk to you about sending Acknowledgements from BizTalk which can be achieved with and without using Orchestration. Whenever we are using Request Response Receive adapter we need to send acknowledgements to the source application on receiving the message in the BizTalk. The Scenarios are listed down below:
– 2 way WCF-SAP Adapter
– 2 way MLLP Adapter – 2 way WCF SQL Adapter
In some cases the messages just need an acknowledgement to ensure the message has reached the BizTalk and it is time to send the next message and in few other cases all the messages being sent are waiting for an acknowledgement to ensure the batch of messages in the queue can be deleted.
In few of the cases the acknowledgement are expected to the static response while in other cases they need some data, based on the received message, to be plugged in the response. There are many other Scenarios but just wanted to concentrate on very few ones here.
How to create the Acknowledgement and send it?
With Orchestration:
1. Receive Message from Request-Response Port with Port bindings: ‘Specify later’
2. Create the response (irrespective of the whether response is static or based on the request message) in the Construct Message Shape
3. Send Response message through Request-Response Port as depicted in the figure below
This is the simplest approach but overhead is this approach uses the XLang engine for acknowledgement
With Pipeline:
1. The Code for the Pipeline component responsible for promoting the properties required for Ack and also to send the Ack is as below

namespace PipelineComponents.Ack
{
using System;
using System.IO;
using System.Text;
using System.Drawing;
using System.Resources;
using System.Reflection;
using System.Diagnostics;
using System.Collections;
using System.ComponentModel;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.Component;
using Microsoft.BizTalk.Messaging;
using Microsoft.BizTalk.Streaming;
[ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
[System.Runtime.InteropServices.Guid(“bbcf1287-f4fb-41f8-97b2-b329e5153658”)]
[ComponentCategory(CategoryTypes.CATID_Any)]
publicclass Ack : Microsoft.BizTalk.Component.Interop.IComponent,IBaseComponent,IPersistPropertyBag,IComponentUI
{
private System.Resources.ResourceManager resourceManager = new System.Resources.ResourceManager(“PipelineComponents.Ack.Ack”,Assembly.GetExecutingAssembly());
privatebool _IsEnabled;
publicbool IsEnabled
{
get
{
return _IsEnabled;
}
set
{
_IsEnabled =value;
}
}
privatebool _IsStaticResponse;
publicbool IsStaticResponse
{
get
{
return _IsStaticResponse;
}
set
{
_IsStaticResponse =value;
}
}
privatebool _IsReceive;
publicbool IsReceive
{
get
{
return _IsReceive;
}
set
{
_IsReceive =value;
}
}
privatestring _StaticResponse;
publicstring StaticResponse
{
get
{
return _StaticResponse;
}
set
{
_StaticResponse =value;
}
}
#region IBaseComponent members
/// < summary>
/// Name of the component
/// < /summary>
[Browsable(false)]
publicstring Name
{
get
{
return“Ack”;
}
}
/// <summary>
/// Version of the component
/// < /summary>
[Browsable(false)]
publicstring Version
{
get
{
return“1.0”;
}
}
// Author: Nihar Malali
/// < summary>
/// Description of the component
/// < /summary>
[Browsable(false)]
publicstring Description
{
get
{
return“For Acknowledgment”;
}
}
#endregion
#region IPersistPropertyBag members
// Author: Nihar Malali
/// < summary>
/// Gets class ID of component for usage from unmanaged code.
/// < /summary>
/// < param name=”classid”>
/// Class ID of the component
/// < /param>
publicvoid GetClassID(out System.Guid classid)
{
classid =new System.Guid(“bbcf1287-f4fb-41f8-97b2-b329e5153658”);
}
/// < summary>
/// not implemented
/// < /summary>
publicvoid InitNew()
{
}
// Author: Nihar Malali
/// < summary>
/// Loads configuration properties for the component
/// < /summary>
/// < param name=”pb”>Configuration property bag</param>
/// < param name=”errlog”>Error status</param>
publicvirtual void Load(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, int errlog)
{
object val =null;
val =this.ReadPropertyBag(pb,”IsEnabled”);
if ((val !=null))
{
this._IsEnabled = ((bool)(val));
}
val =this.ReadPropertyBag(pb,”IsStaticResponse”);
if ((val !=null))
{
this._IsStaticResponse = ((bool)(val));
}
val =this.ReadPropertyBag(pb,”IsReceive”);
if ((val !=null))
{
this._IsReceive = ((bool)(val));
}
val =this.ReadPropertyBag(pb,”StaticResponse”);
if ((val !=null))
{
this._StaticResponse = ((string)(val));
}
}
// Author: Nihar Malali
/// < summary>
/// Saves the current component configuration into the property bag
/// < /summary>
/// < param name=”pb”>Configuration property bag</param>
/// < param name=”fClearDirty”>not used</param>
/// < param name=”fSaveAllProperties”>not used</param>
publicvirtual void Save(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, bool fClearDirty,bool fSaveAllProperties)
{
this.WritePropertyBag(pb,”IsEnabled”,this.IsEnabled);
this.WritePropertyBag(pb,”IsStaticResponse”,this.IsStaticResponse);
this.WritePropertyBag(pb,”IsReceive”,this.IsReceive);
this.WritePropertyBag(pb,”StaticResponse”,this.StaticResponse);
}
#region utility functionality
/// < summary>
/// Reads property value from property bag
/// < /summary>
/// < param name=”pb”>Property bag</param>
/// < param name=”propName”>Name of property</param>
/// < returns>Value of the property</returns>
privateobject ReadPropertyBag(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, string propName)
{
object val =null;
try
{
pb.Read(propName,out val, 0);
}
catch (System.ArgumentException )
{
return val;
}
catch (System.Exception e)
{
thrownew System.ApplicationException(e.Message);
}
return val;
}
/// < summary>
/// Writes property values into a property bag.
/// < /summary>
/// < param name=”pb”>Property bag.</param>
/// < param name=”propName”>Name of property.</param>
/// < param name=”val”>Value of property.</param>
privatevoid WritePropertyBag(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, string propName,object val)
{
try
{
pb.Write(propName,ref val);
}
catch (System.Exception e)
{
thrownew System.ApplicationException(e.Message);
}
}
#endregion
#endregion
#region IComponentUI members
/// < summary>
/// Component icon to use in BizTalk Editor
/// < /summary>
[Browsable(false)]
publicIntPtr Icon
{
get
{
return ((System.Drawing.Bitmap)(this.resourceManager.GetObject(“COMPONENTICON”, System.Globalization.CultureInfo.InvariantCulture))).GetHicon();
}
}
/// < summary>
/// The Validate method is called by the BizTalk Editor during the build
/// of a BizTalk project.
/// < /summary>
/// < param name=”obj”>An Object containing the configuration properties.</param>
/// < returns>The IEnumerator enables the caller to enumerate through a collection of strings containing error messages. These error messages appear as compiler error messages. To report successful property validation, the method should return an empty enumerator.</returns>
public System.Collections.IEnumerator Validate(object obj)
{
// example implementation:
// ArrayList errorList = new ArrayList();
// errorList.Add(“This is a compiler error”);
// return errorList.GetEnumerator();
returnnull;
}
#endregion
#region IComponent members
public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(Microsoft.BizTalk.Component.Interop.IPipelineContext pc, Microsoft.BizTalk.Message.Interop.IBaseMessage inmsg)
{
if (IsEnabled)
{
int bufferSize = 0x280;
int thresholdSize = 0x100000;
IBaseMessageContext messageContext = inmsg.Context;
IBaseMessagePart bodyPart = inmsg.BodyPart;
string msgout =””;
Stream inboundStream = bodyPart.GetOriginalDataStream();
VirtualStream virtualStream =newVirtualStream(bufferSize, thresholdSize);
ReadOnlySeekableStream readOnlySeekableStream =newReadOnlySeekableStream(inboundStream, virtualStream, bufferSize);
if (IsReceive)
{
#region RecieveLogic
try
{
string EpmRRCorrelationToken =String.Empty;
bool RouteDirectToTP =true;
object objEpmToken = messageContext.Read(“EpmRRCorrelationToken”, sysproperty_namespace);
if (objEpmToken !=null)
EpmRRCorrelationToken = (string)objEpmToken;
else
EpmRRCorrelationToken = System.Guid.NewGuid().ToString();
messageContext.Promote(“EpmRRCorrelationToken”, sysproperty_namespace, EpmRRCorrelationToken);
messageContext.Promote(“RouteDirectToTP”, sysproperty_namespace, RouteDirectToTP);
readOnlySeekableStream.Position = 0;
bodyPart.Data = readOnlySeekableStream;
readOnlySeekableStream.Position = 0;
bodyPart.Data = readOnlySeekableStream;
}
catch (Exception ex)
{
throw (ex);
}
#endregion
}
else
{
if (IsStaticResponse)
msgout = StaticResponse;
else
{
//comment the below line and add your Logic to create your Acknowledgement Message here
msgout = StaticResponse;
}
}
VirtualStream outStream =newVirtualStream();
StreamWriter sw =newStreamWriter(outStream,Encoding.Default);
sw.Write(msgout);
sw.Flush();
outStream.Seek(0,SeekOrigin.Begin);
inmsg.BodyPart.Data = outStream;
pc.ResourceTracker.AddResource(outStream);
}
return inmsg;
}
#endregion
}
}
2. Build and Deploy this Pipeline Component
3. Add this component in any stage of the pipeline
4. The Configuration for Receive pipeline will look something like this
The Configuration for the send pipeline will look something like this
How this works?
1. If you look at the subscription you will observe that the Request-Response Receive location is has a subscription for response message and following screenshot depicts the details of the subscription
2. Hence, Promote following 2 properties of the Request Message in Receive Pipeline of the Request-Response Receive Location
And
3. The moment the Request message hits the message box the request message will be picked up by the Subscription waiting on the response message
4. Now if the Acknowledgement is expected to be Static then Hardcode the Message in the Send Pipeline else write the business logic for creating the response message with the Pipeline component
For Static Response this will work Amazing with no performance overhead and in case if you want to create the acknowledge based on the request message or other parameters then add the logic for creating the acknowledgement in the section where you will find the below comment in the above code 🙂 :
//comment the below line and add your Logic to create your Acknowledgement Message here

Happy Coding!!!
NIHAR MALALI
Nihar Malali Avatar

Posted by

Leave a comment

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