Developing BizTalk Artifacts — Creating Orchestrations

16 min read

Orchestrations

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.

Basic shapes and configuration

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:

  • Message and Data Handling
  • Containers
  • Flow Control
  • Orchestration Nesting
  • Other
  • 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.

    Message and Data Handling

    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

    Containers are shapes that, either visually or technically, group other shapes, as follows: table 2

    Flow control

    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

    Orchestration Nesting

    Orchestrations can be nested and called from other Orchestrations, similar to methods in .NET. The shapes that control that are as follows:

    table 4

    Other

    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.

    Orchestration activation

    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.

    Activating Receive

    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:

    1. The port is triggered by an activation subscription, based on design-time-determined filter criteria .
    2. The Receive shape connected to the port is marked with Activate set to True, as shown in the following screenshot:

    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 and Start

    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:

    • After the execution of a Send Port
    • After the execution of a Start Orchestration shape
    • After the successful execution (commit) of a transactional scope
    • When the Orchestration instance is suspended
    • When the Orchestration instance is completed
    • When the Orchestration engine shuts down gracefully
    • When a debugging breakpoint is hit
    • When dehydration is determined appropriate by the engine

    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.

    Dehydration and rehydration

    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:

    • When the Orchestration instance is waiting for a response message
    • When the Orchestration is listening for a message using the Listen shape
    • When the Orchestration engine determines that it has reached an idle delay threshold

    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).

    Transactions

    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.

    Transaction types

    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

    Scopes are the way to handle transactions within the Orchestrations. All scopes have the following properties:

    • Synchronized
    • Transaction Type

    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:

    Long Running

    When configuring the Long Running Transaction Type, the following additional properties (over a non-transactional scope) will become available:

    • Compensation
    • Timeout
    • Transaction Identifier
        • Compensation
        • Isolation Level
        • Retry
        • Timeout
        • Transaction Identifier
            • Read Committed: It reads only committed rows and prevents reading changes that are not yet committed by other transactions, but it does not prevent data it has read from being changed by other transactions before it has completed.
            • Repeatable Read: It prevents updates to rows read by this scope until the transaction is completed.
            • Serializable: It prevents data being committed by other transactions in such a way that queries used by this transaction would give a different result than when executed.
                1. Create a .NET assembly. In this sample, we will use a Helper component that uses directory services to fi nd the full name of the sales representative that created a sales order for a car. The ADHelper class is contained in the Chapter04-Example01.ClassLibary project. The code looks as follows:
                2. code 1

                3. Create an Orchestration that will call the assembly. The Orchestration SalesOrderProcess is implemented in Chapter04-Example01. Orchestrations in Chapter04-Example01.sln, for this sample, look similar to the following screenshot:
                4. The expression in the CreateSOOut Message Assignment shape looks similar to that in the following screenshot:
                5. 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.

                6. Build the solution.
                7. GAC the Chapter04-Example01.ClassLibary assembly, so that it can be located and used from the BizTalk Server.
                8. Deploy the Orchestration.
                9. Create ports. For simplicity, a Binding File is located at C:\BTS2010CertGuide\Chapter04\Example01- Orchestrations\ BTS2010CertGuide-Ch02- Orchestrations.xml.
                10. Con fi gure the Orchestration.
                11. Start and test the Orchestration.
              • The default Isolation Level is Serializable.

                Nesting

                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.

                Transaction reach

                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.

                Storing configuration information

                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

                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.

                Configuration placed in BTSNTSvc.exe.config

                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.

                Configuration placed in web.config for isolated Hosts

                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 placed in machine.config

                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.

                Some configuration can be placed on the Adapter handlers

                Specifically, WCF extension configuration can be placed in the Send and Receive Handlers for the WCF-Custom adapter.

                Through the message

                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.

                Through the message context

                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.

                Business Rules

                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.

                SSO

                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.

                Using a .NET helper component

                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.

                Integrating with .NET assemblies

                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

            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

            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.

        Atomic

        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.

        Atomic

        While configuring the Atomic Transaction Type, the following additional properties (over a non-transactional scope) will become available:

    Packt

    Share
    Published by
    Packt

    Recent Posts

    Harnessing Tech for Good to Drive Environmental Impact

    At Packt, we are always on the lookout for innovative startups that are not only…

    2 months ago

    Top life hacks for prepping for your IT certification exam

    I remember deciding to pursue my first IT certification, the CompTIA A+. I had signed…

    3 years ago

    Learn Transformers for Natural Language Processing with Denis Rothman

    Key takeaways The transformer architecture has proved to be revolutionary in outperforming the classical RNN…

    3 years ago

    Learning Essential Linux Commands for Navigating the Shell Effectively

    Once we learn how to deploy an Ubuntu server, how to manage users, and how…

    3 years ago

    Clean Coding in Python with Mariano Anaya

    Key-takeaways:   Clean code isn’t just a nice thing to have or a luxury in software projects; it's a necessity. If we…

    3 years ago

    Exploring Forms in Angular – types, benefits and differences   

    While developing a web application, or setting dynamic pages and meta tags we need to deal with…

    3 years ago