Oct 202014
 

“Can an itinerary to be able to make a decision in the middle of the flow?”

I have an itinerary, that processes requisitions, there are two requirements:

  • Must archive the message after it goes through the two web services
  • Depending on the requisition amount go down one path or the other: if it is a high requisition, it applies a discount

Using out-of-the-box features, this is VERY challenging, however, using the Orchestration Broker Service, the itinerary looks like this:

Orchestraiton Broker

We are going to concentrate on the Orchestration Broker section (the brown shape) (the other pieces are covered in other posts).

So I dropped the Broker Service shape onto the itinerary surface and chose Orchestration Broker Service (Stott Creations)

Broker Extension 

So there are two broker resolvers, the payload and the context: so I can create two types of filters: based on the data in the message, or based on the context.

The first one I create is the payload, I want to be able to send data based on data in the payload: to the high or low, so I add a new resolver and call it Payload, because there could be multiple parts to a message, you can specify which part number we want to interrogate. By default it is part 0, if you don’t deal with multi-part messages, leaving it at 0 is fine.

Orchestration Payload Resolver

I also want to send data based on the Context, so I add another resolver and choose Orchestration Context Resolver Extension. Notice that there are no other settings (no multi-part requirements)

Orchestration Context Resolver

Okay, now for the fun part.

I want to create a filter so that it will archive the data (regardless of anything else). I add a filter name it Archive Filter, choose the out-of-the-box XPath Filter, and paste the following statement stating: look at all of the context properties and if you find that the Property is called ServiceName with the itinerary system properties and that value is set to StottCreations.ESB.Orchestration.Broker this filter will be true (which it always will because it is in an Orchestration Broker service step):

/ContextProperties/Property[@name=’ServiceName’ and @namespace=’http://schemas.microsoft.biztalk.practices.esb.com/itinerary/system-properties’] = “StottCreations.ESB.Orchestration.Broker”

Archive Filter

I add two more filters based on payload:

Name: High Priority

Filter Implementation: XPath

Expression: /*[local-name()=’Information’ and namespace-uri()=’http://InternalInterface.Canonical’]/*[local-name()=’OrderNumber’ and namespace-uri()=”] > 853

 

Name: Low Priority

Filter Implementation: XPath

Expression: /*[local-name()=’Information’ and namespace-uri()=’http://InternalInterface.Canonical’]/*[local-name()=’OrderNumber’ and namespace-uri()=”] < 853

Now I drop three Itinerary Broker Outports to the edge of the Orchestration Broker Step, this marries the resolvers to the filters:

Archive Out Port

Archive Out Port 1

With the other two I choose the Payload Resolver, and the appropriate Filter

Here is what it looks like:

Partially Configured

I connect the outputs and the input.

So when I run a high message through: (order number > 853) this is what the flow looks like in the Portal:

High Flow

Here is the low flow

Low Flow

Jun 252014
 

I had really high hopes for this release of BizTalk’s ESB Toolkit for BizTalk 2013 R2 (Heard rumors it was no longer called a toolkit because it was part of the install, drug but I was wrong! It still is a toolkit.)

Installed folder states it is still a toolkit

It looks like we are still working under the toolkit version 2.1!

Notice the assembly version!

 

And the XPath Filter is still wrong:

The DLL extension is DLLL

May 162014
 

I am writing this actually for myself.

When defining a XPath Filter and you are using the Context Resolver, the format of the context properties xml document that the XPath will run against is:

<ContextProperties>
  <Property name=”SourceCharset” namespace=”http://schemas.microsoft.com/BizTalk/2003/xmlnorm-properties”>utf-16</Property>
</ContextProperties>

 

So the filter expression would looks something like this:

/ContextProperties/Property[@name=’SourceCharset’ and @namespace=’http://schemas.microsoft.com/BizTalk/2003/xmlnorm-properties’]/text()=”utf-16”

May 032014
 

BizTalk 2013’s ESB Toolkit has a bug: The XPath filter will never work.

The assembly that is deployed has a bad bad extension

Assembly in the GAC

So, troche make sure you rename the extension before running an itinerary that uses the broker service

(I have already applied BTS CU2, malady which stated that there were three ESB fixes, this obviously wasn’t one of them!)

Oct 022013
 

Extending on the last entry, we will build a validation to check to see is there is anything in the Value property.

Open up the ruleset.config and add the following section to the bottom of the xml document

<!-- Hard Coded Resolver --> <type assemblyName="HardCodedResolver" name="StottCreations.ESB.HardCodedResolver.HardCoded"> <ruleset name="Menu"> <properties> <property name="value"> <validator type="Microsoft.Practices.Modeling.Validation.NotEmptyStringValidator, Microsoft.Practices.Modeling.Validation" messageTemplate="The '{1}' property value should not be empty or null." name="Hardcoded.Value not null validator"/> </property> </properties> </ruleset> </type>

After you make the entry, you have to shut down all instances of Visual Studio (not just the one that has itineraries in the project). If you don’t you can test all you want and it won’t validate!

I put the resolver and left it blank. Went to save it (so it would validate it) and I got the following error:

image

There are a significant number of validation components available:

image

Sep 102013
 

So a couple of years I started learning about the ESB and when I discovered that you can pass values into an orchestration through a resolver, I thought ‘this is awesome, now I can send custom values into an orchestration based on a particular itinerary.’

I struggled in actually doing this, and finally put values in the Static Resolver and did sneaky string parsing of the Resolver in an orchestration.

I spent today (yes, one day) and created a simple custom resolver. I read the huge volumes of documentation on how to do it:

  1. Create an assembly with a class that implements the IResolveProvider interface and contains a Resolve method that returns resolver facts as an instance of the Dictionary class.
  2. Register the resolver by adding it to the Esb.config configuration file using a <resolver> element that contains the root moniker as the name attribute and the fully qualified assembly name as the type attribute.
  3. (Optional) Create a schema that defines the root moniker and the query parameters, and then save it in the ESB.Schemas.Resolvers folder. The name should follow existing ESB naming conventions; this means it should use the name of the root moniker appended with “_Resolution.xsd”.
  4. (Optional) Generate a class from the new schema and save it in the custom resolver assembly. This exposes typed parameters in the custom resolver.
  5. Register the new assembly in the global assembly cache.

Not terribly helpful, so I wanted to create the simple steps I took to get it all working:

Resolver

  1. I created a schema that had two values I wanted to pass into the orchestration:
    image
    the actual code is:
    <?xml version="1.0" encoding="utf-16"?> <xs:schema xmlns="http://schemas.microsoft.biztalk.practices.esb.com/itinerary" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.biztalk.practices.esb.com/itinerary" id="HardCoded" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="HardCoded"> <xs:complexType> <xs:attribute name="value" type="xs:string" use="required" /> <xs:attribute name="enable" type="xs:boolean" use="required" /> </xs:complexType> </xs:element> </xs:schema>

  2. I used xsd.exe and created the class for it. I then added decorations to the class:
    using System.Xml.Serialization; using Microsoft.Practices.Modeling.ExtensionProvider.Metadata; using Microsoft.Practices.Services.ItineraryDsl; using System.ComponentModel; using Microsoft.Practices.Modeling.ExtensionProvider.Extension; namespace StottCreations.ESB.HardCodedResolver { [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.17929")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.microsoft.biztalk.practices.esb.com/itinerary")] [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://schemas.microsoft.biztalk.practices.esb.com/itinerary", IsNullable = false)] [ObjectExtender(typeof(Resolver))] public partial class HardCoded { private string valueField; private bool enableField; /// <remarks/> [Category(HardedCodedProvider.ExtensionProviderPropertyCategory), Description("Value to be passed into the service"), DisplayName("Value"), ReadOnly(false), Browsable(true)] [System.Xml.Serialization.XmlAttributeAttribute()] public string value { get { return this.valueField; } set { this.valueField = value; } } /// <remarks/> [Category(HardedCodedProvider.ExtensionProviderPropertyCategory), Description("Enable Property"), DisplayName("Enable"), ReadOnly(false), Browsable(true)] [System.Xml.Serialization.XmlAttributeAttribute()] public bool enable { get { return this.enableField; } set { this.enableField = value; } } } [ExtensionProviderAttribute("E5D2F3B5-C792-4050-BF9F-61234B30A3AC", "HardCoded", "Hard Coded Resolver Extension", typeof(ItineraryDslDomainModel))] [ResolverExtensionProvider] public partial class HardedCodedProvider : ExtensionProviderBase { public const string ExtensionSourcePropertyCategory = "Source Settings"; public HardedCodedProvider() : base(typeof(HardCoded)) { } } }

  3. I included the .cs file as part of the project
  4. Build and place the assembly in the following folder: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft.Practices.Services.Itinerary.DslPackage\Lib
  5. Restart Visual Studio

Provider

  1. Created a new C# project, gave it a strong named key (because BizTalk will execute this in the orchestration)
  2. In the class I wrote the following code:
    using System; using System.Collections.Generic; using Microsoft.Practices.ESB.Resolver; using System.Xml; using System.Reflection; using Microsoft.XLANGs.BaseTypes; using Microsoft.Practices.ESB.Exception.Management; using Microsoft.BizTalk.Message.Interop; using Microsoft.BizTalk.Component.Interop; using Microsoft.Practices.ESB.Resolver.Container; using Microsoft.Practices.Unity; namespace StottCreations.ESB.HardCodedResolverProvider { public class HardCodedResolverProvider : IResolveProvider, IResolveContainer { /// <summary> /// Resolve implementation for use with Resolver Web Service. This method is typically used with unit tests to test for the correct Resolved entities, such as itinerary, maps and endpoint addresses. /// This method invokes the Hard Coded Values that were configured through the Config and Resolver connection string values. /// </summary> /// <param name="config">string containing name, value property values</param> /// <param name="resolver">Resolver connection string</param> /// <param name="message">Xml document containing the message to pass to the resolver if configured properly</param> /// <returns>Resolver Dictionary Collection containing resolved entries, such as itinerary name, map name, and endpoint address resolution values</returns> Dictionary<string, string> IResolveProvider.Resolve(string config, string resolver, XmlDocument message) { throw new NotImplementedException(); } /// <summary> /// Resolve implementation for use within a Pipeline component. /// This method is typically used with one of the ESB Pipeline components such as the Itinerary Selector, or ESB Dispatcher to resolve entities, such as itinerary, maps and endpoint addresses. /// This method invokes the Values that were configured through the Config and Resolver connection string values. /// </summary> /// <param name="config">string containing name, value property values</param> /// <param name="resolver">Resolver connection string</param> /// <param name="message">BizTalk IBaseMessage class which is used to pass to the resolver if configured properly</param> /// <param name="pipelineContext">BizTalk Pipeline configuration</param> /// <returns>Resolver Dictionary Collection containing resolved entries, such as itinerary name, map name, and endpoint address resolution values</returns> Dictionary<string, string> IResolveProvider.Resolve(string config, string resolver, IBaseMessage message, IPipelineContext pipelineContext) { throw new NotImplementedException(); } /// <summary> /// Resolve implementation for use within an Orchestration. /// This method is typically used by creating an instance of the BRE Resolver Provider class inside an orchestration expression to resolve entities, such as itinerary, maps and endpoint addresses. /// This method invokes the BRE Policies that were configured through the Config and Resolver connection string values. /// </summary> /// <param name="resolverInfo">Resolver collection of entries</param> /// <param name="message">BizTalk XLangMessage class which is used to pass to the resolver if configured properly</param> /// <returns>Resolver Dictionary Collection containing resolved entries, such as itinerary name, map name, and endpoint address resolution values</returns> Dictionary<string, string> IResolveProvider.Resolve(ResolverInfo resolverInfo, XLANGMessage message) { Dictionary<string, string> dictionary; if (message == null) { throw new ArgumentNullException("message"); } Resolution resolution = new Resolution(); try { dictionary = ResolverMgr.GetFacts(resolverInfo.Config, resolverInfo.Resolver); } catch (Exception exception) { EventLogger.Write(MethodBase.GetCurrentMethod(), exception); throw; } finally { if (resolution != null) { resolution = null; } } return dictionary; } private static IUnityContainer container; public void Initialize(Microsoft.Practices.Unity.IUnityContainer container) { HardCodedResolverProvider.container = container; } } }

  3. Compile and place the code into the GAC
  4. In the esb.config, you need to tell the ESB how to look up this: so you add the following line to the configuration\esb\resolvers section (upper case of the class of the resolver (public partial class HardCoded))
    <resolver name="HARDCODED" type="StottCreations.ESB.HardCodedResolverProvider.HardCodedResolverProvider, HardCodedProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=41bb35272df047ea"/>

  5. In the orchestration, add the following code in an expression shape (after creating to string variables called Enable and Value)
    Resolver=Resolvers.Current; ResolverDictionary = Microsoft.Practices.ESB.Resolver.ResolverMgr.Resolve(InMsg, Resolver); Enable = ResolverDictionary.Item("ENABLE"); Value = ResolverDictionary.Item("VALUE");

  6. Deploy the orchestration and add the reference to the newly deployed orchestration in the esb.config
  7. Create the itinerary that calls the orchestration you created in step 5 image
  8. Deploy the itinerary, setup the on ramp to call the itinerary
  9. Run a message through the itinerary
  10. I put a breakpoint as I ran it and here is the Orchestration debugger image

Please don’t flame me, I know that there are a series of try/catch blocks I should be putting in this, but this is 15 steps on how to create a custom resolver that you can pass values directly into an orchestration (and do the same for a messaging based solution also).

Mar 282013
 

Microsoft has asked Stott Creations to create a few ESB samples for the release of BizTalk 2013. We are finalizing those samples right now.

One thing I hate about the current samples that come out of the box with the ESB Toolkit, pharm is that they rely on other samples being created. If I want to learn how to do something, dosage there are steps on how to get the sample I care about working. The problem is that each first step states that another sample needs to be completed before you can start working on this one. I go to the that sample, and that example states that it relies on another sample being created first. All told, I have to create 4 different samples to get to the one that really want to work on. With each sample I incur a compound set of exponential opportunities to make a mistake. It generally means that I never get to the actual sample I want to work on.

That rant drove these samples to be completely self contained, so if you want to learn each of these, they rely on nothing else being done. 

Dynamic Endpoint

image

We will be showing how to use a purchase order to send to various end points. Our sample will be a messaging based solution where we will use a static itinerary resolver. The itinerary that it walks through will use the BRE to resolve both the map and the backend system it is going to. We will be showing that it can be sent to the following endpoints:

  • SQL: New PO processing Interface
  • File: Old PO Processing Interface
  • SMTP: Email to operations that this purchase order does not belong to this department
Defining Business Processes

image

We will be showing the following flow within the Itinerary Flow Designer:

  1. Receive Purchase Order
  2. Create Advanced Shipment Notification
  3. Warehouse Notification
  4. Email confirmation

We will show, using the BRE, how this same flow can orders, and how the end points, even though they are for the same flow, based on the data, will go to two different warehouses. The two different areas are defined in this map:
image

Once we show that is working, we are going to add another warehouse to the mix based on some new criteria, which means we add a new rule to the policy and it is now able to handle this new warehouse:
image

Agility

We will show a member verification process as part of an order process. This process will have the following steps:

image

  1. State Verification
  2. Item Verification

When, we will show that there is a new service that is brought online, and we will change the itinerary to add this new step, and watch the new flow without breaking any logic. We will deploy a new map, and add the additional step into the flow, deploy the new itinerary. The new flow will be:

image

  1. State Verification
  2. Member Id Verification
  3. Item Verification
Exception Handling

image

We are going to step outside of ‘ESB World’ and show a standard orchestration that fails, and that orchestration has been setup to send data to the exception handling mechanism. This means that the management console remains ‘empty’ and that the Exception Portal being configured for notifications that an email will be sent out notifying of the failure. The failure will be a mis-configured send port that is bound to the orchestration. We will show that you can resubmit the message back for the orchestration to reprocess it after the send port was corrected.

Repair and resubmit will also be shown, where you can modify the message (as the order will have 0 orders bought, which throws a separate error).

After resubmission, you see the process complete. Again, the best part of this that instead of suspended messages in the message box (I am sure you have never seen this in a production environment before), the messages go to the ExceptionDb and can be handled separately without clogging up the message box.

Mar 012013
 

So if you are creating itineraries, order and you need to stick an orchestration in your itinerary, there are two orchestrations that come out of the box.

AWESOME!

image

 

However, if you are like me, you have found the documentation a little lacking, especially regarding these two orchestrations.

Looking at our previous blog entry about how to look at the shapes in an orchestration, I will describe what is going on with these two orchestrations.

Microsoft.Practices.ESB.Services.Routing
Receive Msg

Gets the message from the message box called InboundMessage

Get Current Itinerary

Retrieves the current Itinerary, Itinerary Step, logs ServiceName and ServiceType to the Trace.

Retrieve Resolvers

Retrieves the resolvers associated to the itinerary at this step, and logs to the trace the number of resolvers at this step

Resolvers Returned?

Checks to ensure that there are resolvers present (resolvers.Count > 0)

Loop through Resolvers

resolvers.MoveNext()

Resolve

Extract out of the resolvers, the current resolver, write to the trace, fill the resolverDictionary the items contained in the current resolver, log all of the items that are specified in the static resolver, set the transportLocation and transportType (internal strings)

Transport Info Returned

Ensured that the two strings have a length greater than 1

Construct Delivery Message/Set Delivery Message

Creates a new message from the InboundMessage called DeliveryMessage, sets the endpoint of the DeliveryMessage, sets the DeliveryPort’s address to the transportLocation and the deliveryPort’s transport type to transportType

Send Delivery

Sends the message off to the address

Catch Delivery Exception

Creates a fault message, sets the fault code to 2444, logs that An error occurred attempting to deliver message., sets the severity to critical and sends the message on

Catch Exception

Same thing except sets the fault code to 2555

and continues the looping through the rest of the resolvers

Advance Itinerary/Construct Outbound Message/Set Advance Itinerary

Creates a new message called OutboundMessage from the InboundMessage, advances the OutboundMessage itinerary, writes it, logs the ServiceName, SeriviceState, and ServiceType.

Catch Exception

If it throws an exception it logs it as 2555 and logs that there was an Exception while attempting to Advance Itinerary

More Itinerary Steps

Checks to see if the state is complete ( itineraryStep.ItineraryStep.State != Microsoft.Practices.ESB.Itinerary.State.Complete )

Send Message

Sends the OutboundMessage back to the bus

Construct Post Itinerary Fault Message

Logs 2777 with the following error message ‘Unable to persist routed message, are there subscribers for it?’

Catch Routing Resolution Exceptions

for some catastrophic error. a fault message is created with error 2111 with the error Exception while attempting to work with Itinerary Step

Use case

If you need to take your message off of the bus and send it out (Scatter pattern), this is the orchestration to do it.

 

 

Microsoft.Practices.ESB.Services.Transform
Receive Message

Receives InboundMessage from the bus

Get Current Itinerary

Retrieves the current Itinerary, Itinerary Step, logs ServiceName and ServiceType to the Trace.

Retrieve Resolvers

Retrieves the resolvers associated to the itinerary at this step, and logs to the trace the number of resolvers at this step

Resolvers Returned?

Checks to ensure that there are resolvers present (resolvers.Count > 0)

Resolve

Gets the current resolver, takes the items from the static resolver and adds it to the dictionary, logs it to the trace, and sets the transformType

Map Name Returned?

transformType.Lenth > 0

Construct Map Resolution Fault Message

Sets fault code to 1111 and logs Exception while attempting to determine map type, creates fault message and send it off

Construct Outbound Message/Construct Outbound Message

Executes the transform and advances the itinerary and drops the OutboundMessage off to the bus

Set Mp Exception Fault Message (sic)

Sets fault code to 1444 and logs Unable to retrieve the the Type for map type: the map

Set Map Execution Fault Message

Sets fault code to 1222 and logs Exception while attempting to apply map: the map

Use Case

You want to execute a map on the bus, you can add this service, specify the map in the resolver, and the map will be transformed and placed back on the bus.

(A close friend asked me if there was a way that multiple maps can be executed in a row in the ESB. This is a perfect service to do just that. Just remember, that only the first resolver will be invoked (any others will be ignored), so if you need multiple maps executed, you need to add multiple services chained together each with one resolver and you can incrementally map the data.)

Feb 192013
 

When you install BizTalk 2013, rx be default, cialis you can’t create itineraries. I was under the distinct impression that the ESB setup was all handled though the BizTalk setup dialog.

However, abortion I am mistaken. If you want the itinerary flow designer, there is an additional setup step required.

In the folder where the BizTalk setup is found, there is a VSIX package installer:

image

Once you install it, you see this confirmation dialog:

VISX Confirmation

 

Happy itinerary designing!