BAM data of Port Messaging Properties doesn't get correctly populated when using Passthrough Pipeline on BizTalk 2013 R2


The problem:

================================

 

  1.        Create and deploy a very simple Tracking Profile with PortStartTime and PortEndTime messaging properties.

 

 

 

  1.       Map the properties to Receive Port which has its receive location with PassThrough pipeline.
  2.       Submit test data to the receive location.

 

The BAM data will not get generate on BizTalk 2013 R2. However it works with BizTalk 2010 and earlier versions. Also, if we deploy proper schema and use XML receive pipeline, it works well on BizTalk 2013 R2.

 

Debugging:

================================

 

From the Time Travel Trace of BizTalk 2010, we can find the BAMArtifactCache.LoadBAMConfig() function get called with the following callstack. The same call also exists in the trace of running XML receive pipeline on BizTalk 2013 R2.

 

Breakpoint 0 hit

Time Travel Position: 84D700000302.

eax=0e27ba1c ebx=122233a4 ecx=0e27ba1c edx=0e40056c esi=0e4004a0 edi=0e400478

eip=1b7336a4 esp=1deef508 ebp=1deef540 iopl=0         nv up ei ng nz na pe cy

cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000287

Microsoft.BizTalk.Messaging.BAMArtifactCache.LoadBAMConfig(System.String, Int32, System.String, System.String):

1b7336a4 b84892f101      mov     eax,1F19248h

0:021> kc

#

00 Microsoft.BizTalk.Messaging.BAMArtifactCache.LoadBAMConfig(System.String, Int32, System.String, System.String)

01 Microsoft_BizTalk_Pipeline!Microsoft.BizTalk.PipelineOM.Pipeline.IsMessageContentTracking(Microsoft.BizTalk.PipelineOM.IBAMMessagingInterceptorInt, System.Guid, System.String)

02 Microsoft_BizTalk_Pipeline!Microsoft.BizTalk.PipelineOM.Pipeline.DoBamTracking(Microsoft.BizTalk.Message.Interop.IBaseMessage, BamTrackingMode, Boolean, Boolean)

03 Microsoft_BizTalk_Pipeline!Microsoft.BizTalk.PipelineOM.ReceivePipeline.GetNext()

 

 

But the same function will not get called in BizTalk 2013 R2’s trace when using passthrough pipeline on receive location. By comparing the source code, we can see there have been a lot of changes between BTS 2010 and 2013 R2’s DoBamTracking() function. Basically their difference is:

 

  • ·         In BizTalk 2010’s code path, IsMessageContentTracking() (it’s the caller of LoadBAMConfig()) will be invoked directly in DoBamTracking().
  • ·         In BizTalk 2013 R2’s code path, DoBamTracking() will try to retrieve the schema by message type first before calling IsMessageContentTracking(). However, this will never succeed because obviously message type and schema information is not available in a passthrough pipeline since it doesn’t perform XML schema resolution.

 

 

By further checking the debug trace,  we can find the following GetDocType call triggered System.ArgumentNullException and was caught directly. This led to the IsMessageContentTracking function didn’t get called at all.

                try
                {
                    if (string.IsNullOrEmpty(obj2 as string))
                    {
                        obj2 = Utils.GetDocType(markableForwardOnlyEventingReadStream);
                    }
                    string text = obj2 as string;
                    if (text != null && this.PipelineContext.GetDocumentSpecByName(text) != null)
                    {
                        flag4 = this.IsMessageContentTracking(iBAMMessagingInterceptorInt, iBTMPipelineContext.BAMGuid, text);
                    }
                }
                catch
 (Exception)
                {
                }

Time Travel: From 80F8C0000125 to 80F8C0000125

Time Travel Success.

Time Travel Position: 80F8C0000125.

eax=1bb98084 ebx=1fa23414 ecx=1bb932c0 edx=0006ee4c esi=1bb932c0 edi=0868f840

eip=06e555d2 esp=0868f828 ebp=0868f850 iopl=0         nv up ei pl zr na pe nc

cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246

Microsoft_BizTalk_Streaming!Microsoft.BizTalk.Streaming.Utils.GetDocType(Microsoft.BizTalk.Streaming.MarkableForwardOnlyEventingReadStream, System.Text.Encoding)+0x172:

06e555d2 e84d45186e      call    clr!IL_Throw (74fd9b24)

DBGHELP: Microsoft_BizTalk_Pipeline - no symbols loaded

 

0:033> !dso

OS Thread Id: 0x62bc (33)

ESP/REG  Object   Name

eax      1bb98084 System.Runtime.Serialization.SafeSerializationManager

ebx      1fa23414 <unknown type>

ecx      1bb932c0 System.ArgumentNullException

esi      1bb932c0 System.ArgumentNullException

0868F844 1fa23414 <unknown type>

0868F85C 1bb8d694 Microsoft.BizTalk.PipelineOM.PipelineContext

0868F860 1bb931a4 Microsoft.BizTalk.Messaging.BAMMessagingInterceptor

0868F868 1bb93180 Microsoft.BizTalk.Message.Interop.MessageContext_ManagedViewOfNative

0868F86C 1bb8c468 System.__ComObject

0868F870 1bb8c468 System.__ComObject

0868F874 1bb8d544 Microsoft.BizTalk.DefaultPipelines.PassThruReceive

 

 

0:033> !mex.t

DbgID ThreadID Position     COM-Initialized

33    62bc     80F8C0000125 APTKIND_MULTITHREADED (MTA)

 

# Child-SP Return   Call Site                                                                                                                                                               Source

0 0868f828 06e54bae Microsoft_BizTalk_Streaming!Microsoft.BizTalk.Streaming.Utils.GetDocType(Microsoft.BizTalk.Streaming.MarkableForwardOnlyEventingReadStream, System.Text.Encoding)+0x172 open start of function

1 0868f858 06e5472b Microsoft_BizTalk_Pipeline!Microsoft.BizTalk.PipelineOM.Pipeline.DoBamTracking(Microsoft.BizTalk.Message.Interop.IBaseMessage, BamTrackingMode, Boolean, Boolean)+0x1e6 open start of function

2 0868f8cc 06e542f9 Microsoft_BizTalk_Pipeline!Microsoft.BizTalk.PipelineOM.ReceivePipeline.GetNext()+0x373                                                                                 open start of function

3 0868f938 74e82936 Microsoft_BizTalk_Pipeline!DomainNeutralILStubClass.IL_STUB_COMtoCLR(IntPtr)+0x19                                                                                       open start of function

 

 

Reflected code snippet of BizTalk 2013 R2

=======================================

 

internal IBaseMessage DoBamTracking(IBaseMessage msg, Pipeline.BamTrackingMode mode, bool handleNonXmlErrorMessages, bool supportOnlyContextTracking)
{
    Trace.Tracer.TraceMessage(4u, "[POM]DoBamTracking: Enter");
    IBaseMessage baseMessage = msg;
    IBaseMessageContext baseMessageContext = null;
    bool flag = false;
    bool flag2 = false;
    MarkableForwardOnlyEventingReadStream markableForwardOnlyEventingReadStream = null;
    IBAMMessagingInterceptorInt iBAMMessagingInterceptorInt = null;
    IBTMPipelineContext iBTMPipelineContext = this.pipelineContext;
    baseMessageContext = msg.Context;
    object obj = baseMessageContext.Read("BAMTrackingNeeded", Constants.SystemNamesapce);
    if (obj is bool)
    {
        flag = (bool)obj;
    }
    if (this.pipelineContext.InvokedFromMessaging && flag)
    {
        bool flag3 = false;
        obj = baseMessageContext.Read("InboundPropertiesTracked", Constants.XmlNormNamespace);
        if (obj is bool)
        {
            flag3 = (bool)obj;
        }
        if (!flag3)
        {
            if (iBTMPipelineContext.TrackingInterceptor.BAMMessagingInterceptor != null)
            {
                iBAMMessagingInterceptorInt = (IBAMMessagingInterceptorInt)iBTMPipelineContext.TrackingInterceptor.BAMMessagingInterceptor;
                object obj2 = baseMessageContext.Read("MessageType", "http://schemas.microsoft.com/BizTalk/2003/system-properties");
                if (!(obj2 is string))
                {
                    obj2 = null;
                }
                bool flag4 = false;
                try
                {
                    if (string.IsNullOrEmpty(obj2 as string))
                    {
                        obj2 = Utils.GetDocType(markableForwardOnlyEventingReadStream);
                    }
                    string text = obj2 as string;
                    if (text != null && this.PipelineContext.GetDocumentSpecByName(text) != null)
                    {
                        flag4 = this.IsMessageContentTracking(iBAMMessagingInterceptorInt, iBTMPipelineContext.BAMGuid, text);
                    }
                }
                catch (Exception)
                {
                }

 

 

Reflected code snippet of BizTalk 2010

=======================================

 

// Microsoft.BizTalk.PipelineOM.Pipeline
internal IBaseMessage DoBamTracking(IBaseMessage msg, Pipeline.BamTrackingMode mode, bool handleNonXmlErrorMessages, bool supportOnlyContextTracking)
{
    Trace.Tracer.TraceMessage(4u, "[POM]DoBamTracking: Enter");
    IBaseMessage baseMessage = msg;
    IBaseMessageContext baseMessageContext = null;
    bool flag = false;
    bool flag2 = false;
    MarkableForwardOnlyEventingReadStream markableForwardOnlyEventingReadStream = null;
    IBAMMessagingInterceptorInt iBAMMessagingInterceptorInt = null;
    IBTMPipelineContext iBTMPipelineContext = this.pipelineContext;
    baseMessageContext = msg.Context;
    object obj = baseMessageContext.Read("BAMTrackingNeeded", Constants.SystemNamesapce);
    if (obj is bool)
    {
        flag = (bool)obj;
    }
    if (this.pipelineContext.InvokedFromMessaging && flag)
    {
        bool flag3 = false;
        obj = baseMessageContext.Read("InboundPropertiesTracked", Constants.XmlNormNamespace);
        if (obj is bool)
        {
            flag3 = (bool)obj;
        }
        if (!flag3)
        {
            if (iBTMPipelineContext.TrackingInterceptor.BAMMessagingInterceptor != null)
            {
                iBAMMessagingInterceptorInt = (IBAMMessagingInterceptorInt)iBTMPipelineContext.TrackingInterceptor.BAMMessagingInterceptor;
                object obj2 = baseMessageContext.Read("MessageType", "http://schemas.microsoft.com/BizTalk/2003/system-properties");
                if (!(obj2 is string))
                {
                    obj2 = null;
                }
                bool flag4 = this.IsMessageContentTracking(iBAMMessagingInterceptorInt, iBTMPipelineContext.BAMGuid, obj2 as string);
                Stream originalDataStream = msg.BodyPart.GetOriginalDataStream();
                if (originalDataStream != null)
                {
                    markableForwardOnlyEventingReadStream = (originalDataStream as MarkableForwardOnlyEventingReadStream);
                    if (markableForwardOnlyEventingReadStream == null)
                    {
                        markableForwardOnlyEventingReadStream = new MarkableForwardOnlyEventingReadStream(originalDataStream);
                    }
                    this.pipelineContext.ResourceTracker.AddResource(markableForwardOnlyEventingReadStream);
                    markableForwardOnlyEventingReadStream.MarkPosition();
                    msg.BodyPart.Data = markableForwardOnlyEventingReadStream;
                }

 

 

 

Status:

 

================================

 

We are still investigating this issue and finding the appropriate solution to fix it.

 

Best regards,

WenJun Zhang


Comments (3)

  1. Dave says:

    Hi WenJun Zhang, any update on a resolution for this? I realise this is probably an obscure scenario, but in our case we really NEED this to work in the pass-thru scenario. Thanks! Dave

  2. Dave says:

    Hi again WenJun Zhang,

    I've also been able to reproduce this when using the XmlReceive pipeline with the "AllowUnrecognisedMessage" property set to "True". This makes sense with your observation from the reflected code that it's related to whenever the message type hasn't been identified.

    Cheers,

    Dave

  3. Hi Dave,

    We've had a hotfix to correct the behavior. Please contact MS support to obtain it.

    Best regards,

    WenJun

Skip to main content