What is the problem? Consider the next Itinerary:
A message is received on the on-ramp, it is transformed to our HL7 message and after that send to an Orchestration. In the Orchestration the message parts MSHSegment (Header information) and ZSegments are added as part in a multipart message. This Orchestration is a generic process (service as you wish) for extending HL7 messages. After that the multipart messages must be routed to the off-ramp, which must be connected to the MLLP Adapter (from the Microsoft BizTalk Server HL7 Accelerator).
But, the MLLP Adapter is a static adapter and not dynamic. This means that no property schema is available for the MLLP transport settings (and if it was, the MLLP send adapter is not programmed that way). This means that no custom ESB adapter provider can be created and this means that you can’t use the MLLP Adapter in an ESB solution. You can’t use the MLLP Adapter in the Itinerary, because you can only use dynamic ports, and the MLLP Adapter has no possibilities to configure it dynamically (setting context properties for the transport).
I would like to see that Microsoft add some new features to the HL7 Accelerator: use it in a dynamic solution. But till that time, I’ve to use another way to get the benefits of the ESB Toolkit and thus my Itinerary (which can be successfully validated). Below I will describe my solution.
Because the MLLP Adapter can only be used in a static scenario, I created a static send port. For this solution I used an one-way port, and I don’t care for the ACK and NACK right now (will be a next blog). Because I want to use the power of the ESB Toolkit, I added a filter to my port:
I’m using my custom send pipeline with the ESB Dispatcher component, HTAHL7 2.x Assembler component (TrailingDelimiterAllowed on True!) and the ESB Itinerary Cache component:
As I mentioned above, you can only use dynamic ports in the off-ramp. So I created a dummy send port (or use an existing one). This dummy port I’m using in my itinerary:
Because my off-ramp has now the wrong values for Service Name, Service State and Service Type, I’ve to overwrite them so the filter is working correctly. Because I want to change my routing easily I define those settings in UDDI. I created a service ‘sendfilterformedicalsystemx’ and a binding ‘MyMLLPBackendSystem’:
Notice that I only added one instance info. I gave the binding a meaningful name so I can use it in the Itinerary:
Don’t forget to add a Category to this binding, else you will receive an exception during testing (see a blog from my earlier this month). It really doesn’t matter now what is in here so I added the transporttype:
And as latest in UDDI I add only one Instance Info: microsoft-com:esb:runtimeresolution:endpointconfig . This property has the next values:
As you can see, this property contains my filter keys and values for my send port. Now my UDDI service is registered (only for filter properties) I can finish my Itinerary. I can fill in the binding key in my UDDIResolver: uddi:esb:systemx
To continue the Itinerary in the ESB the right properties must be set in the Orchestration (note: Itinerary processing takes plance in receive- and send pipelines and Orchestrations). Some are basic and described on the site of Microsoft.
First I execute the next statements to retrieve the Itinerary and the current step:
itinerary = new Microsoft.Practices.ESB.Itinerary.SerializableItineraryWrapper();
itineraryStep = new Microsoft.Practices.ESB.Itinerary.SerializableItineraryStepWrapper();itinerary.Itinerary = Microsoft.Practices.ESB.Itinerary.ItineraryOMFactory.Create(InboundMsg);
itineraryStep.ItineraryStep = itinerary.Itinerary.GetItineraryStep(InboundMsg);
Because the next service in the Itinerary can be used, the next step must be retrieved:
itinerary.Itinerary.Advance(msgPharma, itineraryStep.ItineraryStep);
//itinerary.Itinerary.Write(msgPharma);
For my scenario the Write is not necessary. From the current service (my UDDI Resolver) I can retrieve my endpoint settings from UDDI and put them on the context of my message, so it will be published to my static send MLLP send port:
resolverDict = Microsoft.Practices.ESB.Resolver.ResolverMgr.Resolve(InboundMsg, itineraryStep.ItineraryStep.ResolverCollection[0]);
filterKeys = resolverDict.Item("Resolver.EndpointConfig");ServiceName = OrchestrationHelper.GetConfigItem(filterKeys, "ServiceName");
ServiceState = OrchestrationHelper.GetConfigItem(filterKeys, "ServiceState");
ServiceType = OrchestrationHelper.GetConfigItem(filterKeys, "ServiceType");msgPharma(Microsoft.Practices.ESB.Itinerary.Schemas.ServiceName) = ServiceName;
msgPharma(Microsoft.Practices.ESB.Itinerary.Schemas.ServiceState) = ServiceState;
msgPharma(Microsoft.Practices.ESB.Itinerary.Schemas.ServiceType) = ServiceType;
ResolverMgr.Resolve will resolve my UDDI Service and retrieve all the information I defined. The resolver dictionary will contain my EndPointConfig. Now it is just a matter of getting the right values (split a string) and place them on the context.
As you can see it isn’t that difficult, but I’m still not quiet happy with this solution (dynamic MLLP Adapter is preferable). I hope it gave you an idea how to use UDDI, Itineraries and Static Ports. The next challenge will be to send a message to a MLLP system, receive an ACK/NACK (or nothing), and return this information to the calling system: all of course defined in an Itinerary. I hope to blog about this very soon.
If you have questions, remarks or other ideas please contact me. Thanks for reading.




