Duplicate SOAP Subscription on Dynamic Request-Response Port

Joy of joys, more subscriptions problems to debug this week with some unexpected results.

The first sign of problems were persistence errors:

Microsoft.XLANGs.Core.PersistenceException: Exception occurred when persisting state to the database. ---> Microsoft.BizTalk.XLANGs.BTXEngine.PersistenceItemException: A batch item failed persistence Item-ID dbbd66a3-d748-4051-a238-fea9509efcf4 OperationType MAIO_CommitBatch Status -1061151949 ErrorInfo The message found multiple request response subscriptions. A message can only be routed to a single request response subscription. . ---> Microsoft.BizTalk.XLANGs.BTXEngine.PublishMessageException: Failed to publish (send) a message in the batch. This is usually because there is no one expecting to receive this message.  The error was The message found multiple request response subscriptions. A message can only be routed to a single request response subscription.  with status -1061151949.

With the actual error in bold above – multiple request-response subscriptions were found which aren’t allowed (I’m not running 2006 R2 and don’t have KB923632 installed).

My solution employs an orchestration which consumes a web-service over a dynamic solicit-response port; the port itself has been created using early-binding (creating one of those ugly port names).

Subscriptions Problems

Digging into the dynamic port subscriptions, I was interested to see that a subscription is created for each adapter you have registered in your BizTalk Group. This makes sense as the transport type isn’t known up-front:

Digging into those subscriptions, I discovered two subscriptions that are exactly the same for the SOAP adapter – no wonder we have multiple request-response subscriptions…..

Apart from hacking the database to remove this unwanted subscription entry, I could find no way of updating the subs. on this dynamic port. Interestingly however, creating a new dynamic port from the Admin Console and binding that to the orchestration resulted in the correct number of subscriptions and a working solution.

I’m wondering then where the bug is: I don’t think it can be when the early-bound ports are created during deployment as the subscriptions themselves aren’t created until the port is enlisted, which (AFAIK) happens in exactly the same way for manually created send-ports. The the problem is only evident on early- and not late-bound ports!

I’m now toying with the idea of KB923632 so we don’t have to worry about this issue again, but I’m keen to understand why this is a problem in the first place, so I’d also be pleased to hear from anyone who knows of a Hotfix that addresses this duplicate subscription issue. I also think its a good one to keep in the back of your mind in-case you encounter any ‘interesting’ subscription issues.

The Case for a New Tool?

One final thing on this: diagnosing subscription problems really raises the need for a ‘Subscription Finder’ tool. We currently have the Subscription Viewer in the Admin Console, which is great, but we have to know what subscriptions we are looking for in the first place. What would have been really helpful here would be a tool where I can enter the details of the promoted properties from the Failed Routing Report and the tool locates all subscriptions that would match those properties. I am looking at putting together such a tool, so watch this space.

Enhanced by Zemanta

Cross-Application Subscription

Applications in BizTalk 2006 for me are just logical buckets that allow you place like-minded artifacts (maps, schemas, orchestrations etc.) together, so your environment when viewed through the BizTalk Admin Console looks clean and tidy and can be easily managed.

Although resources (BizTalk Assemblies) and ports can be moved between applications, they cannot exist in multiple applications at the same time*, so is it possible to have one application respond to events caused another application? Yes it is, through cross-application subscription.

If you create the most basic of subscriptions: a receive port/location and a send port, subscribed to the receive port on the ReceivePortName property; stop the send port (but leave it enlisted) and push a message through. The message will suspend because it is waiting for the send port to be started, but this gives us an opportunity to look at the context properties for the message (click on the image for a larger version):

Looking through the context properties (both promoted and non-promoted), there is no property for the originating application, or any ‘special’ properties that only the internals of BizTalk understands such as those seen in messages traversing request/response ports.

Given that applications are these ‘logical buckets’ and that they sit above the Message Box and the subscription engine, there is nothing stopping us therefore in subscribing to messages in ‘Application B’ that originated from ‘Application A’. This means we can quite easily perform cross-application subscription:

In a new application, create a send port that will subscribe to the ReceivePortName property as we did above and start it; drop a new messages in and you should now receive two output copies of the message, processed by different applications!

There is at least one drawback I can see here: Orchestrations in Application B still won’t be able to be bound to Receive Ports in Application A as the Admin Console won’t let you (without some brave database hacking…); it would however work if Orchestration receive ports were directly bound to the Message Box.

I can see that this approach could have beneficial uses across business-streams, or an ESB, where the on-ramp functionality lives in one application and end-point subscriptions live in other, separate applications.

Any other drawbacks or use-cases that I’m missing here?

* this isn’t necessarily true, as applications can reference other applications.