Logo
programming4us
programming4us
programming4us
programming4us
Home
programming4us
XP
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server
programming4us
Windows Phone
 
Windows Server

BizTalk 2009 : WCF LOB Adapter SDK (part 5) - Implementing the Message Exchange Handlers

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
6/26/2011 4:42:32 PM

5. Step 5: Implementing the Message Exchange Handlers

Now that you have learned how to implement the metadata handlers, it's time to get to the meat and potatoes of any WCF LOB Adapter—communicating with the target LOB system. In this step, you will learn how to implement the synchronous inbound and outbound handlers. In the outbound scenario, the WCF LOB Adapters communicate with the target LOB systems by sending the request and receiving the response that will be returned to the client. In the inbound scenario, the WCF LOB Adapters monitor the target system for a particular event or data and notify the client. These message exchange patterns are represented by two interfaces: IOutboundHandler and IInboundHandler.

5.1. Implementing the IOutboundHandler Interface

To enable the outbound capabilities of the adapter, you have to implement the IOutboundHandler[] interface from the Microsoft.ServiceModel.Channels.CommonIOutboundHandler interface is located in the Microsoft.ServiceMode.Channels.dll assembly and is defined as follows: namespace. The

[] http://msdn.microsoft.com/en-us/library/microsoft.servicemodel.channels.common.ioutboundhandler.aspx

public interface IOutboundHandler : IConnectionHandler, IDisposable
{
Message Execute(Message message, TimeSpan timeout);
}

The Execute method extracts data from the incoming WCF message, invokes the corresponding method on the target LOB system passing the extracted data as parameters, and returns a WCF response message to the client application. Implementing the Execute method, you have to follow two rules:

  • If your adapter participates in one-way operations and doesn't expect to receive any outgoing message, the Execute method has to return null.

  • If your adapter participates in two-way operations with Microsoft.ServiceModel.Channels.Common.OperationResult equal to nothing, the Execute method has to return the WCF message with an empty body. Otherwise, the outgoing message has to contain the operation result. To be consumable by BizTalk applications, your adapter must support two-way operations because of the restrictions imposed by the BizTalk WCF-adapter.

As the product documentation[] states, the WCF LOB Adapter SDK forms incoming and outgoing messages according to the following rules.

[] http://msdn.microsoft.com/en-us/library/bb798099.aspx

For the incoming WCF request messages:

  • Message action = operation's nodeID

  • Message body is formed according to the following pattern:

    <displayname><parametername>[value]</parametername></displayname>

For the outgoing WCF response messages:

  • Message action = operation's nodeID + \response

  • Message body takes the following form:

    <displayName + "Response"><displayName + "Result">
    <datatype>[value]</datatype>
    </displayName + "Result"></displayName + "Response">

For example, for the string GetRooms (string) operation supported by the hotel adapter with nodeId = "Hotel\GetRooms" and displayName="GetRooms", the incoming and outgoing messages will look as follows.

For the incoming message:

<GetRooms>
<string>{data}
</string>
</GetRooms>

For the outgoing message:

<GetRoomsResponse>
<GetRoomsResult>
<string>{data}</string>
</GetRoomsResult>
</GetRoomsResponse>

Now let's get to the code:

  1. In Visual Studio, open the HotelAdapterOutboundHandler.cs file.

  2. Add the using System.Xml and using System.IO directives.

  3. Find the Execute method, and replace it with the following code:

    /// <summary>
    /// Executes the request message on the target system
    /// and returns a response message.
    /// If there isn't a response, this method should return null
    /// </summary>
    public Message Execute(Message message, TimeSpan timeout)

    {
    OperationMetadata om = this.MetadataLookup.
    GetOperationDefinitionFromInputMessageAction(
    message.Headers.Action, tim-
    eout);
    if (om == null)
    {
    throw new AdapterException("Invalid action " +
    message.Headers.Action);
    }
    //actions are specified in the proxy files
    //or can be configured in WCF-custom adapter
    switch (message.Headers.Action)
    {
    case "Hotel/GetRooms":
    XmlDictionaryReader inputReader =
    message.GetReaderAtBodyContents();
    // move to the content
    while (inputReader.Read())
    {
    if ((String.IsNullOrEmpty(inputReader.Prefix) &&
    inputReader.Name.Equals("hotelName"))
    || inputReader.Name.Equals(
    inputReader.Prefix + ":" + "hotelName"))
    break;
    }
    inputReader.Read();
    //assume there are 10 rooms available.
    string responseValue = inputReader.Value + ":10 rooms";
    StringBuilder outputString = new StringBuilder();
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.OmitXmlDeclaration = true;
    // Create response message
    XmlWriter replywriter =
    XmlWriter.Create(outputString, settings);
    replywriter.WriteStartElement("GetRoomsResponse",
    HotelAdapter.SERVICENAMESPACE);
    replywriter.WriteElementString("GetRoomsResponseResult",
    responseValue);
    replywriter.WriteEndElement();
    replywriter.Close();

    XmlReader replyReader =
    XmlReader.Create(
    new StringReader(outputString.ToString()));


    // Output Message Format
    // <GetRoomsResponse><GetRoomsResult>{rooms}
    //</GetRoomsResult></GetRoomsResponse>
    // create output message
    return Message.CreateMessage(
    MessageVersion.Default,
    "Hotel/GetRooms/response",
    replyReader);
    default: throw new AdapterException("Invalid action " +
    message.Headers.Action);
    }
    }
    #endregion IOutboundHandler Members
    }

5.2. Implementing the IInboundHandler Interface

To enable the inbound capabilities of the adapter, you have to implement the IInboundHandler[] interface from the Microsoft.ServiceModel.Channels.CommonIInboundHandler interface is located in the Microsoft.ServiceMode.Channels.dll assembly and namespace. The is defined as follows:

[] http://msdn.microsoft.com/en-us/library/microsoft.servicemodel.channels.common.ioutboundhandler.aspx

public interface IInboundHandler : IConnectionHandler, IDisposable
{
void StartListener(string[] actions, TimeSpan timeout);
void StopListener(TimeSpan timeout);
bool TryReceive(TimeSpan timeout, out Message message,
out IInboundReply reply);
bool WaitForMessage(TimeSpan timeout);
}

Table 16 describes what each method does.

Table 16. IInboundHandler Public Methods
MethodDescription
StartListenerStarts listening to messages with the provided WS-Addressing actions. If none is specified, it listens to all or the default actions.
StopListenerStops listening.
TryReceiveTries to receive an inbound message from the target system.
WaitForMessageWaits for the inbound WCF-message from the LOB system.

Here is the process you have to follow:

  1. In Visual Studio, open the HotelAdapter.cs file.

  2. Add new ServiceName property, as shown here:

    public string ServiceNamespace
    {
    get
    {
    return SERVICENAMESPACE;
    }
    }

  3. In Visual Studio, open the HotelInboundHandler.cs file.

  4. Expand the Using Directives region, and make sure it matches the following code snippet:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Xml;
    using System.IO;
    using System.ServiceModel.Channels;
    using System.Timers;
    using Microsoft.ServiceModel.Channels.Common;

  5. Add the following class member variables to the class:

    private Queue<Message> inboundMessages;
    private int pollingPeriod;
    private Timer pollingTimer;
    private Object syncLock;

  6. Replace the HotelInboundHandler constructor with the following code snippet:

    public HotelAdapterInboundHandler(HotelAdapterConnection connection
    , MetadataLookup metadataLookup)
    : base(connection, metadataLookup)
    {
    pollingPeriod =
    connection.ConnectionFactory.Adapter.PollingPeriod;
    syncLock = new Object();
    }

  7. Add the implementation for the StartListener and StopListener methods, as shown here:

    /// <summary>
    /// Start the listener
    /// </summary>

    public void StartListener(string[] actions, TimeSpan timeout)
    {
    //listen for all actions
    //create a Queue to hold inbound messages;
    inboundMessages = new Queue<Message>();
    //set up a timer to pool for guest arrivals

    pollingTimer = new System.Timers.Timer(pollingPeriod * 1000);
    pollingTimer.Elapsed +=
    new System.Timers.ElapsedEventHandler(CheckArrivals);
    }


    /// <summary>
    /// Stop the listener
    /// </summary>
    public void StopListener(TimeSpan timeout)
    {
    if (pollingTimer != null)
    {
    pollingTimer.Stop();
    pollingTimer = null;
    }
    lock (syncLock)
    {
    inboundMessages.Clear();
    inboundMessages = null;
    }
    }


  8. Now add the implementation for the TryReceive and WaitForMessage methods:

    /// <summary>
    /// Tries to receive a message within a specified interval of time.
    /// </summary>
    public bool TryReceive(TimeSpan timeout,
    out System.ServiceModel.Channels.Message message,
    out IInboundReply reply)
    {
    reply = new HotelAdapterInboundReply();
    message = null;

    //assume timeout is infinite
    while (true)
    {
    lock (syncLock)

    {
    if (inboundMessages == null)
    {
    //listener has been closed
    return false;
    }
    if (inboundMessages.Count != 0)
    {
    message = inboundMessages.Dequeue();
    if (message != null)
    {
    return true;
    }
    }
    }
    System.Threading.Thread.Sleep(500);
    }
    }

    /// <summary>
    /// Returns a value that indicates whether a message
    /// has arrived within a specified interval of time.
    /// </summary>
    public bool WaitForMessage(TimeSpan timeout)
    {
    //wait for message to appear in the queue
    while (inboundMessages.Count == 0) { };
    //check if message is there but don't remove it
    Message msg = inboundMessages.Peek();
    if (msg != null)
    {
    return true;
    }
    return false;
    }


  9. Add the implementation for the ElapsedEventHandler callback, as shown in the following code snippet:

    private void CheckArrivals(object sender, ElapsedEventArgs args)
    {
    //poll for example a database
    //if new guest found create inbound message

    HotelAdapter adapter = this.Connection.ConnectionFactory.Adapter;
    String xmlData = String.Format(@"<OnGuestArrived xmlns=""{0}"">
    <FirstName>{1}</FirstName>
    <LastName>{2}</LastName></OnGuestArrived>",
    adapter.ServiceNamespace,
    "John",
    "Smith");
    XmlReader reader = XmlReader.Create(new StringReader(xmlData));
    // create WCF message
    Message requestMessage =
    Message.CreateMessage(MessageVersion.Default
    , "Hotel/OnGuestArrived"
    , reader);
    // add it to inbound queue
    inboundMessages.Enqueue(requestMessage);
    }

  10. Save and build the project.

You have finished the development stage of the HotelAdapter.

NOTE

In the "scale-out" architecture, your adapters may be deployed on more than one server. If this is the case, then in the inbound scenario, there is a potential danger of sending duplicate messages to the client application when different instances of your adapter react on the same event on the target LOB system. Unfortunately, this issue doesn't have a generic solution, and therefore you, an adapter developer, have to provide the implementation specific to your target LOB system to prevent duplicate messages from occurring.

Other -----------------
- SQL Server 2008 : Configuring the Instance (part 3)
- SQL Server 2008 : Configuring the Instance (part 2) - Specifying the Backup Compression Default & Enabling Login Failure Auditing
- SQL Server 2008 : Configuring the Instance (part 1) - Viewing Configuration Settings & Specifying Maximum and Minimum Server Memory
- Microsoft PowerPoint 2010 : Expanding PowerPoint Functionality - Loading and Unloading Add-ins
- Microsoft PowerPoint 2010 : Expanding PowerPoint Functionality - Viewing and Managing Add-ins
- Microsoft Dynamics CRM 2011 : Sending and Tracking Email Messages in Microsoft Dynamics CRM for Outlook
- Microsoft Dynamics CRM 2011 : Using Microsoft Dynamics CRM for Outlook - Using the Add Contacts Wizard
- Microsoft Dynamics CRM 2011 : Using Microsoft Dynamics CRM for Outlook - Creating and Tracking Contacts
- Windows Server 2008 R2 : Managing Disks and Disk Storage - Understand the Basics (part 2) - Work with Partitions & Use DiskPart
- Windows Server 2008 R2 : Managing Disks and Disk Storage - Understand the Basics (part 1) - Work with Your Storage
 
 
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
 
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server