How to build BizTalk Custom Adapters

Luigi Pampaloni

BizTalk Solutions Architect

LPYSoft Ltd

Content of the presentation

First part

BizTalk Interfaces to be implemented

Second part

SimpleHTTPAdapter documentation

2

BizTalk adapters

Aspect

 

 

Options

Communication

Receive

Direction

 

One-way Submit

 

Request – Response

 

 

Request – Response time-outs

 

Transmit

 

 

One-way Send

 

 

Solicit – Response

Adapter "code"

In-process – the adapter is created within BizTalk host process. All transmitting

hosted

 

adapters are in-process

 

Isolated – the receive adapter is created in an isolated host (external process i.e.

 

 

w3wp.exe) which is not part of the BizTalk runtime. A classic example is an http

 

 

receive adapter. The actual message is received while being in the IIS worker

 

 

process boundary

Port Binding

Static – the target location for send/receive is preconfigured

 

Dynamic – the target location can be determined in runtime

Adapter

Asynchronous adapter – the adapter is able to send messages without holding

Capabilities

 

the BizTalk send thread. Messages are sent on the adapter thread (relevant for

 

 

transmitting adapters)

 

Transactional adapter – support for transactional send/receive of messages

 

Batch support – the adapter supports receiving and transmitting batch of

 

 

messages

 

 

 

Design-time

Property browser – defines a list of properties and uses the std property dialog

 

Metadata wizard – used to generate or import items (i.e. schemas) from an app

 

 

Static – The wizard provides a standard default hierarchical tree structure

 

 

Dynamic – The adapter provides a custom UI

3

Adapter components

Design-time component

Run-time component

Receive adapter

Send adapter

Adapter registration

4

Design-time components

Property browser. Adapter properties for a send or receive port, or a send or receive handler, are configured through their Properties menu by using the BizTalk Server Administration console. During configuration of these artifacts the adapter (transport) is selected and its properties are configured by using a property browser. Applicable properties are displayed through a schema with a set name. The adapter implements the IAdapterConfig interface to locate and load the appropriate schema to expose specific properties in the property browser. The IAdapterConfigValidation interface is used to validate those entries and make any final modifications to the values before saving the configuration data.

Add Adapter Metadata Wizard. In the case of application and database adapters, you may need to import supporting schemas that describe message types and port types that the adapter needs in the BizTalk project in Visual Studio. Or sometimes there is the need to consume services provided by the adapter. The Add Adapter Metadata Wizard enables you to view services that an adapter supports and import the related message types and port types into your project. This process is known as "metadata harvesting." As an adapter developer you create an XML file describing those services and expose it to the wizard at design time through either the IStaticAdapterConfig or IDynamicAdapterConfig interface, with the following results:

Static adapter. The wizard provides a standard default hierarchical tree structure with which to display the adapter's services. A static adapter is defined as an adapter that uses the standard tree user interface (UI) provided by the wizard. Use the IStaticAdapterConfig.GetServiceOrganization and GetServiceDescription methods to allow selected services to be added to the BizTalk project. This is the simplest configuration option for an adapter developer, but the tradeoff is rigidity of the display format

Dynamic adapter. If the basic service selection UI provided by the wizard is not flexible enough meet your UI needs you can create a custom UI that is dynamically displayed by the wizard. Use the IDynamicAdapterConfig.DisplayUI method to display the custom UI to allow selection of services to be added to a BizTalk project

5

IAdapterConfig

IAdapterConfig defines two methods, GetConfigSchema and GetSchema. Based on the value of the ConfigType parameter, GetConfigSchema must return the appropriate XSD which defines the configuration properties. The schema will be validated against the BizTalkAdapterFramework.xsd

Under Microsoft.BizTalk.Adapter.Framework namespace

Two methods must be implemented:

string GetConfigSchema (ConfigType configType)

Get a schema representing the configuration properties of the adapter. Potentially, a receive handler, a send handler, a receive location, and a send port could all have different schemas that define different properties, in which case four different schemas would be needed

Parameters

configType

»The target usage of the configuration specification

(One of ReceiveHandler, ReceiveLocation, TransmitHandler, TransmitLocation)

Return Value

A string containing the schema that represents the configuration properties (XSD) or null if the configType type is not supported

Result GetSchema (string uri, string namespaceName, out string fileLocation) Get the location of schema files that need to be imported into the BizTalk project

Parameters

uri

»A string containing the URI uniquely identifying the schema.

namespaceName

»A string containing the namespace of the schema.

fileLocation

»A string containing the XSD schema content.

Return Value

One of the Result values: Back, Cancel, Continue, Exit, Fail

6

IAdapterConfig sequence diagram

GetConfigSchema must return the appropriate XSD which defines the configuration properties. The schema will be validated against the BizTalkAdapterFramework.xsd

GetSchema is called if there are any import nodes in the WSDL files returned by the adapter during setup using the Adapter Wizard as a way to be able to import necessary schemas into the BizTalk project but don't get confused by the name of the return parameter as defined by the interface (fileLocation), the return should be the actual string representation of the schema and will be validated against the BizTalkAdapterFramework schema

BizTalk Explorer

 

IAdapterConfig

 

 

 

GetConfigSchema()

Property schema (XSD)

Note: The GetSchema is called just when a WSDL is returned by the GetConfigSchema with an import of an external schema (probably is not called when implement just the IAdapterConfig interface)

7

IAdapterConfig configuration

public interface IAdapterConfig

{

string GetConfigSchema( ConfigType cfgType);

}

Adapter Design-time

GetConfigSchema

public enum ConfigType

{

ReceiveLocation = 0, TransmitLocation = 1, ReceiveHandler = 2, TransmitHandler = 3

}

public enum Result

{

Continue = 0,

Cancel = 1,

Back = 2,

Fail = 3,

Exit = 4

}

XSD

8

IAdapterConfig sample implementation

public string GetConfigSchema(ConfigType type)

{

switch (type)

{

case ConfigType.ReceiveHandler:

return GetResource("ReceiveHandler.xsd");

case ConfigType.ReceiveLocation:

return GetResource("ReceiveLocation.xsd");

case ConfigType.TransmitHandler:

return GetResource("TransmitHandler.xsd");

case ConfigType.TransmitLocation:

return GetResource("TransmitLocation.xsd");

default: return null;

}

}

public Result GetSchema(string xsdLocation, string xsdNamespace, out string xsdSchema)

{

xsdSchema = null; return Result.Continue;

}

9

IAdapterConfig sample schema

Below a schema which defines a PropertyName as a property of type string

<?xml version="1.0" encoding="utf-16"?>

<xs:schema xmlns:baf="BiztalkAdapterFramework.xsd" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" targetNamespace="http://tempuri.org/XMLSchema.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:import namespace="BiztalkAdapterFramework.xsd" /> <xs:element name="Config">

<xs:complexType> <xs:sequence>

<xs:element name=“PropertyName" type="xs:string"> <xs:annotation>

<xs:appinfo>

<baf:designer xmlns:baf="BiztalkAdapterFramework.xsd">

<baf:displayname _locID="PropertyNameName">Edit this field in the resource file</baf:displayname>

<baf:description _locID="PropertyName

this field in the resource file</baf:description>

<baf:category _locID="

">Adapter Properties</baf:category>

</baf:designer>

 

</xs:appinfo>

 

</xs:annotation>

 

</xs:element>

 

</xs:sequence>

 

</xs:complexType>

 

</xs:element>

 

</xs:schema>

 

10

IAdapterConfigValidation

IAdapterConfigValidation defines a single method, ValidateConfiguration. This method will be called when saving the configuration for any one of the four configuration types

Under Microsoft.BizTalk.Adapter.Framework namespace

A method must be implemented:

string ValidateConfiguration ( ConfigType configType, string configuration ) Validates the adapter configuration information

Parameters

configType

»One of the ConfigType values.

(One of ReceiveHandler, ReceiveLocation, TransmitHandler, TransmitLocation)

configuration

»A string containing the xml instance that the adapter can load into an XmlDocument instance.

Return Value

A string containing the xml instance configuration information, corrected if necessary

Throw an exception to notify wrong parameters specified on the property page

11

IAdapterConfigValidation sample impl.

public string ValidateConfiguration(ConfigType configType, string xmlInstance)

{

string validXml = String.Empty;

switch (configType)

{

case ConfigType.ReceiveHandler:

validXml = ValidateReceiveHandler(xmlInstance); break;

case ConfigType.ReceiveLocation:

validXml = ValidateReceiveLocation(xmlInstance); break;

case ConfigType.TransmitHandler:

validXml = ValidateTransmitHandler(xmlInstance); break;

case ConfigType.TransmitLocation:

validXml = ValidateTransmitLocation(xmlInstance); break;

}

return validXml;

}

private string ValidateTransmitLocation(string xmlInstance)

{

if(something wrong with the instance)

throw new ApplicationException(“Something wrong”); // Prompted by the property page on the OK button click

}

12

NOTE: Address (URI) is mandatory

The Address (URI) property is mandatory and read only on BTS

To set the Address (URI) property add a property called URI (browseable=false)

<xs:element name="uri" type="xs:string"> <xs:annotation>

<xs:appinfo>

<baf:designer xmlns:baf="BiztalkAdapterFramework.xsd"> <baf:browsable show="false" />

</baf:designer>

</xs:appinfo>

</xs:annotation>

</xs:element>

Implement the IAdapterConfigValidation to return a valid calculated address URI

transportType + “://” + someOtherProperty

13

IAdapterInfo

IAdapterInfo defines a single method, GetHelpString which should return a link to the help file associated with the configuration. This method will be called when the help button is clicked while viewing the custom adapter configuration property sheet for any one of the four configuration types

14

IStaticAdapterConfig

The UI for the IStaticAdapterConfig interface will be generated based on the xml returned by a call to the GetServiceDescription method (the return will be validated against the BizTalkAdapterFramework schema and will be used to generate a tree-view of the "services" the adapter provides

Under Microsoft.BizTalk.Adapter.Framework namespace

Two methods must be implemented

string GetServiceOrganization ( IPropertyBag endpointConfiguration, string nodeIdentifier )

Get an XML representing the way the adapter organizes its services. This tree is used to generate the service organization tree that is displayed to the user in the Add Adapter Wizard

Parameters

endpointConfiguration

nodeIdentifier

»The name of the node. The Adapter Framework passes null to request the root of the service organization hierarchy and the name of a node to request the hierarchy under an expandable tree node.

Return Value

A string containing XML that represents the way the adapter organizes its services

string[] GetServiceDescription ( string[] wsdlReferences )

Gets an array of Web Service Description Languages (WSDL), based on the unique WSDL references specified in the returned XML of the GetServiceOrganization method

Parameters

wsdlReferences

»An array of string with the WSDL references (as obtained from the Service Organization XML). Each input string is derived from the XML provided from the GetServiceOrganization call.

Return Value

An array of string of WSDLs. Each output string should contain the WSDL content corresponding to the WSDL reference in the input parameter

15

IStaticAdapterConfig sequence diagram

The GetServiceOrganization is called to get the hierarchical structure of the services

The service description (as WSDL format) is requested for each service selected on the UI

For each import defined on the WSDL the GetSchema is called to retrieve the external schema

BizTalk Explorer

 

IStaticAdapterConfig

 

IAdapterConfig

 

 

 

 

 

GetServiceOrganization()

Service Organization XML

GetServiceDescription()

Service Description WSDL

GetSchema()

External Schema

16

IStaticAdapterConfig configuration

public interface IStaticAdapterConfig : IAdapterConfig

{

string GetServiceOrganization();

string [] GetServiceDescription(string [] wsdls);

Result GetSchema(string uri, string namespaceName, ref string fileLocation);

}

 

 

 

 

 

 

public enum Result

 

 

 

{

 

 

 

 

Continue = 0,

 

 

 

Cancel = 1,

 

Adapter Design-time

 

Back

= 2,

 

 

Fail

= 3,

 

 

 

 

 

 

Exit

= 4

GetServiceOrganization

 

XML

}

 

 

 

 

 

 

 

 

GetServiceDescription

GetSchema

WSDLs

XSDs

17

IStaticAdapterConfig sample implementation

public string GetServiceOrganization(IPropertyBag endPointConfiguration, string NodeIdentifier)

{

//Simple implementation, assuming the TreeView xml instance is on the filesystem string result = "";

OpenFileDialog fileDialog = new OpenFileDialog();

fileDialog.Filter = "Service description files (*.xml)|*.xml|All files (*.*)|*.*"; if (fileDialog.ShowDialog() == DialogResult.OK)

{

using (TextReader tr = new StreamReader(fileDialog.FileName))

{

result = tr.ReadToEnd(); tr.Close();

}

}

return result;

}

public string[] GetServiceDescription(string[] wsdls)

{

//Simple implementation, assuming the wsdl is on the filesystem string[] result = new string[1];

result[0] = "";

OpenFileDialog fileDialog = new OpenFileDialog();

fileDialog.Filter = "Service description files (*.wsdl)|*.wsdl|All files (*.*)|*.*"; if (fileDialog.ShowDialog() == DialogResult.OK)

{

using (TextReader tr = new StreamReader(fileDialog.FileName))

{

result[0] = tr.ReadToEnd(); tr.Close();

}

}

return result;

}

18

IStaticAdapterConfig sample XML & UI

• Service Organization sample XML

<?xml version="1.0" encoding="utf-8" ?> <CategoryTree>

<DisplayName>Services Organization</DisplayName>

<DisplayDescription>An organization of application services</DisplayDescription> <CategoryTreeNode>

<DisplayName>Health Care</DisplayName> <Description>Services under Health Care</Description> <CategoryTreeNode>

<DisplayName>Administrative</DisplayName>

<Description>Administrative Health Care Svc</Description> <ServiceTreeNode>

<DisplayName>Eligibility</DisplayName> <Description>Eligibility Verification Tx</Description> <WSDLReference>ANSI X 12 270</WSDLReference>

</ServiceTreeNode>

</CategoryTreeNode>

</CategoryTreeNode>

<CategoryTreeNode> <DisplayName>Manufacturing</DisplayName> <Description>Manufacturing Services</Description> <CategoryTreeNode>

<DisplayName>Inventory</DisplayName> <Description>Inventory Services</Description> <ServiceTreeNode>

<DisplayName>Requisition</DisplayName> <Description>Requisition</Description> <WSDLReference>RequisitionService</WSDLReference>

</ServiceTreeNode>

</CategoryTreeNode>

</CategoryTreeNode>

</CategoryTree>

19

IDynamicAdapterConfig

The UI for the IDynamicAdapterConfig interface is defined by the developer and should be loaded in the DisplayUI method which will be called by the wizard

Result DisplayUI ( IPropertyBag endpointConfiguration, IWin32Window owner, out string[] serviceDescriptionFiles )

Displays the user interface for the custom adapter, enabling the user to import the services descriptions that are returned to BizTalk and then added to the BizTalk project

Parameters

endpointConfiguration

owner

»An IWin32Window containing the handle to the parent window.

serviceDescriptionFiles

»An array of string with the Web Service Description Languages (WSDL) references (as obtained from the Service Organization XML). Each string should be a valid WSDL file (with root element <definitions>). The Adapter Framework reads the strings into instances of the ServiceDescription class.

Return Value

An array of string of WSDLs

20

IDynamicAdapterConfig sequence diagram

The DisplayUI open a custom form. An array of WSDLs is returned by the

UI

For each import defined on the WSDL the GetSchema is called to retrieve the external schema

BizTalk Explorer

 

IDynamicAdapterConfig

 

IAdapterConfig

 

 

 

 

 

DisplayUI()

Service Description WSDL

GetSchema()

External Schema

21

IDynamicAdapterConfig configuration

public interface IDynamicAdapterConfig : IAdapterConfig

{

Result DisplayUI( ref string [] WSDLFileList);

Result GetSchema(string uri, string namespaceName, ref string fileLocation);

}

 

public enum Result

 

{

Continue = 0,

Cancel = 1,

Back = 2,

Adapter Design-timeFail = 3,

Exit = 4

}

GetDisplayUI

Display

WSDLs

 

Custom UI

 

 

GetSchema

 

 

 

 

XSDs

22

IDynamicAdapterConfig sample implementation

• DisplayUI sample

23

Run-time components

Messages

Message Engine

Receive adapter

Transmit adapter

24

Messages

A message (IBaseMessage) has one or more message parts represented by the IBaseMessagePart interface. Each message part has a reference to its data through an IStream interface pointer. The context of a message is represented by its IBaseMessageContext interface. The following figure illustrates the BizTalk message object model

25

Message Engine

The messaging engine has three public interfaces used by adapters:

IBTTransportProxy Adapters always talk to the messaging engine via their own Transport Proxy. The Transport Proxy is used to create batches, get the message factory, and register isolated receivers with the engine

IBTTransportBatch The interface exposed by the messaging engine's batch. Work done against the engine is performed using a batch; batches are processed asynchronously.

IBTDTCCommitConfirm Adapters using DTC transactions on batches must notify the engine of the outcome of the transaction using this interface

26

Message Engine – receive message flow

1.The Adapter creates a new message, connecting the data stream to the message.

2.The Adapter requests a new batch from the messaging engine via its Transport Proxy.

3.The Adapter adds a message to the batch to be submitted.

4.The batch is committed, which causes it to be posted to the messaging engine's thread pool.

5.The messaging engine's thread pool starts processing the new batch.

6.The message is processed by the receive pipeline.

7.Zero or more messages will be produced by the receive pipeline. Pipelines can consume messages providing they do not return any errors; receive pipelines can produce more than one message, typically when the dissassembler component disassembles a single interchange into many messages. Usually, the receive pipeline will normalize the message submitted into XML.

8.The message(s) produced by the pipeline may be processed in the mapper if mapping is configured.

9.The message(s) will be published to the Message agent and MessageBox.

10.The Messaging Engine will call back the adapter to notify it of the outcome of that batch of work.

27

Adapter load and initialisation

When the BizTalk service starts, all receive adapters are instantiated, as long as they have one or more configured and active receive locations

By default a send adapter is not instantiated until the Messaging Engine removes from the queue the first message to be sent by using that send adapter

The following figure shows the logic for creating adapters:

28

Receive adapter interfaces

Below a list of mandatory/optional interfaces to be implemented by the receive adapter

29

Receive adapter initialisation

Immediately after a receive adapter is instantiated it is initialized by the Messaging Engine, the engine calls QueryInteraface for IBTTransportControl. It then calls IBTTransportControl.Initialize passing in the adapter's transport proxy, which the adapter persists in a member variable. Next the engine calls QueryInterface for IPersistPropertyBag. This is an optional interface; if the adapter implements it, the handler configuration is passed to the adapter in the Load method call. The final stage of initializing a receive adapter involves passing the endpoint configuration to the adapter. During this phase the engine calls IBTTransportConfig.AddReceiveEndpoint once for each active endpoint, passing in the URI for the endpoint, the adapter specific configuration for the endpoint, and the BizTalk configuration for that endpoint

30

In-process receive adapter initialisation

The Messaging Engine creates an instance of an adapter, initializes it, and sets the configuration of receive locations. The Messaging Engine passes a property bag to an adapter on the AddReceiveEndpoint method call. The property bag contains the configuration for the receive location and receive handler. The configuration is stored in the database in the form of an XML- styled property bag. The Messaging Engine reads the XML and rehydrates a property bag from the XML. After at least one endpoint (receive location) is added, the adapter can start submitting messages

31

Isolated receive adapter initialisation

After the adapter has successfully registered with the transport proxy, the Messaging Engine passes the configuration information and the other receive locations back to the adapter by calling the Load method of the IPersistPropertyBag interface and the AddReceiveEndpoint method of the IBTTransportConfig interface respectively

32

Receive adapter operations

Receive adapters can perform the following operations:

One-way submit: void SubmitMessage(IBaseMessage msg). After receiving a message from a receive port, the adapter submits it to BizTalk Server to be processed by a subscribing orchestration or send port

Suspend: void MoveToSuspendQ(IBaseMessage msg). When the adapter determines a parsing, transmission, serialization, or other applicable failure has occurred after submission, it moves the message to the Suspended queue

Submit request: void SubmitRequestMessage(IBaseMessage requestMsg, string correlationToken, bool firstResponseOnly, DateTime expirationTime, IBTTransmitter responseCallback). A receive adapter submits an incoming message to BizTalk Server in a request-response pair. After BizTalk Server successfully processes this request message, it sends the response to the adapter to transmit it to the specific endpoint

33

One-way batch receive

A receive adapter obtains the batch from the transport proxy by calling the GetBatch method of the IBTTransportProxy interface. In its call to GetBatch the adapter passes in a pointer to its IBTBatchCallback interface implementation.

An adapter adds the messages one at a time into the batch by calling the SubmitMessage method of the IBTTransportBatch interface. If this is a two-way operation such as solicit-response messaging, the SubmitResponseMessage method of this same interface is called to submit the response message.

When all the messages have been added to the batch, the adapter calls the Done method of the IBTTransportBatch interface to submit the batch to the transport proxy. Because receive adapters are asynchronous in nature, the adapter can immediately obtain a new batch and start submitting other messages after it calls Done.

After the batch has been processed, the Messaging Engine invokes the adapter's BatchComplete callback method using the transport proxy to make the actual call. An array of BTBatchOperationStatus objects containing the status of the submission is passed to the adapter. Each object corresponds to an operation type and contains the overall status of the operation as well as the status for each message for which the operation was performed. The following sequence describes the actions the adapter needs to perform to analyze the status of batch processing:

Check the overall batch status HRESULT value passed as a parameter to the BatchComplete method. If it is a failure, it means that at least one of the operations in the batch was unsuccessful. Therefore the submission of the entire batch as one entity failed. The adapter should then try to discover the offending message(s) and resubmit as a batch only the ones that did not initially cause a failure.

If the overall batch status succeeded, it means that all the messages that were given to the transport proxy were persisted to disk. However, it does not mean that the pipeline successfully processed all the messages. It is possible that messages that failed in the pipeline were suspended. For messages that fail in the pipeline, the overall batch status returned is successful because the data was written to disk.

Check the status for each operation type in the operationStatus parameter. If the status is S_OK, the submission for this operation succeeded and you do not need to check the status any further. If the status is set to BTS_S_EPM_MESSAGE_SUSPENDED some of the messages were suspended. BTS_S_EPM_SECURITY_CHECK_FAILED signifies that some messages failed authentication in an authentication-required receive port. If E_FAIL is returned, or any HRESULT with a value that is less than zero, the message submission for this operation failed.

Check the status of individual messages for the operation type. For the submit operation type, the status of each message is set to S_OK if the submission succeeded. BTS_S_EPM_MESSAGE_SUSPENDED is returned if the message was suspended. BTS_S_EPM_SECURITY_CHECK_FAILED is returned if the message failed authentication on a receive port that requires authentication. E_BTS_NO_SUBSCRIPTION comes back if there were no subscribers for the published message. If E_FAIL is returned, or any HRESULT with a value that is less than zero, the message submission failed.

Depending on your adapter, you may want to suspend messages that return E_FAIL or any failing HRESULT.

The BatchComplete method needs to return either S_OK or E_FAIL to indicate the result of execution. If the BatchComplete method returns E_FAIL or any negative HRESULT, the transport proxy logs an error.

34

One-way transactional batch receive

A transactional receive adapter creates and passes a pointer to a Microsoft Distributed Transaction Coordinator (MSDTC) transaction on the Done method of the IBTTransportBatch interface. This ensures that all batch operations are performed in the scope of that specific transaction object. When the batch submission completes, the adapter callback method commits or rolls back the transaction. Which action it takes depends upon the status returned from the transport proxy, and possibly upon other transaction-related work that the adapter does that is not visible to the transport proxy. The adapter determines whether the transaction failed or succeeded. The adapter reports the result of the transaction (commit or rollback) back to the transport proxy by using the DTCCommitConfirm method of the IBTDTCCommitConfirm interface. It passes in true for a successful transaction or false for a failure

35

Request-response receive adapter

The receive adapter receives incoming request messages. It obtains a batch from the transport proxy by calling the GetBatch method of the IBTTransportProxy interface. In this call the adapter passes in a callback pointer to its implementation of the IBTBatchCallBack.BatchComplete method.

The adapter adds request messages into the batch by calling the SubmitRequestMessage method of the IBTTransportBatch interface, once for each request message.

When all the messages have been added, the adapter calls the Done method of the IBTTransportBatch interface, which submits the batch to the Messaging Engine through the transport proxy.

After the batch has been processed, the Messaging Engine invokes the adapter's IBTBatchCallBack.BatchComplete callback method through the transport proxy. The status of the submission is passed to the adapter as an array of HRESULT values corresponding to each message in the batch. If the batch fails, either in the pipeline or in the orchestration, the SOAP fault message is returned to the adapter as a response.

The incoming request messages may have orchestration subscribers. After the orchestration completes and the request message has been processed, the Messaging Engine sends the response message through the transport proxy to the adapter by calling the adapter's TransmitMessage method from the IBTTransmitter interface.

The adapter sends a response message and deletes the original message from the MessageBox database.

36

IBaseComponent

Three read only properties to be provided by the adapter

String Name – Adapter name

String Description – Adapter description

String Version – Adapter version

37

IBTTransport

Three read only properties to be provided by the adapter

String TransportType

Guid ClassID

38

IBTBatchCallBack

BatchComplete

Called by BTS once the message is received by the EPM

39

IBTTransportConfig

AddReceiveEndPoint

Called by BTS for each port bound to the adapter and started when the BTS service instance starts

Or

When a port bound to the adapter is started

RemoveReceiveEndPoint

Called when a port is shut down

UpdateEndPointConfig

Called when the properties of the port are changed

40

IBTTransportControl

Initialize

Called by BTS when the BTS service starts

Terminate

Called by BTS when the BTS service is stopped

41

Transmit adapter interfaces

• Below the list of the mandatory/optional interfaces:

42

Transmit adapter initialisation

When the Messaging Engine initializes a send adapter, it first performs a QueryInterface for IPersistPropertyBag, which is an optional interface. If the adapter implements the interface, the handler configuration is passed to the adapter in the Load method call. The adapter uses this information to ensure it is configured correctly.

The Messaging Engine performs a QueryInterface for IBTTransportControl, which is a mandatory interface.

The engine calls IBTTransportControl.Initialize, passing in the transport proxy for the adapter.

The Messaging Engine performs a QueryInterface for IBTTransmitter.

If the Messaging Engine discovers this interface, the adapter is treated as a batch-unaware transmitter.

If the Messaging Engine does not discover this interface, the Messaging Engine performs a QueryInterface for IBTBatchTransmitter, discovery of which indicates that the adapter is a batch-aware transmitter.

If the Messaging Engine discovers neither of these interfaces, an error condition results, causing the initialization to fail. The initialization fails if any mandatory interfaces are not discovered.

43

Transmit adapter operations

Resubmit: void Resubmit(IBaseMessage msg, DateTime timeStamp). After a transmission failure occurs on a message, an adapter resubmits it when appropriate. This is called on a per-message basis. If a batch of messages was submitted unsuccessfully, the adapter must determine the messages causing the failure, and resubmit the ones that did not cause the batch to fail in separate calls to Resubmit. There is information at the end of this topic about how to preserve message context property values when you call Resubmit.

Move to Next Transport: void MoveToNextTransport(IBaseMessage msg). If a message fails during a send operation and its retry attempts have been exhausted, the adapter can send the message to the next configured transport for retransmission.

Suspend: void MoveToSuspendQ(IBaseMessage msg). The adapter moves a failed send message to the Suspended queue if no additional backup transport is configured. There is information at the end of this topic about how to preserve message context property values when you call Suspend.

Delete: void DeleteMessage(IBaseMessage msg). The adapter deletes a message after being notified by BizTalk Server of its successful transmission. Deleting a message tells BizTalk Server that the adapter is finished with the message. Generally the SubmitResponse operation is done in the same batch as its associated Delete operation.

Submit Response: void SubmitResponseMessage(IBaseMessage solicitMsgSent, IBaseMessage responseMsgToSubmit). The adapter submits a response to the batch to be sent back to BizTalk Server. This operation includes the original message in the call along with the response so that BizTalk Server can correlate them.

Cancel Response: void CancelResponseMessages(string correlationToken). If the sending of a response message needs to be canceled before the batch is submitted, the CancelResponseMessages method is used, passing in the correlation token for the associated response message to be deleted.

44

Transmit adapter synchronous send

In a synchronous send, the adapter sends the message while blocking TransmitMessage, and after successful transmission returns True

45

Transmit adapter asynchronous send

The Messaging Engine uses the transport proxy to pass an outgoing message to a send adapter by calling the TransmitMessage method of the IBTTransmitter interface.

The adapter returns immediately from TransmitMessage after storing the message to be sent to some internal queue, and returns False for bDeleteMessage. This tells the Messaging Engine the message will be transmitted in an asynchronous manner.

The adapter sends the message using its own thread pool.

After the send operation completes, the adapter deletes the original message from the MessageBox database. It obtains a batch from the Messaging Engine using the IBTTransportBatch.GetBatch method of the transport proxy, and then calls DeleteMessage.

46

Transmit adapter synchronous batch send

Batch-aware adapters may send messages synchronously or asynchronously, and may perform transacted send operations. To send batches of messages, a send adapter must implement the following interfaces:

For the synchronous batch send, the Messaging Engine gets a batch from the adapter and adds messages to be transmitted to that batch. The Messaging Engine adds each message to the batch and sends the messages only when it calls the Done method on the batch. The adapter returns True for bDeleteMessage for each message that it intends to transmit synchronously. The adapter should save message data, as opposed to a message pointer, in its TransmitMessage implementation. This is because the message pointer is no longer valid after True is returned, and should not be used or cached for later use

47

Transmit adapter asynchronous batch send

For the asynchronous batch send, the Messaging Engine gets a batch from the adapter and adds messages to be transmitted to that batch. The messages are only sent when the Messaging Engine calls the Done method on the batch. The adapter returns False for each message that it intends to transmit asynchronously. The adapter then gets a batch from the adapter proxy and deletes those messages that it successfully transmitted

48

Transmit adapter tx asynchronous batch send

An adapter creates an MSDTC transaction and returns a pointer to that object in the call to the BeginBatch method of the IBTTransmitterBatch interface. The Messaging Engine calls this method to obtain a batch with which it posts outgoing messages to the send adapter. When the adapter finishes the send operation and commits or rolls back a transaction, it notifies the Messaging Engine of the result of the transaction by using the DTCCommitConfirm method of the IBTDTCCommitConfirm interface

49