BizTalk and the WCF Channel for WebSphere MQ

This post is about how to (or not how to – more of that later) use the WCF Channel for WebSphere MQ with BizTalk.

WCF Channel for WebSphere MQ is part of BizTalk Adapters for Host Systems (BAHS) 2.0. (On MSDN subscriber downloads, it is listed under BizTalk Server 2009. In MSDN library, the product documentation is listed under Host Integration Server 2009.) During installation, check this component:

image

To be able to use the new WCF channel, a new channel binding must be defined in Machine.config (in C:WindowsMicrosoft.NETFrameworkv2.0.50727CONFIG). Under <system.serviceModel><extensions><bindingExtensions> add

<add name="mqChannelBinding" type="System.ServiceModel.Channels.WebSphereMQ.WebSphereMQBindingCollectionElement, System.ServiceModel.Channels.WebSphereMQ.Channel, Version=7.0.2300.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

(For details, see How to Enable the WCF Extensibility Points with the WCF Adapters.)

To be able to test, I installed an evaluation copy of WebSphere MQ 7.0, which I downloaded from IBM. (Registration is necessary.) During installation, include MQ Explorer – it is handy for troubleshooting. During configuration, I used the following options:

image

The installation was performed on a Windows 2008 server called BTS2009. This installation created a queue manager called QM_BTS2009, a channel called S_BTS2009 and a listener on port 1414.

Next, create a send port in BizTalk, choose transport type WCF-Custom and click Configure. On the general tab, the address (URI) should be net.mqs://<queue manager name>/<queue name>, e.g. net.mqs://QM_BTS2009/default. On the Binding tab, select mqChannelBinding and input the appropriate configuration:

Key Value Example
connectionType BaseClient BaseClient
deadLetterQuee True True
leaveMQHeadersInMessage True True
mqcdChannelName <channel name> S_BTS2009
mqcdConnectionName <host>(<port>) BTS2009(1414)
mqcdTransportType TCP TCP

Or import this configuration file if you don’t want to type so much:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <enterpriseLibrary.ConfigurationSource selectedSource="ESB File Configuration Source" />
  <system.serviceModel>
    <client>
      <endpoint address="net.mqs://QM_BTS2009/default" behaviorConfiguration="EndpointBehavior" binding="mqChannelBinding" bindingConfiguration="SendSampleBinding" contract="BizTalk" name="ToMQSeries" />
    </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name="EndpointBehavior" />
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <mqChannelBinding>
        <binding name="SendSampleBinding" connectionType="BaseClient" leaveMQHeadersInMessage="True" deadLetterQueue="True" mqcdChannelName="S_BTS2009" mqcdTransportType="TCP" mqcdConnectionName="BTS2009(1414)" mqpmoSyncPoint="True" mqgmoSyncPoint="True">
          <readerQuotas maxDepth="10" maxArrayLength="1000" maxBytesPerRead="2000" />
        </binding>
      </mqChannelBinding>
    </bindings>
  </system.serviceModel>
</configuration>

Now send an XML document to this send port and check the result in WebSphere MQ Explorer. The queue depth should be 1.

So what about receiving a message from MQ? I tested that too, but had issues. Using the following configuration:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <enterpriseLibrary.ConfigurationSource selectedSource="ESB File Configuration Source" />
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="SendReceiveSampleServiceBehaviour" name="BizTalk">
        <endpoint address="net.mqs://QM_BTS2009/default" behaviorConfiguration="EndpointBehavior" binding="mqChannelBinding" bindingConfiguration="SendReceiveSampleBinding" name="FromMQSeries2" contract="BizTalk" />
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="EndpointBehavior" />
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="SendReceiveSampleServiceBehaviour" />
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <mqChannelBinding>
        <binding name="SendReceiveSampleBinding" connectionType="BaseClient" leaveMQHeadersInMessage="True" deadLetterQueue="True" mqcdChannelName="S_BTS2009" mqcdTransportType="TCP" mqcdConnectionName="BTS2009(1414)" mqpmoSyncPoint="True" mqgmoSyncPoint="True">
          <readerQuotas maxDepth="10" maxArrayLength="1000" maxBytesPerRead="2000" />
        </binding>
      </mqChannelBinding>
    </bindings>
  </system.serviceModel>
</configuration>

I got the following warning repeatedly in the application event log:

Event Type:    Warning
Event Source:    BizTalk Server 2009
Event Category:    (1)
Event ID:    5740
Date:        2009-08-25
Time:        15:24:07
User:        N/A
Computer:    BTS2009
Description:
The adapter "WCF-Custom" raised an error message. Details "System.ServiceModel.Channels.WebSphereMQ.WebSphereMQException: Unexpected error; webspheremqtransport.cpp#1206; ImqQueueManager::connect; completionCode = 2; reasonCode = 2058
   at System.ServiceModel.Channels.WebSphereMQ.AsyncResult.End[TAsyncResult](IAsyncResult result)
   at System.ServiceModel.Channels.WebSphereMQ.TryReceiveAsyncResult.End(IAsyncResult result, Message& message)
   at System.ServiceModel.Channels.WebSphereMQ.WebSphereMQInputChannel.EndTryReceive(IAsyncResult result, Message& message)
   at System.ServiceModel.Dispatcher.InputChannelBinder.EndTryReceive(IAsyncResult result, RequestContext& requestContext)
   at System.ServiceModel.Dispatcher.ErrorHandlingReceiver.EndTryReceive(IAsyncResult result, RequestContext& requestContext)".

The message was not read. The strange thing is that I could get it to work with the MQSC (client based) adapter. I could also run the BAHS SendReceiveSample .Net sample without errors.

Supposedly the cause is that BizTalk uses System.URI which appears to convert everything to lower case, and since MQ is case sensitive, it does not work. So until this bug is fixed, you have to use queue manager and queue names in lower case.

In my case, I created a new queue manager called qm_test with a listener listening on port 1415. I then created a queue called q_test and a channel called S_BTS2009 as before. I then adjusted the send port and receive location configurations. That worked!

Advertisements