I admit it - this article's title is a little contrived.
You are likely to get a different answer to the question "What is BizTalk?" depending on your perspective and whom you ask. So here it is - in 47 words (or less) - the answer to the question, "What is BizTalk?":
- BizTalk is an application platform for integrating applications based on messaging and workflow.
- BizTalk is an integration and business process automation framework.
- BizTalk connects existing applications on any platform, and makes it easy to compose, expose, and consume new services.
- BizTalk enables business processes integration and automation.
There are likely more answers to the question too. Why are there so many answers to such a simple question?
As of the release of BizTalk 2006 R2, BizTalk Server is in its fifth major release. Since it was first released, more than 7,000 customers have adopted it as their integration platform of choice. Since integration needs are constantly changing, so are the innovative solutions that are built using BizTalk Server. Some solutions focus on using a small subset of BizTalk's features, while others use almost every available feature - the solutions' architects and developers of these have varying perspectives, resulting in a varied set of descriptions.
At the end of this article, you will understand the following concepts:
- BizTalk is a versatile platform.
- BizTalk is loosely coupled - its components don't directly rely on each other, and the product itself is loosely coupled with its environment.
- BizTalk uses a Publish-Subscribe model.
- BizTalk is type safe - XML is considered to be as type safe as C# types.
- BizTalk uses a declarative programming model.
- BizTalk is extensible through custom assemblies (DLLs).
- BizTalk builds on what you already know.
Exploring BizTalk's Design
BizTalk is versatile primarily because its design separates components to the point that they are loosely coupled, meaning, its components don't have direct dependencies on each other. This loose coupling results in a high degree of isolation between components, allowing designers to focus on specific areas like communication and data access.
For example, BizTalk uses adapters to communicate with other systems through SOAP, SQL Server, MSMQ, and others. Changes in a deployed solution's communication methods don't affect other solution components. Contrast that with more traditional applications that might have a data access layer and code throughout the solution that uses the data access layer. Changing the application from, for example, using SQL Server to using XML files likely requires a lot of updates to not only the data access layer, but also to the rest of the application.
BizTalk's loosely coupled design makes it possible to add or change capabilities, often while a BizTalk application is still running, without affecting the currently running instances.
Understanding the Publish-Subscribe Model
BizTalk is, at its core, a messaging system that is based on a model called Publish-Subscribe. The Publish-Subscribe model is an asynchronous programming technique that makes it easier to share information between entities that send information (publishers) and entities that receive information (subscribers). The main advantages of the Publish-Subscribe model include scalability (the ability to take advantage of available, changing, resources) and flexibility (works as the basis for many other programming approaches).
In more concrete terms, think of Publish-Subscribe as if you are a speaker at a conference. You publish information using your voice, and the audience is consuming that information by listening. You are actively publishing information, and members of the audience register their interest by being present and listening.
You can speak to an audience of one person or hundreds - the only difference is in how you project that information (speaking plainly, loudly, or using a microphone). The way you project the information is the one aspect of scalability - you can reach more members of the audience over a larger physical space with resources like a microphone and a small speaker or several large speakers.
Your speech (content) is the same if the audience has one person or hundreds. Members of the audience can leave and new members can join at any time without affecting your ability to publish information. Since people can join or leave at anytime, you are effectively decoupled from not only the overall audience, but also, the identity of the individual members of the audience - you are essentially making a speech to anonymous members of the public.
BizTalk handles messages in the same way: BizTalk publishes messages to a common area, and processes that are interested in consuming the published messages subscribe to them (orchestrations, receive or send ports, or directly bound ports).
The Publish-Subscribe model wouldn't work if all subscribers receive all messages. When a subscriber registers its interest, the registration includes filters to select messages of interest. In general, there are two types of filters - topic based filters that BizTalk represents as Receive Ports or Send Ports, and content based filters which filter messages based on their content - BizTalk provides several means of filtering based on content.
So, what does a BizTalk subscription look like? Here is an example:
The subscription includes both types of filters that I mentioned earlier:
- The topic filter is based on the
- The content filter is based on an attribute called
A Receive Port is an abstraction (logical representation) of a means to receive a message using a specific protocol or location. For example, BizTalk can receive messages in files, from Message Queues, or via HTTP (among the methods - there are others). The specific protocols and locations are referred to as Receive Locations. There can be several Receive Locations per Receive Port, making it possible to accept messages from a variety of locations and treat them the same way in BizTalk. The following is how BizTalk represents a Receive Port in the Orchestration Designer:
The MessageType is a representation of a message's type. BizTalk represents all messages in XML. One important aspect of all XML documents is its namespace. Briefly, a namespace allows you to describe a Person (for example) in one way without affecting anyone else's description - since Person can mean different things to other applications. Another important aspect of all XML documents is the name of the document's root node. In the preceding example, the combination of the message's namespace and name of the root node are represented as:
The hash symbol (#) separates the namespace from the name of the root node. I'll explain more about the concepts of XML namespaces and root node names in a future blog post.
So, where is the "Publish" part of Publish-Subscribe? You can publish messages in BizTalk in a variety of ways, including:
- Sending a message to a receive port
- Calling an orchestration from another orchestration
- Creating a direct bound port (more about this in a future article)
- Publishing messages for which there are no subscribers (known as routing failures)
BizTalk is very robust since it can recover from a variety of hardware and software failures. This robustness is provided in a large part by SQL Server - BizTalk's message and configuration store. BizTalk not only manages publications and subscriptions using SQL Server, it also uses SQL Server to store and route messages. The logical name of the common location where publications and subscriptions take place is the MessageBox - a BizTalk SQL Server database.
The MessageBox is an integral part of BizTalk's implementation; however, it is not strictly necessary, as a developer, to know much more about it than the fact that it exists and its role. The BizTalk system (Visual Studio and the management tools) abstract the MessageBox database so you can treat it as an opaque, supporting, subsystem.
A message's type is defined by its XML representation, and is treated just like C# treats its own types. You cannot pass a string to a function that expects an integer - in the best case, you will get a compiler error, and a run-time error in the worst case. BizTalk works in exactly the same way.
A message in BizTalk is defined by its XML representation. Specifically, a combination of the XML document's namespace and root node name defines a message's type.
For example, you could describe a Person using the following XML instance document:
The document's namespace is "http://example.com/sample" and the name of the root node is
Person. BizTalk represents the combination of the two like this:
The notation is important because you will see it when you debug routing failures, a common development-time error, and a number of other places in BizTalk.
When BizTalk receives a Person message, it publishes the message to a general location (for those of you that are interested, the general location is called the MessageBox); however, that information is not strictly necessary at this point. Interested recipients, subscribers, receive notification that a new message is waiting. BizTalk delivers the actual message to the subscriber instead of a general message, or event, that indicates that a message is available.
A subscriber describes the message it is interested in receiving using an expression similar to this:
While the left side of the expression (to the left side of the == operator) is new, the right side should look familiar - it is the message type of the Person message we saw earlier. Notice that the comparison is being made to a property called
MessageType is an attribute of all messages, effectively promoting a seemingly simple XML document into a first class type. Just as in programming with a language like C#, BizTalk enforces type safety to assure that you cannot send a message to a subscriber that cannot process it, or assign incompatible messages to each other.
You create a new message type by creating an XML schema using the BizTalk Schema Designer in Visual Studio. You don't have to know a lot about XML or XML schemas to be able to create a schema, since BizTalk allows you to describe the schema and then handles the details of generating the type descriptions for you. This approach is called declarative programming since you focus on what you want to accomplish rather than how to accomplish it. I discuss Declarative Programming next.
Understanding BizTalk Declarative Programming
BizTalk is different in the way that you work with it. In contrast to applications you write using code, you may have seen and heard that BizTalk developers write very little, if any, code.
BizTalk programming uses a declarative model. The declarative programming model lets you focus on what you want to accomplish rather than how to accomplish it. You are actually already familiar with declarative programming.
When you create a Windows Forms or ASP.NET application and add a button control to a form or page, you focus on aspects like the button's position and text that appears on the button. If you review the code, you are likely to see code like this:
button1 = new System.Windows.Forms.Button();
button1.Size = new System.Drawing.Size(150, 45);
button1.Location = new System.Drawing.Point(30, 15);
button1.Text = "Click Me!";
Notice that the code simply describes the button. The automatically generated code does not get into window handles and drawing contexts, leaving the runtime to handle the details of actually drawing the button and sending click events to your event handlers.
A BizTalk developer describes a message using an XML schema, and declares the location at which the application receives instances of the schema. The developer then describes the processing that takes place when the message arrives: the developer could transform the message, change its attributes, execute rules, and even create new types, all using a declarative model.
At runtime, the BizTalk environment handles the details of receiving messages, routing them to interested applications, and converting the developers' declarations into actions. All of this happens in a type-safe environment that makes it easier to create a technically correct solution (correct in terms of handling types and acting on them - BizTalk cannot, of course, confirm that the actions you take are correct).
BizTalk developers can also write code within the BizTalk environment using XLang/s, a language that is modeled after C#. Writing code in XLang/s often involves actions like message assignment, creating instances of objects, and invoking class member functions. You can use more advanced functionality using statements like
if; however, this is not strictly necessary since the orchestration designer's purpose is to make it easier to express these statements using orchestration shapes like Call Orchestration, Loop, and Decision.
I alluded to BizTalk's extensibility in the discussion about XLang/s - the next section goes into some more detail.
Understanding BizTalk Extensibility
BizTalk's programming model is largely based on orchestrations that, when used in combination with maps, for example, usually provides enough functionality for a range of problems. There can be cases when it is either difficult *or not possible* to represent a solution using BizTalk's stock toolset.
BizTalk developers can extend BizTalk functionality using C#, Visual Basic .NET, or any .NET-supported language. You package your code in an assembly (DLL), or Class Library project in Visual Studio .NET, and reference it from your BizTalk project in Visual Studio, like you reference any other assembly (Select Project -> Add Reference from the Visual Studio menu).
You can access your assembly's functionality using an Expression shape from the Orchestration designer toolbox.
On hearing the great news, most developers fire-up Visual Studio and happily start writing a bunch of code. (After all, BizTalk uses a declarative approach. If you like code, it is hard to resist an opportunity to be in control again by writing your own code.) Before you do that, make sure that you really cannot express your proposed solution in BizTalk.
When I was learning C++, I got stuck on several problems along the way. I often found myself late at night sitting in front of my noisy 486-based system - its 200MB hard drive spinning the bits of my solution at the same dizzying rate that I was going through ideas to try to solve my problems. On further reflection about the problem at hand, I found that I was standing in my own way - I was not able to find solutions to the problems because my approach was wrong. I ignored the symptom (not being able to solve the problem), and instead focused on finding a solution. I easily came up with an effective solution the moment I changed the way I thought about the problem!
My point is that I see a lot of developers immediately creating new assemblies, writing a bunch of code, and then calling that code through BizTalk. The presence of the code is often a symptom of not understanding the problem, understanding BizTalk, or both.
You need to keep this in mind if you still need to write some code:
- All of the types you use in your code must be serializable. An example of an object that you cannot serialize is
- You must sign your assembly and deploy it into the GAC (Global Assembly Cache) to be able to call it from your BizTalk solution.
- Since your assembly is in the GAC, you may have to think differently about using configuration values from a config file.
These points are not as bad as they seem. I'll address the first two and leave the last one for you to figure out for your homework.
The first point, about using serializable types, is easy to address: avoid using non-serializable objects! The great thing is that this is pretty easy to do since most types you use day-to-day are, in fact, serializable.
If you accidentally use a serilaizable type, or cannot avoid using one, you might be tempted to use some unconventional approaches. For example, if you look around the internet, you might find some interesting ways to work around this by tricking the type system into serializing a non-serializable type - use those techniques with extreme caution.
You have to mark your types (classes) as serializable for BizTalk to accept them - just add
[Serializable] to your class' declaration. The compiler will gently remind you with a cryptic error message if you lie and use non-serializable types anyway.
The second point - you need to sign your assembly and deploy in the GAC - is also really easy to address. Signing in this sense is actually Strong Name-ing your assembly. You can use the Strong Name Utility (sn.exe), or use Visual Studio to sign your assembly. Deploying the signed assembly is also easy: just drag the assembly to the c:\windows\assembly folder (it goes there as a copy), or command line enthusiasts - use can use gacutil (gactul.exe).
Note that I will say that I have oversimplified the management aspect of strong naming and deploying assemblies into the GAC. Those topics are out of the scope of this particular article. Let me know if you'd like to see an article about that.
The great feature of both of these points is that these procedures build on your knowledge of the .NET Framework, so there is not much more for you to learn if you are already familiar with these tasks. If you are not familiar with these tasks, then you'll gain a deeper understanding of the .NET Framework.
Although you can do just about anything you like in your custom assembly, you should carefully consider the performance impact of your code. For example, loading a huge XML document into an
XmlDocument object will use a lot of memory, which can slow the overall performance due to paging. I personally like to keep my custom code as lean as I can: I use
StringBuilder, streaming types, I try to use math whenever I can, and use compact representations of data even if that makes my code a little more complicated. The classic rule still applies - avoid optimizing too early and without knowing whether it is necessary; however, if you know that you are processing very large messages, then it makes sense to avoid operating on them entirely in memory.
BizTalk Builds on What You Already Know
Although I have drawn many parallels between Windows programming using the .NET Framework and working with BizTalk, it should be clear at this point that you can leverage a lot of what you already know when you start working with BizTalk.
If you review everything you just read, you will see that I have not introduced any new concepts to most developers with even some programming experience.
So far, I have discussed BizTalk theory - now it's time to put that knowledge to use.
Content Based Routing Using an Orchestration
A classic sample BizTalk application demonstrates the orchestration engine because the orchestration designer is interesting to look at and makes it easy to understand how the solution works. Since BizTalk is so flexible, other, less obvious, approaches are possible too, and these less obvious approaches offer more features over the simpler ones.
One classic example of a solution built using a message-oriented system like BizTalk is content based routing. Content based routing (CBR) inspects a message for certain content (perhaps a specific value in a certain field) and routes the message to one out of possibly several destinations. CBR is like a C#
switch statement: execute a particular case clause based on the result of evaluating the condition in the
The sample application that I'll demonstrate looks like this:
This sample demonstrates several core features:
- Declarative programming
- Type safety
The idea is simple: Accept a message, transform the message into another type, and send the message a destination based on the value in the
There are three variations of the sample:
- Transform and Route using an orchestration (I demonstrate this technique here)
- Transform at the Receive Port and, using an orchestration, route to the destination
- Without orchestrations - accept a non-routable message, transform, and route
All three solutions demonstrate BizTalk's Publish-Subscribe model; however, the last version (the one that does not use orchestrations) highlights Publish-Subscribe since it is based purely on port configurations (that are backed by BizTalk's Publish-Subscribe model).
I'll walk you through the solution first - skip to the Installation and Use section if you are impatient.
The demonstration begins by accepting a specific type of message (XML instance document), transforms the message into another type, inspects the message, and decides where to send the new message (the message can end up in one out of two places).
A sample of the input message type is:
Based on what you have learned so far, the input message's type is: http://BizTalkSample_CbrMain_wWorkflow...#CbrSampleMain (combination of namespace and name of the root node). You trigger processing by copying one of the sample files into the FileDrops\Inbound folder. The File adapter reads the contents of the file and passes it onto a pipeline. The pipeline confirms that the file contains a message type that our solution can accept, and forwards it to the logical port called
The logical port serves as binding point for an adapter like the File adapter. You could change the adapter to MSMQ without having to change or redeploy the solution.
The Receive shape, rcvMainInbound, triggers the orchestration because it is an Activating receive. The shape that follows is a Construct Message which in turn contains a Transform shape. The Construct Message shape tells BizTalk that the orchestration is creating a new message type using the shape(s) that it contains. BizTalk ensures, at compile time, that the orchestration does, in fact, create the message type it declares.
The Transform shape invokes a Map (which is really a compiled version of an XSL) that transforms the original message into a new format. The new format has a structure that is similar to the original message, except that the names of the nodes and namespace have changed:
A Decide shape follows - its role is to route the new message to one of two places. If the RouteTo node contains "A", the message gets delivered to the sndDestA Send shape, otherwise the message gets delivered to the sndDestB Send shape. Each Send shape is bound to its own logical send port. Each Send port is bound to a Send port that uses the File adapter to deliver its message to its output folder within the FileDrops folder.
The Decide shape inspects the value of the RouteTo field using an alias or synonym which is referred to as a Promoted Property. A Promoted Property is a special kind of alias used to describe a location in an XML document (known as an XPath statement). There is another type of alias called a Distinguished Field that behaves in a seemingly similar way to a Promoted Property (there is a significant difference though). You are not limited to using these aliases to inspect values in an XML document - you could use the BizTalk
xpath function to check the value.
If you wanted to use the
xpath function, the call would look something like this:
testValue = xpath(Inbound,
[local-name()='RouteTo' and namespace-uri()='']/)");
I think the expression in the decide shape (which uses the Promoted Property) is easier to read:
Outbound(BizTalkSample_CbrMain_wWorkflow.PropertySchema.RouteTo) == "A"
One thing you might have noticed is that the orchestration does not validate the input message - so what happens when you send the wrong type of file to the orchestration?
BizTalk will only activate the orchestration when the correct type of message appears at the receive location. BizTalk reads all files that appear in the Inbound folder, but sends only valid files to the orchestration. A valid file is one that contains an XML document that has the http://BizTalkSample_CbrMain_wWorkflow...#CbrSampleMain message type. XML documents that are not of the correct type get consumed and end up being deleted - BizTalk also logs an error in the Application Event Log.
Installing and Using the Sample
Installation is simple. I assume the following:
- Your system's main drive is drive C
- You have BizTalk Server 2006 installed on your system (local)
- BizTalk Server 2006 works
- You have Visual Studio 2005 installed and working
Your system is ready if you have successfully worked with the BizTalk SDK samples or some BizTalk labs on your system. If you have not done either of these things, try the BizTalk SDK Sample called HelloWorld - you are in great shape if that sample works without changing anything.
- Download and unzip the ZIP file to your system's C:\ folder. The unzip process creates a new folder called C:\Samples\wWorkflow.
- Using a Visual Studio Command Prompt, navigate to the solution folder by typing the following command:
- Now, type the following command to setup and start the solution:
- You'll see a lot of messages scrolling by - inspect the output for errors.
The solution will be running if everything went well.
- The BizTalkSample-CbrMain-wWorkflow\FileDrops folder contains two sample files (they both begin with "NonRoutableMessage"). Copy (be careful not to Move) one of the files to the Inbound folder.
BizTalk should pickup the file within a minute, and a new file should appear in the DestinationA or DestinationB folder (depending on which file you copied).
If the solution does not work, or you are impatient, you can read through a sample output file by opening RoutableMessage-Main_output.xml.
Remove the solution by doing the following:
- Click the following on your Start menu:
Start - All Programs - Microsoft BizTalk Server 2006 - BizTalk Server Administration
- Open the BizTalk Server 2006 Administration Folder.
- Open the BizTalk Group folder.
- Open the Applications folder.
- Find the CbrSampleMain folder and right-click it.
- Select Stop.
- Select Full Stop from three options.
- Click Stop.
- Using a Visual Studio Command prompt, navigate to the solution folder by typing the following command:
- Now, type the following command to setup and start the solution:
You should not see any messages in red. If you do, try steps five to ten again.
The next article in this series will demonstrate the same type of solution; however, it will push the transformation of the inbound message to the Receive Port so that the orchestration only works with the routable message type. The final version removes the orchestration completely - instead relying only on port configuration.
As always, I am interested in your feedback. Post here, rate my article, and I would appreciate a link to my site (http://blog.wWorkflow.net or http://wWorkflow.net).
- Created June 11 2008. This article is perfect - there won't be any further revisions ;)