Party Time?

by Dan Rosanova 3. August 2009 01:37

For a long time I never worked very much with Parties and Role Links in BizTalk and I've been teaching it some lately (and had a question posted on a board) so here goes. I really just plan to talk about them and tell you where to get more info on using them. I guess it started when I was just trying to touch all the features I never had and found Role Links in the Orchestration designer. I checked MSDN which does give the answers, but not as directly as I was looking for (in retrospect the documentation is great, but I just needed a good overview to understand what I was looking at).

As I looked more I came to Richard Seroter's blog posting here which also points to a good post by Todd Uhl. This all started to make more and more sense over time. Then I had the requirement for a solution to send messages to a large variety of partners depending on some information that is looked up based on the input of an incoming message. There are a lot of ways to solve this in BizTalk and Dynamic Ports is certainly one, but I really don't like dynamic ports because they obscure important solution details from the administrator / operations team. To make matters worse the number of possible partners was likely to be in the hundreds for this solution.

After yet more research and playing around I stumbled onto the Party Resolution Sample (it's in the older versions too despite this link now pointing to 2009) and this is where I had the epiphany. Parties and Role Links could solve my problem with almost no work on my part. Here was my chance to look like a superhero without needing to do much more than figure out how to tie the pieces together (something that I find is common in BizTalk).

Basically it works like this: you use Role Links in your Orchestration like Richard suggests and if you have the defining piece of information in your inbound message (like in Richard's case) you're set. All I did was have a simple external service lookup that provided me that data from an existing repository. The best part of this solution is that the Maps go on the Ports (like they always should) and the Orchestration simply uses the internal (canonical) schemas. The other than assigning/resolving the party in the expression shape the Orchestration knows nothing about the ports and their details.

There are a few caveats such as: the Parties must exist in the BizTalk Group (surprise) and that they must have ports tied to them which will become a requirement of application (or more precisely Orchestration) binding before everything can be turned on. Also I'm pretty sure the ports need the same basic communication pattern (One Way or Two Way).

Currently rated 3.0 by 2 people

  • Currently 3/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Orchestration

Handling Binary Messages in Orchestrations

by Dan Rosanova 4. December 2008 06:02

Introduction

In my post How BizTalk Identifies Types I explained that any message can be represented within an Orchestration as an instance of XmlDocument even if it is not a valid XML document (such as a binary file). In this post I will explain how you can handle binary documents in Orchestrations and walk through how I handled receiving reports from SQL Server Reporting Services (SSRS) and sending them to Sharepoint via the Sharepoint Services Adapter.

Often there are times in an integration solution where non XML documents must be operated on by a solution. One such example would be receiving PDF or image files and sending them to another location. In simple cases you may be able to do this in a messaging only scenario, in more complicated cases you may need to bring in Orchestration.

Sending and Receiving Binary Messages in Orchestration

Although any message can indeed be represented as an XmlDocument in an Orchestration performing any operation on the XmlDocument (i.e. the message or variable that is the message) will result in a runtime exception. If you're solution requires some sort of action to be performed on these documents that cannot be done via direct subscription you are limited to setting promoted properties on the message (i.e. Adapter / BizTalk properties). This may be all you need to do and if that's the case you may not need an Orchestration in the first place, but maybe a Pipeline.

Creating Binary Messages in Orchestration

At times you may find yourself required to do something a bit more complex, like retrieve the binary result of a Web Service call (like I did with SSRS) and doing something with the message payload. In my case I wanted to put the report in a Sharepoint site dynamically, which certainly could have been done with the SSRS Sharepoint integration, but I don't like that solution as it is a point to point rather than hub and spoke remedy.

There are several ways to create messages in Orchestrations and some are not very well documented, but the one recommended way (documented in the Sdk\Samples\Pipelines\ComposedMessageProcessor example) to create new Binary Messages is to use a send Pipeline called by a Message Assignment shape. Creating the Pipeline can be made much easier by using the BizTalk Server Pipeline Component Wizard which is a free Visual Studio plug-in that makes this a very simple process (we'll look at this later).

The main caveat here is something I pointed out in How BizTalk Identifies Types and that is that Pipelines and Orchestrations use different interfaces to represent messages. As a result, you must the use the supplied wrapper classes for executing this functionality. For one you will need an Orchestration variable of type Microsoft.XLANGs.Pipeline.SendPipelineInputMessages (which requires a reference to Microsoft.XLANGs.Pipeline.dll, in your BizTalk install location).

Calling the Pipeline

The basic steps are quite simple: add a message to an instance of this class via the Add method which takes one parameter: the message to be added; then call the Microsoft.XLANGs.Pipeline.XLANGPipelineManager.ExecuteSendPipeline method from within a Message Assignment shape or an Expression shape before the Message Assignment.

Every example I've ever seen including Composed Message Processor always first sets the output message (the XLANGMessage that is the last parameter) to null before calling this method so it's probably a good idea to do so.

Microsoft.XLANGs.Pipeline.XLANGPipelineManager.ExecuteSendPipeline(

    Type, SendPipelineInputMessages, XLANGMessage);

Be sure the Type is the that of your .btp pipeline that uses your component, not the Pipeline component created by the Wizard that we discuss below.

After this your binary message is in the message you supplied for the XLANGMessage parameter which I generally make as type XmlDocument. From here you are free to do what you like with the message, but remember it is not really an XmlDocument so don't call any of its methods.

More about that Pipeline

After you've run the Pipeline Component Wizard you have a class that implements IComponent, IBaseComponent, IPersistPropertyBag, and IComponentUI. The single method Execute of IComponent is the one we're interested in, this is what will be called when ExecuteSendPipeline is invoked.

If your situation is like mine this is all slightly complicated by the fact that the binary data you want is in a Base64String typed element within a message you have received. This is where the Pipeline Component Wizard can really help by allowing you to specify properties that can be set for the Pipeline. I declared an xpath used to read out the payload element from the body, this way I can reuse my Pipeline or change message formats. You can also create a class that represents your original message (containing the binary element) and use the XmlSerializer to create an instance of this message and access the byte[] property containing your raw byes (the XmlSerializer handles the translation to and from Base64String for you). End result, don't forget to convert from Base64String to byte[] or your file will be corrupted.

Below is the code from my Execute method. The properties are created for you in the Wizard and you don't need to worry about the other parts of the class.

//This is required: create the message to return

XmlTextReader reader = new XmlTextReader(inmsg.BodyPart.Data);

IBaseMessageFactory factory = pc.GetMessageFactory();

IBaseMessage message = factory.CreateMessage();

IBaseMessagePart body = factory.CreateMessagePart();

//This uses more properties and reflection to process the message

System.Runtime.Remoting.ObjectHandle objectHandle = Activator.CreateInstance(_assemblyName, _typeName);

object underlyingObject = objectHandle.Unwrap();

XmlSerializer serializer = new XmlSerializer(underlyingObject.GetType());

underlyingObject = serializer.Deserialize(reader);

object result = underlyingObject.GetType().InvokeMember(PropertyName, System.Reflection.BindingFlags.Public |

System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetProperty, null, underlyingObject, null);

byte[] resultBytes = (byte[])result;

Importantly you use either the segment above or the one below, but not both.

//This avoids the relfection, but makes the pipeline only useful to one message type

XmlSerializer serializer = new XmlSerializer(typeof(RenderResponse));

RenderResponse response = (serializer.Deserialize(reader)) as RenderResponse;

byte[] resultBytes = response.Result;

//This also is common to both approaches

MemoryStream memStream = new MemoryStream();

memStream.Write(resultBytes, 0, resultBytes.Length);

memStream.Position = 0;

body.Data = memStream;

pc.ResourceTracker.AddResource(memStream);

StreamReader sr = new StreamReader(body.Data);

message.AddPart(inmsg.BodyPartName, body, true);

return message;

At some point you'll probably want to populate some properties for the Adapter you're using either in the Message Assignment shape in your Orchestration (which I did) or in the Pipeline itself.

Once you have your pipeline component you add it to your \Microsoft BizTalk Server 2006\Pipeline Components directory and you are free to use it when creating .btp files. At this point you simply add the Pipeline to your BizTalk Toolbox (by picking Choose Items) and then drag it into the encode stage.

If you've used properties to make your Pipeline configurable you would set them here as well. This is the Type that you will specify in the call to ExecuteSendPipeline in the Message Assignment shape.

Improvements

I know there must be a way to stream this and it would be a good idea. Loading this message into an XmlDocument or using the XmlSerializer will load the entire message into memory; this can cause problems with very large messages. The entire BizTalk engine is designed to use streaming and it would be nice to incorporate it here as well. If you can think of a way to do this, please let me know.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Messaging | Orchestration

Multipart Messages in Orchestrations

by Dan Rosanova 24. November 2008 03:02

A while back I ran into Marty Wasznicky and Scott Zimmerman excellent MSDN Article 8 Tips And Tricks For Better BizTalk Programming which is really worth a bookmarking. I really never got into their #1 Always Use Multi-Part Message Types (though the others I had picked up most of the hard way). I normally work with more messaging centric solutions and as a result do less with Orchestration, but the last year and a half has had me doing a lot more Orchestration and now I really understand this tip a lot better.

Although most Messages used in BizTalk Orchestrations are not multipart, using them in an Orchestration provides the benefit of isolating schema changes from impacting Orchestrations. Changing a schema without using multipart messages will require disconnecting all the Port, Send, and Receive shapes within the Orchestration Designer. This is a tedious an error prone process and it is not always easy to track down all of these affected shapes and there is no automated way to do it ahead of time. As the authors correctly point out; binding Ports and Messages within an Orchestration directly to a schema can lead to problems down the road. Usually these problems appear the first time you try to change something, which is often before even getting to production.

Granted there is one extra step here, defining the new part of the multipart message, but this is a small amount of work to do for a large amount of benefit. If you've ever worked with Web Services in an Orchestration (as a consumer) you've seen the Web Message Types that are generated for you; this is basically the same thing as using the multipart message types.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Messaging | Orchestration

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen