Saturday, July 30, 2011

Encoded Multi Part Messages to SOAP adapter

I had one of those old/non conforming to the standards web service of kinds I needed to call.
The ones you really hate, and wish they’d just upgrade them to WCF... but hey thats 90% of integration, old rotten systems... so I persisted.

It did accept xml messages, however was very fussy as it seemed to employ the good old, no xml translator, the one that is more of a text base, string manipulation xml decoder, where if you send quite valid xml, it will fail because they didn’t support it.
This kind of set up is... sadly... quite common....
It would not handle xml tags that had no content, but had a closing tag.

EG: <salary currency="en-AU"></salary>
It needed to have them encoded differently:
<salary currency="en-AU"/>
Now both of these examples are valid xml, however good old string parser went the easy route and didn’t cater for an end tag.
The problem is that you can’t exactly tell biztalk to not put the end tag, it’s going to put xml, valid xml, and thats what it does....
Further more... it also complained about white space in my xml message.... ??? you say???
<salary currency=""><salary> <standout logoid="”1111"><standout>
The white space it didn’t like was between the tags, <salary>[--- white space ---]<standout>

Now how on earth do you cater for this?

A custom pipeline component to the rescue, just before it sends the message I would “FixUP” the xml by removing the end tags, and white space between tags, using my old favourite, c#.net .
So I go to the trouble of making a custom pipeline component, hook it up to a custom send pipeline, and then attach the pipeline to the send port.

BANG, nothing happens... it stil fails for the same reason.

At this point I’m a little annoyed, and more p’d off than i’d care to mention.
I spend the next hour trying to figure out why......

Firstly the web service is a SOAP web service, I have to use the SOAP adapter because it’s a multipart message, I check with Yossi. http://blog.sabratech.co.uk/2009/08/biztalk-wcf-adapter-and-multipart.html to discover that even if I went to WCF and fudged a wcf-http port to work it would not make much difference.

I then try and pump the message out to the file system, using a send port in the orchestration. I get a message, with only the first part. It throws me for a second, then I realise that the FILE adapter does not support multi part messages. Weird, considering all messages are multi part messages, most with one part, but I prevail.

How do I see what is going to the adapter? I really need to see the message, I mean I have tested by component, and it is good, it works and does the trick, its .net, so I of course have a .TEST project to test it...

How... Ah..ha... You can stop the send port, not unenlist it, but stop it, the message will still go to the port however sit there waiting for you.

I can then see the message from the admin console, ALL parts of the message, a much better way to debug messages BTW, I notice the message part has been encoded, the multi part message takes two strings, the second of which is my xml message. So the message is wrapped in a <string> tag, with the contents.... no longer in XML format, they are html encoded. My lovely <salary> tag is now a horrid, & lt;Salary& gt; the xml is hardly readable.... I cringe, it’s destroyed my lovely xml...

Now I can see what’s going on, before it even gets to my custom pipeline, my xml is encoded, therefor my pipeline which is looking for xml, does not find any, and does not work.... UGH!

Interestingly when I assign the value of the xml in the outbound message, I do it from a message assignment shape, I have the xml in my grasp...
I do a cheeky thing in BizTalk, turn the message into an xml document, which I can turn into text. Luckily I wrote the pipeline by using a separate class for the tagging and white space cleaning. So I can call the methods from the message assignment shape, and I process the xml, clean and massage it.

I then set the xml document back up by loading the NEW xml into to, and then set the value of the parameter of the outbound message to the xmldocument.

The message is now encoded before it goes to the port. I send the message to the port and wolla, response message, in xml... that tells me it worked.

This is a bit of a hack and a workaround, it does work, however I would have preferred the pipeline to work.

I do note with interest that only the SOAP adapter is able to process this multipart message, because it’s an OLD soap web service, I did hear of talk of scrapping the SOAP adapter, however multipart messages are VERY common on soap web services, and this would be foolish to scrap it. I’d like to see support for multi part messages in the WCF set of adapters, with more backwards compatible support, so I don’t have to use an out dated SOAP adapter.