In this section, we will get into the details of how itineraries are implemented and used specifically in the ESB Toolkit.
As we mentioned earlier in this chapter, itineraries are just the representation of the different itinerary services that will be triggered along with the execution of the itinerary itself.
In the initial versions of the ESB Toolkit (when it still was called ESB Guidance), there was really limited tooling to create the actual itinerary definition files, but the Toolkit has evolved providing a nice visual designer that really helps to abstract from those lower-level details of how the itinerary definition file is made up.
There are two main XML structures related to itineraries, as discussed in the following sections.
The itinerary model is the XML representation that contains all the information required to describe those itinerary services involved in the itinerary. This is the itinerary representation generated at design time by means of the visual Itinerary Designer in Visual Studio. We will have a deeper look into how we work with itinerary models later in the chapter.
This metadata is the actual instance of the itinerary to be applied to a message at runtime. Its structure is defined by the ESB Itinerary Schema (Itinerary.xsd
) and its contents are driven by an actual itinerary model.
It travels with the message being processed as part of its context and stores the XML representation of the actual state of the execution of the itinerary. The different itinerary services will retrieve and update it in order to reflect how the itinerary processing progresses.
It has three principal sections:
ServiceInstance
: Represents the current itinerary service that is processing the message.Services
: Represents the whole set of itinerary services that make up the itinerary. It stores the information about the execution of any previous itinerary services.Resolvers
: Contains the list of resolvers that will be used by the itinerary services as part of their processing. We will further describe the resolvers' concept later.The following figure shows an itinerary metadata instance of the itinerary model shown in the previous figure:
In order to create an itinerary model, we just need to create a new project of BizTalk ESB Itinerary Designer
type, which by default will contain a brand new itinerary model with the .itinerary
file extension. We will be able to add as many itinerary models to the project as we need.
The following figure shows the first step we take while creating an itinerary. We start off by selecting the BizTalk ESB Itinerary Designer project.
The Itinerary Designer is a DSL (Domain Specific Language) tool that allows us to drag-and-drop the different model elements that define how our itinerary will behave, connecting those as required, and setting up the corresponding properties.
There are different kinds of elements we can use from the toolbox to build our itinerary model:
Some of these element types have different subtypes that imply different characteristics for them (for example, an itinerary service can be a messaging service, an orchestration service, or an off-ramp extender) and which other elements they can be connected to. This is defined on the Extender
property of those elements, as we will see next.
The itinerary services are components that carry out some processing over the messages flowing through the ESB. The basic processing of an itinerary service is as follows:
The three types of itinerary services that we can use in the itinerary model are:
One key ESB Toolkit concept that concerns itinerary services is the Resolution framework that we will explain later in this chapter.
The itinerary on-ramp is a logical representation of the receive port that will initiate the itinerary execution. An itinerary mode can contain only one on-ramp.
The only extender type this element supports is the
On-Ramp ESB Extender
. This extender type has two more properties associated with it that we have to define in order to link the on-ramp with the receive port that will effectively receive the messages to be processed by the itinerary:
The ESB Toolkit already includes two itinerary receiver ports (for both one way and request/response itineraries execution) that cover all the standard ESB message reception scenarios, so we shouldn't need to create our own itinerary receive ports and just use those already defined in the Microsoft.Practices.ESB BizTalk application.
On-ramp is also a logical container that defines the different itinerary services that will process the corresponding message on its way in (Receive Handlers) or on its way out (Send Handlers in case we are talking of a request/response on-ramp). The Receive and Send handlers effectively represent where the messaging itinerary services will be executed, either on the way in or in the way out of the ramp. We will describe further the messaging itinerary services later in the Itinerary Services section.
The itinerary off-ramp is a logical representation of the send port that will send out a message from the ESB as part of the itinerary execution. An itinerary model can contain one or more off-ramps.
The only extender type this element supports is the Off-Ramp ESB Extender
. This extender type has two more properties associated with it that we have to define in order to link the off-ramp with the send port that will effectively send the messages to the target system:
The send ports that are associated with the off-ramp need to be configured with the appropriate subscription filters, so that they receive the messages they should process. The filter required on an itinerary service is made up of at least three different elements that are the BizTalk message context properties it will filter on:
Microsoft.Practices.ESB.Itinerary.Schemas.ServiceName
property has a value that is the name of the service the port provides.Microsoft.Practices.ESB.Itinerary.Schemas.ServiceState
property value is Pending
, indicating the current itinerary step the message should be processed by is pending.Microsoft.Practices.ESB.Itinerary.Schemas.ServiceType
property value is Messaging
, indicating that the service that should process the message is a messaging service and not an orchestration (we could have the save itinerary service implemented as a messaging and orchestration service)A port that is meant to be used to run an itinerary service should be a dynamic port, so it supports the execution of dynamic end point resolution provided by the routing itinerary service that comes out-of-the-box with the ESB Toolkit. This itinerary service is explained later in the chapter.
The same way as on-ramp, off-ramp is a logical container that defines the different itinerary services that will process the corresponding message on its way out (Send Handlers) or on its way in (Receive Handlers in case we are talking of a request/response off-ramp). These handlers will also be messaging itinerary services within the send and receive pipelines of the port.
The ESB Toolkit Resolution framework is intended to dynamically resolve processing information within the ESB. This adds an extra indirection level in the ESB processing by providing a decoupled manner of directing how information is processed by the ESB, without needing to modify the actual implementation of an ESB process.
An ESB Resolver is responsible of taking some input information (either contained in the resolver connection string or in the message being processed itself), and produce a set of results that can be used downstream to guide the processing of the message. The result of the resolver is called Resolver Dictionary that is just a set of name/value pairs that contain different properties derived from the resolution process. Those name/value pairs can be used by downstream components (like itinerary services or adapters) to dynamically set context properties on the message being processed, or take decisions on how to continue processing the message.
The resolver connection string is made up of two main pieces:
The full resolver connection string would look like the following line:
{moniker}:\{property name}={property value};{property name}={property value}
The resolvers included by default in the ESB Toolkit are (listed using their corresponding monikers):
STATIC
: The results of the resolution are directly defined in the resolver connection string. It's mainly used for endpoint and transformation information resolution. The main properties used with this resolver are:TransportType
: Defines the transport/adapter that will be used to communicate with the target endpoint (for example, FILE, FTP, SMTP, MQSeries, WCF-BasicHttp, WCF-WSHttpor WCF-Custom).TransportLocation
: Specifies the actual address of the target endpoint (for example, web service URL)Action
: The action/operation meant to handle the request on the target endpoint (for example, the SOAP action in the target web service).EndpointConfig
: Sets additional configuration properties for the corresponding adapter. It's a name/value pair's list that contains properties that can be used to further configure certain adapters. We can see the whole list of EndpointConfig
elements that can be used by opening the corresponding Endpoint Configuration property in the resolver (the list depends on the TransportType
value). For example, we can see the list of endpoint properties for the WCF-BasicHttp transport in the following screenshot:TargetNamespace
: The actual namespace to be used on messages sent to the target endpoint.TransformType
: The fully qualified name of the type that implements the transformation that should be applied to the outbound message.UDDI
: The results of the resolution are taken by querying a UDDI registry whose URL is defined in the connection string. The properties used in the connection string define how UDDI should be queried:ServerUrl
: Defines the URL of the UDDI server to query.ServiceName
: Defines the name of the service registered in UDDI that contains the information to be returned as a result of the resolution.ServiceProvider
: Defines the name of the service provider the service we want to resolve is associated with in UDDI.XPATH
: Each result of the resolution is taken from the contents of the inbound message by means of XPATH queries. For example, we could set the TransportLocation
property to be extracted from certain node in the message XML by means of the corresponding XPATH query (TransportLocation=/*[local-name()='OrderDoc' and namespace-uri()='http://globalbank.esb.dynamicresolution.com/northamericanservices/']/*[local-name()='ID' and namespace-uri()='http://globalbank.esb.dynamicresolution.com/northamericanservices/'];
).BRE
: The results of the resolution, and produced by means of the execution of a BizTalk Rule Engine policy. The properties set in the connection string define which policy should be executed:Policy
: Defines the name of the policy that should be executed.Version
: Defines the version of the policy meant to be executed.UseMesage
: Defines if the message is provided to the policy as an input fact to be used during the execution of the policy.BRI
: Similar to BRE, but used to resolve (through a business rule) the itinerary name and version to be applied on a message, by means of the ESB.Itinerary
vocabulary. The properties in the connection string are the same as in the BRE resolver.ITINERARY and ITINERARY-STATIC
: Used to resolve the itinerary to be used to process a message, retrieving it from the itinerary repository as instructed by the name and version defined on the connection string. Both the resolvers use the same connection string properties:LDAP
: Retrieves information from Active Directory objects to populate the resolution results. The connection string properties specify both how the active directory should be queried (for example, filter to be applied to the query), as well as from which properties in the active directory object returned by the LDAP query should be used to retrieve resolution values (for example, with TransportLocation={mail}
we declare that the transport location should be retrieved from the value of the mail property of the active directory object).We can even create our own resolvers to implement any other type of custom resolution we might need.
Now, we will look in detail into the different choices that we have when we add an itinerary service shape into our model.
This type of itinerary service is basically classes that do some processing on the message during the execution of a pipeline.
These components are executed as instructed by the itinerary model by a pipeline component within a specific pipeline that will be used as a receive or send pipeline in a port, so while the message travels through the pipeline, each of these components will receive the message, do some processing on it if required, and hand it over to the next component (or to the message box / corresponding adapter in case it´s the last component of the receive/send pipeline).
The ESB Toolkit includes two pipeline components (ESB Dispatcher and ESB Dispatcher Disassembler) that both take care of executing messaging itinerary services registered in the ESB. There are two services that come with the ESB Toolkit:
You can use these components in your own pipelines, but the ESB Toolkit already includes a series of send and receive pipelines that use those components. Those pipelines are in turn used on the different ports that build up the basic artifacts of the ESB Toolkit (for example, default on-ramp itinerary receive ports) or can be used in our own send and receive ports. There are other pipeline components that can be included in those pipelines that are not really itinerary services, but are involved in the itinerary processing framework itself, or support some other features of the ESB Toolkit. We will list those later in this chapter.
The messaging itinerary services have the benefit that they are quicker to execute (reducing latency) and less resource-intensive than the orchestration-based itinerary services.
To add one of these into the itinerary in the itinerary model designer, you will just drag-and-drop an itinerary service shape and set the Itinerary Service Extender type to Messaging
. You will also select the itinerary service that will be actually executed. As you can see, by default we just see the two services that come with the ESB Toolkit:
By setting the Container
property in the shape properties we will be able to define if the service is meant to be executed in the way in of the ramp (Receive Handlers) or in the way out of the ramp (Send Handlers). You will notice that the shape border changes a little bit from one value to the other (a dashed border for Receiver Handlers and a dotted border for the Send Handlers).
You can also add a resolver to the itinerary service. This one will be used to actually resolve information required to execute the service (for example, resolve the map to be applied to the message).
These types of itinerary services are implemented within a BizTalk orchestration. They follow the same basic process of a messaging itinerary service, but the difference is that they hand over the message for further processing by any downstream itinerary service by means of ports:
The ESB Toolkit provides two out-of-the-box orchestration itinerary services that are the counterparts of the ones provided in the messaging flavor:
You can also implement your own orchestration services just by following the same processing pattern we just discussed.
The orchestration itinerary services add some processing overhead intrinsic to the orchestration execution lifecycle, but have the benefit of being more flexible in terms of composition, and allow us to implement more complex itineraries and itinerary services.
In the Itinerary Designer, you will just drop an itinerary service shape as we did before, but this time we will choose Orchestration
on the Itinerary Service Extender
property. The same way, we will choose the service that will process this itinerary step from those orchestrations that implement itinerary services.
This variant of the itinerary service shape is a peculiar one because these don't actually execute any processing on the message. They are just required by design to define the stage where an off-ramp will be executed as the next step of the process, and so any messaging itinerary services executed within the off-ramp send port pipeline will run.
As we can see in the following screenshot, it just precedes the off-ramp and the messaging service to be executed on the way out of the message:
As we mentioned before, the ESB Toolkit provides a series of pipeline components that either support the execution of itineraries or add extra features to be executed while a message travels through the itinerary, but are not itinerary services as such:
This is the last type of shape that we can add into our itineraries. It's meant to allow us to make decisions on which should be the next itinerary service to execute, so they are some sort of if/switch clause in terms of programming languages.
This shape comes together with another shape, the itinerary broker outport. This is the one that will link the itinerary broker service shape to each of the possible routes the message could take as a next step in the itinerary.
The process to set up a broker service is as follows:
In the following example, we see that we created two outports in the broker service, both of them using the same resolver, but each of them with their own filter.
We could just set the type of the resolver used to CONTEXT
(this one will return as a result of the resolution the collection of context properties of the message) and set filters' expressions to:
GoToService1: //Property[@name='InboundTransportType']='FILE'
GoToService2: //Property[@name='InboundTransportType']!='FILE'
The message would then just be delivered to the corresponding next itinerary service, depending on if it was received from a file port or not.
We went through the main components that build up an itinerary, but to finish it off we need to put them together and look into some other properties we can set in there.
If you click on the design surface outside of any shape, you'll see in the properties pane the properties of the itinerary itself:
3.144.28.70