1. Web Services
The ESB Toolkit ships with a
number of ASMX and WCF web services. We'll review the most important of
those services in the following subsections.
1.1. On-Ramp Services
The ESB Toolkit has been
designed so that you can use any adapter as part of your on-ramps.
However, when you install the toolkit, a number of on-ramps are
installed by default for you. These on-ramps are web services and rely
on WCF and ASMX services that have been deployed into Internet
Information Services (either version 6.0 of 7.0). These services and
their default install locations are as follows:
Each of these four
services has a corresponding receive location in BizTalk. To find these
receive locations, open the BizTalk Administration Console, and expand
the Microsoft.Practices.ESB application. This is the application where
all the ESB components have been installed. In the Receive Locations
folder, you will see a receive location set up around each of these web
services.
You use one-way services if
you simply want to fire a message into the ESB without waiting for a
response. Two-way services are for request-response scenarios.
If you open the WSDL for the one-way on-ramp (found at http://localhost/ESB.ItineraryServices/ProcessItinerary.asmx), you should notice two things. First, you should look at the SubmitRequest operation that is defined. A section of the WSDL that defines this operation is shown here:
<SubmitRequest xmlns="http://microsoft.practices.esb">
<Root xmlns="http://schemas.microsoft.com/BizTalk/2003/Any">xml</Root>
</SubmitRequest>
SubmitRequest is the method you will use to submit a one-way message into the ESB, and it is expecting a single parameter (defined by the Root node). As you can see, the Root node is defined using the Any type. The Any
type allows you to submit any valid XML. This aligns with our goal of
setting up a generic on-ramp that will receive multiple messages.
The second thing that you should notice within the WSDL is the <soap:Header>
node. This node has a number of elements that are designed to contain
an itinerary for the message that you are submitting. To submit a
message to this web service, you need to include the message itself and
also include itinerary information into the SOAP headers.
1.2. The Transformation Web Service
We have presented the ESB Toolkit somewhat as a "whole"—a fully
functional solution that has multiple parts that all work together to
achieve the ESB vision. However, many of the components within the ESB
Toolkit can be used completely on their own. One of these components is
the Transformation Service, which exposes BizTalk's underlying mapping
engine.
There are many times and
situations where someone might want to use BizTalk's mapping engine
only without having to worry about the rest of the BizTalk or ESB
components. If all you want to do is transform some data, then why would
you care about on-ramps, resolvers, itineraries, and so on? In fact, it
would be really nice to be able to invoke the mapping engine directly,
and it would be really nice to avoid having to post a message into
BizTalk's Messagebox.
Interestingly enough, it is
entirely possible to invoke the mapping engine directly. BizTalk's
mapping engine can be called directly via its APIs, so there is no
reason why you cannot expose a web service that exposes these APIs to
other applications. The Transformation Service that ships with the ESB
Toolkit does precisely that. You can use this web service to access the
BizTalk mapping engine directly in memory without having to submit a
message into BizTalk at all. There is then no need for a receive port
and no need for the message to be submitted into the Messagebox.
The Transformation Service is
exposed as a basic ASMX web service and as a WCF service. On a default
install of the ESB Toolkit, these services will be located at http://localhost/ESB.TransformServices/TransformationService.asmx and http://localhost/ESB.ResolverServices.WCF/ResolverService.svc, respectively.
The ASMX version of the service exposes the following WSDL:
<soap:Envelope xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Transform xmlns="http://Microsoft.Practices.ESB.TransformServices/">
<message>string</message>
<mapName>string</mapName>
</Transform>
</soap:Body>
</soap:Envelope>
You can see from this WSDL that the service accepts two parameters, message and mapName.
To execute a map, you simply pass in your message as a string in the
first parameter while including the fully qualified name of the BizTalk
map in the other. The transformed message will be returned as a string.
You also have the option of
invoking a WCF service, which does the same thing as the ASMX-based
service. The following code outlines how you can call the WCF-based
service to perform a simple transformation. In this example you pass in a
string (containing the data you want transformed) and the name of the
BizTalk map that you want to execute to the client.
Transform() function. The transformed message is returned as a string.
private string CallTransformService(string inputText)
{
try
{
string sOutput;
//Create a new instance of the service client
TransformationServiceClient client = new TransformationServiceClient();
//Use a fully qualified map name as defined in BizTalk
string sMap = "GlobalBank.ESB.TransformServices.Maps.
CanonicalOrder_To_OrderConfirmation,GlobalBank.ESB.
TransformServices.Maps, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=c2c8b2b87f54180a";
sOutput = client.Transform(inputText, sMap);
client.Close();
return sOutput;
}
catch (Exception ex)
{
// Handle Exception
}
}
1.3. The Resolver Service
When we introduced the
resolver concept earlier in the article, we said that resolvers are
invoked by ESB services when they need to retrieve their configuration
information. However, ESB services are not the only components that can
access the resolver mechanism. Any application can access the resolver
mechanism using the Resolver service. Like most of the ESB web services,
there are ASMX and WCF versions of this service.
In a default installation, the ASMX version is located at http://localhost/ESB.ResolverServices/Resolverservice.asmx, and the WCF version is located at http://localhost/ESB.ResolverServices.WCF/ResolverService.svc.
We are not going to dive too
deeply into the Resolver service other than to say that it exists and
the ESB Toolkit contains a detailed example on how to use it if you are
interested in learning more. You can find this example at
C:\Projects\Microsoft.Practices.ESB\Source\Samples\ResolverService if
you have installed the toolkit to the default location.
The one thing that you should be
aware of is that the Itinerary Designer relies on this service. The designer uses it to
test resolvers that you have configured in your itineraries, and it
allows you to see the data that one of your resolver will return once it
is put into the live ESB environment. This is an incredibly handy tool
for you to have as you are designing and debugging itineraries.
2. Schemas
We have mentioned several times
that the ESB components do not rely on schemas to define the structure
of the messages they are processing. However, there are in fact some
schemas used in the ESB Toolkit for other reasons. System-Properties.xsd
is a property schema that defines a list of context properties that are
used extensively through the ESB. For sake of simplicity, we will refer
to all of these properties collectively as the ESB context properties, and Table 15-2
describes each of them. The properties are critical to understand
because they form the backbone for how messages are passed between the
ESB components inside of BizTalk.
Table 1. ESB-Specific Context Properties
Property | Description |
---|
ServiceName | This is a string that holds the name of the current service that needs to process the message next. |
ServiceState | This is a string that holds the state of the current service. It is either Pending or Complete. |
IsRequestResponse | This is a Boolean that indicates whether the current service is a two-way or one-way service. True indicates a two-way service. |
ServiceType | This is a string that indicates whether the current service should be processed by a messaging component or an orchestration. |
ItineraryHeader | This is a string that holds a copy of the entire itinerary. |
CurrentServicePosition | This
is an integer that indicates which position the current service holds
within the overall itinerary (this is, is it the first service, second
service, and so on). |
The first property to look at is ItineraryHeader.
This property will hold the itinerary that is associated with this
message for the entire time that the message is inside of BizTalk.
If you remember back to the "Mediation Policies (Itineraries)" section of this article where you looked at an actual itinerary, you'll remember that you saw an XML node named <Service>. This node has a number of attributes that we said you should be aware of: name, type, isRequestResponse, state, and position.
Looking at these, you can see that they line up fairly closely to the
context properties defined in System-Properties.xsd. This is no
coincidence. The ItineraryHeader property
is used to hold the entire raw XML of the itinerary. However, BizTalk
components are not really set up to work with raw XML. Therefore, key
data from the itinerary is extracted and placed into the other ESB
context properties so that the BizTalk components can easily access it.
By moving this information into context properties, it allows you to
route your message between the various ESB services using BizTalk's
publish and subscribe mechanism.
In the "Mediation Policies (Itineraries)" section, we also mentioned that when each ESB Service completes its unit of work, it asks the ItineraryHelper component to update
the itinerary and to identify the next service that needed to be
executed. What we did not mention is that when this next service is
found, its corresponding XML data is written to the message's ESB
context properties, and the old values are overwritten.
This idea that pieces of the
larger itinerary are continually being extracted and stored within the
message's context properties is important to grasp if you are going to
understand how the overall itinerary processing mechanism works. The raw
itinerary is always stored in the message's ItineraryHeader
property and can be accessed at any time if needed. As a message flows
into the ESB, data from this XML-based itinerary is extracted and
inserted into specific context properties. BizTalk's publish and
subscribe mechanism then routes the message to whichever ESB component
has a subscription that matches the values contained in the context
properties. As each ESB component completes, it updates the itinerary.
Updating the itinerary involves retrieving the next service from the
overall itinerary and writing its information into the context
properties (thereby overwriting the old values). Once the context
properties are updated, the newly modified message is dropped back into
the BizTalk Messagebox, and the publish and subscribe mechanism runs and
again routes the message to an ESB service. This process continues
until all of the services in the itinerary have been completed.
The process we've just
described is how messages are routed through the ESB and across the ESB
services. This process provides you with a mechanism for loosely
coupling together ESB services and ESB components at runtime.
One point to note is that components inside the ESB define subscriptions to messages based on these properties and only
these properties. As you begin to use the ESB Toolkit, you are going to
want to create your own orchestrations or send port to extend it, and
you must make sure that you follow this principle so that your new
components will play nicely with the out-of-the-box ones.
3. The Itinerary Database
Not long after a
developer creates their first itinerary, they will likely start to
wonder about how they can version, store, and manage it. If you have a
large ESB environment, it might potentially have to process thousands of
messages and use hundreds of different itineraries. In this scenario,
you will obviously need a proper mechanism for managing itineraries. To
address this need, the ESB Toolkit ships with an Itinerary Database that
runs within SQL Server (both SQL Server 2005 and 2008 are supported).
This database is named EsbItineraryDb and has one key table named
Itinerary. It allows you to version your itineraries (both major and
minor versions) as well as to define a name and description for the
itinerary.
The Itinerary Database serves two purposes:
The
second purpose will become clearer when you review the ESB Itinerary
Selector pipeline component. For now, it is enough for you to know that
the ESB provides a database for you to store and access itineraries as
needed at both design time and runtime.
With regard to high
availability and disaster recovery of this database, you can simply use
SQL Server's built-in capabilities. This is not a BizTalk database. It
is a stand-alone basic SQL Server database. You can use standard
clustering to provide high availability for this database, and you can
use SQL Server's built-in backup features within your disaster recovery
plans.