Many integrations are based on pure messaging scenarios, that is, they do not need Orchestrations. They consist of receiving a message through an adapter, applying some form of transformations to the message, routing it to one or more subscribers, and sending them out again, using the same or another adapter. They might also require a response. In cases where that response is synchronous, and the ports are con fi gured with the request-response message exchange pattern, this can be handled without an Orchestration. However, as soon as you have an integration that implies more than one logical step, you use an Orchestration.
It is usually stated that Orchestrations exist to coordinate business processes. I would drop the word “business” from that. In a nutshell, the Orchestration engine is the work fl ow engine employed by the BizTalk Server to allow you to handle various processes, whether they have their roots based in business or technology. Orchestrations are based on the C#-like language named XLANG/s. Though you sometimes resort to writing XLANG/s statements directly, you most often work with modeling your process using Orchestration shapes and setting properties.
Orchestrations, and the executable processes they implement, are modeled using a sequence of shapes. Each shape has a distinct meaning and usage. The shapes can be divided into five areas, as follows:
The available shapes are the ones you have to work with. Orchestration shape is not an area of extensibility. You do, however, like with the Scripting Functoid for Maps, have a way of writing code or calling external components to perform processing. In Orchestrations, this has the form of the Expression shape.
Within this category, there are shapes that help to receive, send, construct, transform, or assign message variables as follows:
table 1
Some shapes require nesting, such as the Assign and Transform shapes, which always need to be put into a Construct shape, as shown in the following diagram:
Containers are shapes that, either visually or technically, group other shapes, as follows: table 2
Since Orchestrations model processes, and processes are much about the fl ow of messages, there are many shapes used to handle that fl ow, as follows:
table 3
Orchestrations can be nested and called from other Orchestrations, similar to methods in .NET. The shapes that control that are as follows:
table 4
These shapes are dynamic and either allow for advanced message processing, decision making, or actions through calling Business Rules, or allow for making arbitrary XLANG/s statements through calling .NET helper components. The shapes are as follows:
table 5
More information about the limitations and structure of the XLANG/s language can be found at http://msdn.microsoft.com/en-us/ library/aa577463(v=BTS.70).aspx.
Orchestrations can be activated in one of two ways: by message publication to the MessageBox, fulfilling the Orchestrations activation subscription, as specified by the activating Receive Port and its binding option, or through their being called from another Orchestration. This activation process is not arbitrary. Instead, you need to determine how an Orchestration should be activated when you design it.
An activating Receive shape is used when the Orchestration is fi rst constructed. It is fulfi lled by a message publication matching the activation subscription. This port can be of any binding type. The two main differentiators from any other port in the Orchestration are as follows:
In this case, the Filter criteria for subscription has not been set explicitly. We will examine when it is needed and when it is not, later in this chapter, as we discuss port binding options.
Call or Start Orchestration is used when an Orchestration is used in the same way as a .NET method, that is, when it is called from another Orchestration directly using design-time coupling. Parameters are used to relay information. Such parameters might be variables, ports, messages, and so on.
Call is a direct synchronous instantiation that does not rely on message publication. It waits for the called Orchestration to complete and then returns the control back to the caller. Start is a fire-and-forget style asynchronous instantiation that uses message publication. A called Orchestration can return a response in the form of out or updated reference parameters, while a started Orchestration cannot return a result through parameters to its starter. However, it can use ports to receive a result.
Persistence
During the execution of an Orchestration, the state of the process is saved, or persisted. This enables the Orchestration to recover from failures and retry or restart from a previous point of execution.
Persistence may occur at the following occasions:
Persistence and serialization of the entire Orchestration, including all messages, variables, and state information, brings with it the requirement that everything used within an Orchestration must be serializable.
If a class used within an Orchestration is not serializable, you must use it within a transactional scope marked as atomic.
Persistence also enables dehydration and rehydration , saving on precious processing resources by removing Orchestration from active memory and serializing it to the database awaiting its next step (dehydration), for example, the correlation of a response message.
Once that event occurs, usually in the form of a message being published to the MessageBox., the Orchestration is rehydrated and processing is continued.
The scenarios in which dehydration is considered by the engine are as follows:
The algorithm that the engine uses to determine dehydrations is based on the last 10 delays at that point in the Orchestration, and compared with a runtime calculated value, that differs depending on available resources and other factors, but is between a configurable minimum and maximum time (that, by default, is 0 and 1800 seconds respectively).
Orchestrations employ the use of transactions to compose operations in units or work, isolated from others, and to recover from failures. Transactions in BizTalk Server can be either Long Running or Atomic.
Long Running transactions are Long Running units of work for which you want to have the ability to define custom compensating logic and exception handling, or those that need to serve as an umbrella for nested transactions. Long Running transactions persist state, and send operations are committed to the MessageBox and seen by subscribers immediately.
Atomic transactions are transactional, and follow the Atomicity, Consistency, Isolation, and Durability (ACID) rules. Either everything within the transaction is correctly committed, or none of it is. The persisted state of the Orchestration is either the state before the transaction began or the state after all operations are committed. The changes performed by any operation during the transaction, such as a message being published to the MessageBox, is not visible to anyone during the transaction, but only after commit. Any changes, once committed, are persisted so that they are available, even if the system fails after the transaction is committed.
Read more on the ACID rules of transactions at the following URL: http://en.wikipedia.org/wiki/ACID#Characteristics
Scopes are the way to handle transactions within the Orchestrations. All scopes have the following properties:
Synchronized scopes ensure that the data being read is not simultaneously written to by other branches in a parallel shape. Scopes are, by default, not synchronized, though Atomic scopes are implicitly synchronized, regardless of the property value.
A scope can be marked as transactional by the Transaction Type property being set to either Long Running or Atomic. The third option for the Transaction Type property is None, as shown in the following screenshot:
When configuring the Long Running Transaction Type, the following additional properties (over a non-transactional scope) will become available:
code 1
Since the expression is using a static method, no variable of type ADHelper is required, and the method can be called outside an Atomic scope, even if the class is not marked as serializable.
The default Isolation Level is Serializable.
Long Running transactions can contain other transactions, either Long Running or Atomic. Atomic transactions can contain no other transactions.
Conceptually, when it comes to transactions and nesting, you can look at the Orchestration level as a scope, that is, the Orchestration can be marked as a transaction in the same way as a scope. If you want to put an Atomic transactional scope directly inside the Orchestration, then the Orchestration needs to be con fi gured as Long Running.
Another important concept about transactions in BizTalk Server is their reach. Transactions initiated in Orchestrations end in the MessageBox. This means that marking a scope as Atomically transactional does not allow you to have a transactional conversation with the intended recipient of the message through the MessageBox from within the Orchestration. The reach of a transaction is depicted in the following diagram:
As the diagram shows, it is possible to extend the reach of a transaction from an Orchestration to a COM+ (Enterprise Services-managed) component.
Many Orchestrations may rely on con fi guration parameters. There are different ways of supplying configuration to an Orchestration. We will examine some of these and look for the pros and cons.
Orchestration variables are a very static place to have con fi guration values. If variables point to a class, the default constructor of that class can be called automatically to instantiate the variable. If anything other than the default constructor is called, this needs to be done in an Expression shape. Also, when Orchestrations are called or started, the caller can supply the initial values for parameters. However, they have to originate from somewhere.
The BTSNTSvc.exe file is an executable file used by all BizTalk in-process Host Instances. As a .NET executable, it reads its configuration from the BTSNTSvc. exe.config file at startup. It is possible to place custom configuration into that file. The issue with this approach is that any addition or change to a configuration value requires the Host Instance to be restarted. Since the introduction of 64-bit processes, there is also a BTSNTSvc64.exe file with a corresponding con fi guration fi le. This requires confi guration to be duplicated in two places (and on as many BizTalk Servers as there are in the group). Also, any con fi guration property supplied in this file is not available to the isolated Hosts, though that is not an issue with Orchestrations, since they only run in process. Accessing files under the Program Files folder might also be restricted in some organizations.
For Isolated Hosts, it is possible to place configuration in web.config, in the directory of the web service being called. In the end, this is just a bad practice resulting in many configuration duplications and maintenance challenges, not to mention confi guration being overwritten and removed if the service is republished.
Configuration in machine.config solves the issue of having different places for in-process or isolated Hosts. There is still the issue of whether to choose 32- or 64-bit, which will have their machine confi gs in C:\Windows\Microsoft.NET\ Framework\v4.0.30319\Config\machine.config and C:\Windows\Microsoft. NET\Framework64\v4.0.30319\Config\machine.config, respectively. Also, as with BTSNTSvc.exe.config, if your BizTalk environment consists of more than one server, you will need to apply settings to all machines. machine.config settings are also only read when the process is initiated, so this placement also requires Host restart for updates or new additions. Accessing the machine.config fi le is also often restricted in many organizations.
Specifically, WCF extension configuration can be placed in the Send and Receive Handlers for the WCF-Custom adapter.
Configuration values can be sent in as part of the message. It is not uncommon to determine the outcome of a process, based on the content of the message. However, sending in pure configuration values through the message is uncommon.
Configuration values can be part of the message context. A common place to con fi gure values to be placed in the context is through the use of a custom Pipeline component, whose job is to write (or promote) the appropriate values to the context. Configuration can then be done in the Pipeline on a per-instance runtime con fi guration. The downside of this is that Orchestrations that can get their messages from more than one Receive Location must have those properties con fi gured in all the locations. Also, more than one value (that is, either two Pipeline components or an un-typed one) needs to be put into the context, where it is hard to keep track of the format for inputting con fi guration values.
The ESB Toolkit uses a variation of this approach where the “itinerary” is included in the message context.
For configuration values that change often or for those you would like an out of the box-versioned user interface for, Business Rules are a good choice. They are centrally stored in the database, and as such are available on all machines to all types of Hosts. Business Rules can be, in some cases, a cumbersome addition to the solution just for the sake of configuration properties from some perspectives, but they are de fi nitely a good viable option. There are also Application Programming Interfaces (APIs) available in the form of the Call Rules Orchestration shape that allows you to call Business Rules easily.
Single Sign-on (SSO) can be used as a centralized data store for configuration values. Besides storing user account mappings, it also stores custom con fi guration for adapters and can be used for secure storage of custom confi guration for custom logic, as well. Although there are no easy, out of the box options for using SSO this way, there are samples in the documentation and tooling available from the BizTalk Community that makes this relatively easy.
If you decide to use a .NET helper component to store and retrieve your con fi guration, then you can get the con fi guration from anywhere, say a fi le or a database. File storage will have its drawbacks, but it is certainly possible. In many cases, using a custom component may seem easy, but you should strive to use built-in functionality and features wherever possible, if you want to minimize maintenance costs.
Sometimes there are methods or logic contained within .NET helper components that you would like to use from within an Orchestration. Even though there is no option to call an external assembly, like with the Scripting Functoid, doing so is easy. It requires an assembly reference added to the project, a variable of that type, and an Expression shape. The following are the steps required to call a .NET assembly from an Orchestration:
For Atomic transaction, the Timeout value indicates the amount of time that passes before the transaction is marked as failed and is rolled back, but only if it was coordinated in a transaction, together with another resource, by the Distributed Transaction Coordinator (DTC).
The Retry value indicates whether PersistenceException (caused by database connectivity issues) and RetryTransactionException (explicitly thrown in the Orchestration) should cause the transaction to be retried. Only these exceptions wil be affected by the Retry flag. All other exceptions will cause the transaction to fail.
Isolation levels control the locking levels used in the database by the engine while dealing with reads and writes for the actions performed by shapes in the scope. These transaction levels are available as follows:
For Atomic transaction, the Timeout value indicates the amount of time that passes before the transaction is marked as failed and is rolled back, but only if it was coordinated in a transaction, together with another resource, by the Distributed Transaction Coordinator (DTC).
The Retry value indicates whether PersistenceException (caused by database connectivity issues) and RetryTransactionException (explicitly thrown in the Orchestration) should cause the transaction to be retried. Only these exceptions wil be affected by the Retry flag. All other exceptions will cause the transaction to fail.
Isolation levels control the locking levels used in the database by the engine while dealing with reads and writes for the actions performed by shapes in the scope. These transaction levels are available as follows:
Compensation can be Default or Custom. Setting it to Custom has the same effect as selecting to add a new Compensation Block to the scope.
The Timeout property specifies the amount of time spent in the scope before TimeoutException is raised.
While configuring the Atomic Transaction Type, the following additional properties (over a non-transactional scope) will become available:
Compensation can be Default or Custom. Setting it to Custom has the same effect as selecting to add a new Compensation Block to the scope.
The Timeout property specifies the amount of time spent in the scope before TimeoutException is raised.
While configuring the Atomic Transaction Type, the following additional properties (over a non-transactional scope) will become available:
At Packt, we are always on the lookout for innovative startups that are not only…
I remember deciding to pursue my first IT certification, the CompTIA A+. I had signed…
Key takeaways The transformer architecture has proved to be revolutionary in outperforming the classical RNN…
Once we learn how to deploy an Ubuntu server, how to manage users, and how…
Key-takeaways: Clean code isn’t just a nice thing to have or a luxury in software projects; it's a necessity. If we…
While developing a web application, or setting dynamic pages and meta tags we need to deal with…