The Recipient List pattern addresses the scenario solution in which a message is routed to one or more recipients.
For a detailed description of this pattern, see Recipient List on the Enterprise Integration Patterns site.
The implementation of this pattern is a combination of the %u200bMicrosoft BizTalk ESB Toolkit Itinerary Routing Service and multiple resolvers.
Out of the box you can:
- Define the itinerary routing service with a messaging extender to execute in the BizTalk pipeline using Itinerary Designer.
- Define the itinerary routing service with an orchestration extender to execute as an orchestration using Itinerary Designer, which performs routing using BizTalk send ports.
Usually the Recipient List does not modify the message contents but what if recipient A wants to have another message as recipient B, C, and D? In the resolvers you can also configure a map but it will not be executed in the Routing service because only a Transform service can execute a map. You can add a Transform service to the itinerary but then all the messages are modified. So how can you solve this problem? Create a custom RecipientList service and combine the two services!
How to: Create a Custom Itinerary Service Using a BizTalk Orchestration
The following steps are necessary to create an Orchestration based Routing service that also can transform the message.
1. Create new BizTalk Server project in Visual Studio and add the new RecipientListService orchestration. |
2. Add references to the following ESB Toolkit assemblies: |
|
3. Define a logical direct-bound Receive Port and an activated Receive Shape in the Orchestration. |
4. Define a subscription filter to the Receive Shape to activate the orchestration from the message itinerary context so that the orchestration executes the RecipientListService step. |
5. Add an Expression Shape to the orchestration with the following code to retrieve the current itinerary step. |
// Retrieve the current itinerary step
itinerary = new Microsoft.Practices.ESB.Itinerary.SerializableItineraryWrapper();
itineraryStep = new Microsoft.Practices.ESB.Itinerary. itinerary.Itinerary = Microsoft.Practices.ESB.Itinerary. itineraryStep.ItineraryStep = itinerary.Itinerary.GetItineraryStep(InboundMessage); .csharpcode, .csharpcode pre |
6. Add an Expression Shape to the orchestration with the following code to retrieve the Resolvers associated with the itinerary. |
// Init
resolverDictionary = null;
// Retrieve the Resolvers associated with the itinerary
resolvers = itineraryStep.ItineraryStep.ResolverCollection; |
7. Add a Decide shape with the rule “resolvers.Count > 0” |
8. Add a Loop Shape to the orchestration with the expression “resolvers.MoveNext()” to loop through the Resolvers. |
9. Add an Expression Shape to the orchestration with the following code to retrieve the Resolver properties. |
// Retrieve current resolver
resolver = resolvers.Current; // Pass the resolver configuration to the Resolver mgr for resolution
resolverDictionary = Microsoft.Practices.ESB.Resolver. // Get properties
mapName = resolverDictionary.Item("Resolver.TransformType");
transportLocation = resolverDictionary.Item("Resolver.TransportLocation");
transportType = resolverDictionary.Item("Resolver.TransportType");
.csharpcode, .csharpcode pre |
10. Add a Decide shape with the rule “mapName != null && mapName != " |
11. Add an Expression Shape to the orchestration with the following code to transform the message. |
// Transform message
transformedMsgXml = Microsoft.Practices.ESB.Transform.MapHelper. // Create XmlDocument
xmlDoc.LoadXml(transformedMsgXml); .csharpcode, .csharpcode pre |
12. Add a Message Assignment Shape to the orchestration with the following code to create the ESBRequest message and set the dynamic port properties. |
// Create ESB Message
ESBMessage.Body = xmlDoc; // Call the Adapter Manager to set all necessary properties
Microsoft.Practices.ESB.Adapter.AdapterMgr.SetEndpoint(resolverDictionary,ESBMessage); // Set delivery port address
DynamicPort(Microsoft.XLANGs.BaseTypes.Address) = transportLocation; DynamicPort(Microsoft.XLANGs.BaseTypes.TransportType) = transportType; .csharpcode, .csharpcode pre |
13. Create a Port with a Dynamic binding and add a Send Shape to the orchestration to send the ESBRequest message to the Recipient. |
14. Add a Message Assignment Shape to the orchestration with the following code to create the Outbound message and set the dynamic port properties. |
// Create message
OutboundMessage.Body = xmlDoc; OutboundMessage(*) = InboundMessage(*); // Call the Itinerary helper to advance to the next step
hasMoreSteps = itinerary.Itinerary.HasNextService(); itinerary.Itinerary.Advance(OutboundMessage, itineraryStep.ItineraryStep); itinerary.Itinerary.Write(OutboundMessage); .csharpcode, .csharpcode pre |
15. Add a Decide shape with the rule “hasMoreSteps” |
16. Create a Correlation Type and a Correlation Set for the itinerary. |
17. Create a Port with a Direct binding and add a Send Shape (with the Correlation Set) to the orchestration to send the Outbound message back to the MessageBox database. |
18. Add an Exception handler to the Main scope to catch all the exceptions. (You can also have exception handlers on other scopes) |
19. Add a Message Assignment Shape to the Exception handler with the following code to create a Fault Message. You can add multiple messages to the FaultMessage. |
// Trace
System.Diagnostics.Trace.WriteLine("[RecipientListService] Exception:" + ex.Message);
// Create FaultMessage
FaultMessage = Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt. // Set Fault Message Properties
FaultMessage.Body.FaultCode = "2111";
FaultMessage.Body.FaultDescription = "Exception";
FaultMessage.Body.FailureCategory = "Routing Failure";
FaultMessage.Body.FaultSeverity = Microsoft.Practices.ESB.ExceptionHandling. // Add message
Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.AddMessage .csharpcode, .csharpcode pre |
20. Create a Port with a Direct binding and add a Send Shape to the orchestration to send the FaultMessage message back to the MessageBox database. |
21. Right click on the BizTalk project and click in the Menu on the Properties item. Click on the signing tab to create Strong Name Key. |
22. Click on the Deployment tab to configure the Deployment properties and set the Application Name. |
23. Right click on the BizTalk project and select Build to create the assembly. |
24. Right click on BizTalk project and click on Deploy to deploy the Orchestration. |
25. In the BizTalk Administration Console go to the created application and configure the Bindings of the orchestration and start the application. |
How a Custom Itinerary Service can be used in an Itinerary
The following steps describe what must be done so that the Custom Itinerary Service can be used in the Itinerary Designer in Visual Studio.
1. Close Visual Studio |
2. In the BizTalk Administration Console double click on the orchestration and copy the name and the assembly properties. |
3. Open the esb.config from the ESB Toolkit as an Administrator |
Location: C:\Program Files (x86)\Microsoft BizTalk ESB Toolkit |
4. Add a new itineraryService entry in the itineraryServices section. |
|
5. Open Visual Studio as an Administrator and open the ESB solution |
6. Right click on the ESB solution select Add / New Project. |
7. In the “Add New Project” PopUp window select BizTalk ESB Itinerary Designer. Give it a name and click on the OK button. |
8. In Solution Explorer, right-click the ItineraryLibrary project, point to Add, and then click New Itinerary. |
9. From the Toolbox, drag an Itinerary Service model element to the design surface. In the Properties select: – Itinerary Service Extender: Orchestration|Orchestration Extender – Service Name: RecipientListService |
10. Add a Resolver to the Itinerary Service and set the necessary properties. (Location, map, etc.) |
11. Connect the Itinerary Service to an OnRamp and validate the itinerary. |
Conclusion
It’s not very complicated to create a Custom Itinerary Service using a BizTalk Orchestration but there is not much documentation on MSDN. It is shortly described but the documentation is not complete. There are some other blogs on the internet and the %u200bMicrosoft BizTalk ESB Toolkit includes the “Scatter-Gather” sample that you can install and run.
You can download the Custom Itinerary Orchestration Service and the sample itinerary here:
Creating a Custom Itinerary Orchestration Service for the Recipient List pattern