Adding Transactional Support to a Custom WCF LOB Adapter


 

Building a custom WCF LOB Adapter is rather simple, after you’ve stepped through the process once or twice. As a matter of fact, there are many blogs, and references that step you through it, one such as this: http://geekswithblogs.net/michaelstephenson/archive/2009/02/10/129302.aspx, and references here: http://blogs.msdn.com/sonuarora/archive/tags/_2600_quot_3B00_WCF+LOB+Adapter+SDK_2600_quot_3B00_/default.aspx. I also suggest a good thorough reading of the BizTalk WCF Adapters and the WCF LOB Adapter pack here: http://www.microsoft.com/downloads/details.aspx?FamilyID=45537d57-cbbf-423e-b083-f71e07e4ae47&displaylang=en

 

The WCF LOB Adapter SDK is the framework that you can use to build WCF LOB Adapters for Sending and Receiving messages to LOB Systems. One thing I noticed that was missing in most of the documentation on MSDN, blogs, and forums, was an answer to some common questions: exactly how do you add Transactional support to a WCF Custom LOB Adapter? And when adding Transactional support to the adapter how does it work with BizTalk? Isn’t all this just built in? Are there any special steps you need to take or be aware of? – Hence the purpose of this blog.

Before I get into the nuts and bolts of this, I’d suggest you read a little on Transactions in WCF: http://msdn.microsoft.com/en-us/library/ms733904.aspx, as well as things to consider when using WCF LOB Adapter with BizTalk: http://blogs.msdn.com/adapters/archive/2009/03/12/things-to-consider-when-writing-wcf-lob-adapters-for-consumption-through-biztalk.aspx

Now after a refresh of Transactions with WCF, we understand that when we speak of transactions WCF Supports two transaction protocols: WS-AtomicTransactions, and Microsoft Based (DTC) OleDb transactions. The main difference between these two transaction types is the purpose and implementation of each. The Purpose of the WS-AtomicTransactions is to support interoperability between Non Microsoft databases such as Oracle, DB2, MySql and etc. However, for this to work, the implementation of such protocol requires that non Microsoft database also support and understand the WS-AT protocol, otherwise it is a mute point, and in some circles a “pipe dream” that will never come true. Unfortunately, this blog is not about which non Microsoft databases support WS-AT and the specifics of such protocol, nor is it about using the second natively supported OleTransaction protocol. To continue, the OleTransaction protocol is used specifically for Microsoft based distributed databases that utilize the Microsoft Distributed Transaction Coordinator (MS DTC), and this includes BizTalk SQL databases. The implementation of this protocol uses the native OleDb api’s to communicate with the MS DTC and databases enlisted within the transaction. Now that you remember there are these two major types of transactional support for WCF, we have to determine which of these two transaction types we would like to support in the Custom Adapter. Supporting one or the other, and possibly both dictates exactly which components need to be implemented, and what properties are available at runtime within the adapter.

There are many settings and options between both transactional protocols in WCF, however the main configuration for enabling transactions within WCF is through its transaction flow settings. In WCF, these settings are expressed using a number of different options. They are controlled through a combination of attributes, bindings, and configuration settings. For example, the Transaction Flow settings are compiled using the intersection of the following three values:

  1. Transaciton Flow Attribute: [TransactionFlow(TransactionFlowOption.Mandatory| TransactionFlowOption.Allowed| TransactionFlowOption.NotAllowed)]
  2. The TransactionFlow property on a standard binding: true|false
  3. The TransactionFlowProtocol property in the specific binding: WS-AtomicTransaction Protocol or OleTransactions Protocol

These three settings dictate to WCF if a transaction flow is required, supported or not allowed for a particular operation, if the transaction context and information will actually be flowed across the wire, and which transaction protocol format to use for flowing the transaction information across the wire, respectively. There is one major expected caveat here, in that when the WCF Operation transaction flow attribute uses Mandatory or Allowed, the operation can not be “One-way” or marked with the “One-Way” attribute: [IsOneWay=true]. This should make perfect sense, because we are requiring or supporting transactions, thus a Positive or Negative Synchronous acknowledgement must be returned to the original caller informing them that the process completed. In the “One-Way” scenario, there is no response, it is for the most part Asynchronous, thus there is no way to inform the original caller that the process completed. I hope this is clear, because this launches us into the next section… How to implement all this with the WCF LOB Adapter, and how BizTalk Adpaters work with this.

For those following up until now, you know we have the 3 values which need to be configured to support transactions. However, for those of you who have already built custom LOB Adapters, you may have noticed that the WCF LOB Adapter framework SDK does not provide a way to simply add a Transaction Flow attribute, nor does the adapter generated wizard provide a property, setting, or class that can set any of these three values. Not to mention, the framework produces different classes depending on if we want to support Inbound (“Receive”) adapters, Outbound (“Send”) adapters, Inbound-Outbound (“Solicit-Request”) adapters, and Outbound-Inbound (“Request-Response”) adapters, as well as asynchronous vs synchronous handlers

Let’s address these three settings one at a time to get a full overstanding of how this works…

  1. Using the Transaction Flow attribute with WCF Custom LOB Adapters.
    1. To understand this attribute I will show it in an example:

      Utilizing this attribute is usually done inside a Class or Interface, marked as the Service contract as below:

       

      [ServiceContract(Namespace=”http://www.microsoft.com/biztalk/2006/r2/wcf-adapter”)]

      public interface ITwoWayAsyncVoidTxn

      {

      // Methods


      [TransactionFlow(TransactionFlowOption.Mandatory), OperationContract(AsyncPattern=true, IsOneWay=false, Action="*", ReplyAction="*")]

      IAsyncResult BeginTwoWayMethod(Message message, AsyncCallback callback, object state);


      [TransactionFlow(TransactionFlowOption.Mandatory), OperationContract(IsOneWay=false, Action="BizTalkSubmit")]

      void BizTalkSubmit(Message

      message);

      void EndTwoWayMethod(IAsyncResult result);

      }

       

       

      In the above example, we have an interface named: ITwoWayAsyncVoidTxn, which is a service contract for the BizTalkServiceInstance that we will discuss later. This service contract outlines that the BeginTwoWayMethod, and BizTalkSubmit operations require a mandatory Transaction context and information be flowed into the Service. Specifically what this means is that the when a client is trying to discover or communicate with one of these two operations, the WCF Service description will contain a policy assertion that mandates communication to this operation requires a transaction soap header be sent and it must be understood.

       

      Adding this type of transaction flow attribute is done when designing the Service Contract. Once this is accomplished, the Service which implements this contract can be instantiated and run within the confines of the Service Host application. Normally the host will be an IIS Web Site, or custom built Host such as a windows background service, or command line application. Hosting this adapter inside a BizTalk Runtime is completely different which I’ll discuss later.

       

      Now you may be wondering, how do we specify a service contract inside the WCF LOB Custom Adapter? There is no place to create a Service Contract, specifying the operations which will support transactions at least not like the example above. If you recall, the LOB Adapter framework, provides a set of classes that you implement to handle inbound and outbound operations. Basically these classes pass in a collection of action values you can use to determine which operation to invoke, however the programming model is unlike the normal WCF programming model. The WCF LOB Adapter programming model is focused on three to four major components: The Connection to the System, The Binding settings, The Metadata Resolution, and the actual implementation to send and retrieve the data.

       

      When our WCF LOB Adapter is hosted inside the out of the box (OOB) IIS Hosting options, the best we can do is use the MetadataResolverHandler class that the framework provides, and a custom WSDL exporter class we would have to create, to yield the correct policy assertions. However, if you create or extend the OOB IIS Hosting options, such as creating your own ServiceHost class, and even create your own host altogether, adding the Transaction flow attribute is rather simple. Below is an example on how to add the transactionflow attribute to an operation inside a custom ServiceHost class:

       

      public class MyCustomServiceHost : ServiceHostBase

      {

       

      protected override System.ServiceModel.Description.ServiceDescription CreateDescription(out IDictionary<string, System.ServiceModel.Description.ContractDescription> implementedContracts)

      {

      implementedContracts = new Dictionary<string, ContractDescription>();

      ContractDescription contractDesc = new ContractDescription(“myCustomDescription”);

      contractDesc.Operations.Add(new OperationDescription(“BizTalkSubmit”, contractDesc));

      contractDesc.Operations[0].Behaviors.Add(new TransactionFlowAttribute(TransactionFlowOption.Mandatory));

       

      KeyedByTypeCollection<IServiceBehavior> behaviors = new KeyedByTypeCollection<IServiceBehavior>();

      behaviors.Add(new ServiceDebugBehavior() { IncludeExceptionDetailInFaults = true });

       

      ServiceEndpoint ep = new ServiceEndpoint(contractDesc );

      List<ServiceEndpoint> endpoints = new List<ServiceEndpoint>();

       

      endpoints.Add(ep);

      string serviceName = “MyCustomService”;

      string serviceNamespace = “http://tempuri.org&#8221;;

      Type serviceType = typeof(AddingTransactionFlow.Service1);

      ServiceDescription desc = new ServiceDescription(endpoints) { Behaviors = behaviors, Endpoints = endpoints, Name=serviceName, ServiceType=serviceType, Namespace=serviceNamespace };

       

      }

      }

       

       

      Now, I must stress, that adding the transaction flow attribute is only for the contracts to assert the notion that transaction are required, when using your WCF LOB Adapter inside IIS or a custom host. In reality, if you don’t need to assert that the transaction context is flowed from client to adapter then for the most part, the above is a mute point.

       

      So What about BizTalk Server Adapters, and its runtime environment?

       

      Good question. When our WCF LOB Adapter is hosted inside the BizTalk Runtime, it will run as apart of the WCF Custom adapter. What’s interesting to note here is that the WCF Custom Adapter (both send and receive) are built using a generic messaging pattern. This means is that there is no need to create a special service contract in code, because the WCF Custom Adapter utilizes five different generic service contracts to handle all possible scenarios. (Read here: http://www.biztalkgurus.com/newsletter/TheBizTalker-volume-12.html for more information.)

       

      On the receiving side of things, BizTalk creates a custom ServiceHost Class named BtsServiceHost that instantiates the BiztalkServiceInstance. The Service Host base class implements a method called CreateImplementedContract which basically checks to see if the BizTalk Receive Port/Receive Location configured pair is a 2 –way port or not, or if the configuration does not contains any Reply or Duplex binding elements, or if any transactions settings are configured in the adapter, or if an transaction flow binding element is in the binding configuration. Based on these options, the method returns the correct associated Interface with the correct behaviors and settings. For example, if the WCF Custom adapter is configured to use a WCF binding that contains a transaction flow binding element, and it also contains a binding element which implements one of the WCF IReply, IDuplex, or IReplySession Channel interfaces then the ITwoWayAsyncVoidTxn interface is selected. In a nutshell, if the receive location is configured as a transactional receive, then the ITwoWayAsyncVoidTxn interface is returned, otherwise one of the other four remaining interaces are returned. Notice that the ITwoWayAsyncVoidTxn, interface is decorated with the TransactionFlow attribute as outlined above.

       

      So What does this mean for my custom LOB Adapter when hosted in BizTalk?

       

      This is another good question. What this means is that when building a custom LOB Adapter, if you want the BizTalk WCF Custom Adapter to use the service contract with the TransactionFlow Attribute, just add a transaction flow binding element to the binding collection.

       

      // Inside the xxxAdapterBinding class …..

      // Override the CreateBindingElements

      #region Public Methods

       

      /// <summary>

      /// Creates a clone of the existing BindingElement and returns it

      /// </summary>

      public override BindingElementCollection CreateBindingElements()

      {

      if (null == bindingElements)

      {

      bindingElements = new BindingElementCollection();

      //Only create once

      if (this.transactional)

      bindingElements.Add(new System.ServiceModel.Channels.TransactionFlowBindingElement());

      bindingElements.Add(this.BindingElement);

      }

      return bindingElements.Clone();

      }

       

      #endregion Public Methods

       

       

      In the example above, I have overridden the CreateBindingElements() method of the xxxAdapterBinding class that gets created as a part of the WCF LOB Adapter Framework SDK. In this method, I check a public property transactional which is set on the adapter binding, to determine if I need to add the transaction flow binding element to the collection. After doing this, when this adapter is configured for use with the WCF Custom Adapter inside BizTalk, it will be considered a “transacted binding” in effect telling the BtsServiceHost base class to create a Service Instance of type ITwoWayAsyncVoidTxc. – exactly what we want!!! Now to the next section, TransactionFlow Property.

       

  2. Using the TransactionFlow property in a custom WCF LOB Adapter.

     

    The TransactionFlow property is a Boolean property that must be set on one of the standard OOB bindings, such as the NetTcpBinding, or the WsHttpBinding. If you are not encompassing any of these bindings inside your WCF LOB Adapter, then adding a transactionFlow binding element as outlined in the previous section is good enough.

     

  3. Choosing a TransactionFlowProtocol in a custom WCF LOB Adapter.

     

    The TransactionFlow Protocol is an enumeration that outlines the format of the transaction information you are flowing across the wire. It comes in three flavors:

    1. OleTransactions
    2. WSAtomicTransaction11
    3. WSAtomicTransactionOctober2004

    These values are set on the TransactionFlow binding element added to the binding elements from previous sections. The value you select mostly depends on the underlying database you are using for Atomic transaction support. If it’s a Microsoft based database or MS DTC managed resource (such as MSMQ, or Exchange), then you’re going to use OleTransactions. Other than that you’ll need to consult the third party database/resource to determine which WS-AT protocol they support.

     

After you have configured the three main settings for WCF to support transactions should be good to go… You have done everything you need to add support to a custom WCF LOB Adapter, however, there are a couple of small caveats that you should be aware of especially when working with the BizTalk WCF Receive Adapter.

BizTalk WCF Receive adapters in general connect to some endpoint, retrieve the message, and then submit the message into the BizTalk Message Box database. Throughout this whole process we never mention how this works from an atomic transactional perspective. When you have a WCF Custom LOB Adapter that needs to support atomic transactions, from the endpoint into the BizTalk SQL Messagebox database, you need to be aware that the atomic transaction will only work if:

  1. All the above are followed.
  2. You implement the TryReceive() method of the Asynchronous or Synchronous Inbound Handler.
  3. You configure the AdapterSettings to support transacted inbound channels, and you list the inbound channels the adapter will support.

Why do we need to implement the TryReceive() synchronous method in the Asynchronous handler?

First off, in a true atomic transaction which follows the ACID characteristics, we cannot have an inconsistent state outside the context of the current transaction. In BizTalk WCF Custom Adapters, this is enforced by invoking the synchronous, thread blocking form of the xxxReceive() method, aka TryReceive(). It doesn’t matter if you have implemented the Asynchronous handlers, nor the Synchronous handlers. Behind the scenes the code just calls the “syncHandler.TryReceive()” method. It just so happens that the “syncHandler” object is set to the AsyncHandler class if you have implemented the AsynchronousHandlers. Below is an example of the implementation:

    

Try

{

IAsyncInboundHandler listenerAsyncHandler = this.channelListener.ListenerAsyncHandler;

if (listenerAsyncHandler != null)

{

IInboundReply reply;

flag = listenerAsyncHandler.TryReceive(helper.RemainingTimeout, out message, out reply);

}

Else

{

return true;

}

}

catch (Exception exception)

{

 

 

How do I configure AdapterSettings?

To configure the adapter settings class, you access the AdapterSettings instance from the xxxAdapter class created from the WCF LOB Adapter SDK framework. The AdapterSettings class instance can be found as the Settings property available on the xxxAdapter class. This class contains settings about the Connection Pool, Messaging settings, Metadata Settings, and Cache Settings. Specifically, the WCF LOB Adapter framework uses the Adapter class as the base class, which derives from the TransportBindingElement, and implements the ITransactedBindingElement. This interface helps determine if a custom Adapter supports atomic transaction receiving through the TransactedReceiveEnabled property. By default, this property in the base Adapter class simply returns:

 

return this.Settings.Messaging.SupportsTransactedInbound;

 

 

In order for your adapter to work as expected this last piece of information needs to fall in place. Here’s an example in a custom xxxAdapter class constructor:

 

/// <summary>

/// Initializes a new instance of the CustomAdapter class with a binding

/// </summary>

public CustomAdapter(CustomAdapter binding)

: base(binding)

{

this.EnableConnectionPooling = binding.EnableConnectionPooling;

this.MaxConnectionsPerSystem = binding.MaxConnectionsPerSystem;

this.MaxAvailableConnections = binding.MaxAvailableConnections;

this.HandlersShareSameConnection = binding.HandlersShareSameConnection;

this.transactional = binding.transactional;

this.pollingInterval = binding.pollingInterval;

if (binding.transactional)

{

Settings.Messaging.SupportsTransactedInbound = true;

Settings.Messaging.SupportedInboundChannels = SupportedInboundChannels.IInputChannel;

}

 

if (binding.enableConnectionPooling )

{

Settings.ConnectionPool.EnablePooling = true;

Settings.ConnectionPool.HandlersShareSameConnection = binding.handlersShareSameConnection;

}


 

}

 

 

I hope this document helps in explaining how to support transactions in WCF LOB Custom Adapters…

Happy Coding!

4 thoughts on “Adding Transactional Support to a Custom WCF LOB Adapter

  1. Excellent article! Do you have any guidance/experience to share on how writing an Adapter with the WCF LOB Adapter SDK that supports Ordered Delivery? Thanks!

    Like

  2. Hi Dwight, I saw your post on the
    MSDN forums where you mentioned that there is a hack to allow the WCF LOB Adapter to access the normal promoted properties.

    http://social.msdn.microsoft.com/Forums/en/biztalkr2adapters/thread/75ce6cb1-c37b-4a35-a61a-4c2b06e6ae13

    I am writing a test adapter for development purposes and am interested to know what the hack is as I need those promoted properties. Could you let me know how to do this?As it is NON production code it wont cause any support issues. Please email me on the address provided here if you can help

    Thanks
    benjy

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s