Thursday, February 5, 2015

BizTalk using Business Rule Engine Introduction

Title: BizTalk using Business Rule Engine Introduction:
Author: Toraj Khavari
Date: Feb. 2, 2015

Objective: The Microsoft BizTalk Rule Engine (BRE) is a powerful tool with very flexible technologies. The BizTalk Rule Composer is a GUI enabling the users to create, modify, and deploy business rules to production without BizTalk Application implementation. The technologies enable business with variety of functionalities. To name a couple, the BRE contains Value Pair information (can be used for example in, email list, configuration information), and BRE has flexible product discount logic (can be utilized for example for, time, value and product dependent). In this wiki article we will explore using BRE for a key value pair and use the information inside an application Orchestration.

Article Body:
For production support, I have business requirements to implement a solution to distribute emails when there are orchestrations errors with different priorities, and provide some recommendation in the email about who can fix it, and lay the foundation to a web site that the application and system administrators can post blogs, wikis, solutions, notes, etc. There are five key value pairs needed to meet the requirements. The value pairs were instantiated in BRE and deployed. The BizTalk administrators can modify them as needed without code deployment and developers involvements.

1-      Create a schema and capture all the nodes needed. In my case it is called Adec.VendorsEDI.BRESchemas.EmailInfo.


2-      In the BizTalk Rule Composer, construct the Vocabularies to use Adec.VendorsEDI.BRESchemas Schema for Source Fact. In my case they are type System.String.


3-      Create a Policy, build the Business Rule and deploy it.


4-      Create three Messages in a new orchestration. 1) Message Type matching the BRE Vocabulary Source Fact, in my case, it is Adec.VendorsEDI.BRESchemas.FlatFileSchema1. It is called ExceptionAssignVendorsEdiAdminInfoMsg. 2) Message_XMLIn and 3) Message_XMLOut of Message Type matching the inbound and out bound schemes. In my case they are the same Adec.VendorsEDI.InboundWHSchema.X12_00401_850.


5-      The best method to communicate how to use BRE in an orchestration is to review a complete solution first; thereafter, look at each component. Let us review a complete orchestration.


a.      Add a receiving messages port. With a Message Type matching the inbound schema. In my case Adec.VendorsEDI.InboundWHSchema.X12_00401_850.


b.      Add a dynamic send port matching the outbound schema. For my case, it is the same message type as inbound. Adec.VendorsEDI.InboundWHSchema.X12_00401_850. It is called. POErrorOrchestrationDynamicSend.


c.       Set up the receiving port with Message type identified in the Orchestration Messaged. It is Message_XNLIn. Connect the Receive port (a) with the Receive shape (c).


d.      Insert a construct message. The Message Construction must construct the Message element identified in the orchestration to contain the BRE information. In my case it is ExceptionAssignVendorsEdiAdminInfoMsg.


e.      This is where it gets interesting. The best way to instantiate a message schema is using a Map. Add a Transform Shape to Construct Message, Transform_InitEdiAdminInfo.


Build a simple map with source Message_XMLIn and Destination ExceptionAssignVendorsEdiAdminInfoMsg. Use the Value in the Property window and initialize all the values for ExceptionAssignVendorsEdiAdminInfoMsg. Does not matter what Values are. We are instantiating and initializing schema nodes.


f.        Insert a Call Rule shape. Select the BRE Policy and Parameter.


By now, we have received a message, instantiate a schema with nodes matching the BRE vocabularies, and called the BRE policy.  At this point of orchestration, we have all the information in the orchestration message. In our case, it is called ExceptionAssignVendorsEdiAdminInfoMsg.
g.       Add an Expression and extract the values from the ExceptionAssignVendorsEdiAdminInfoMsg node. The following is a sample code.

// Extract the BRE Information. The Schema, Node, Properties, and Instance XPath is the best place to get the Xpath.
// Remove the "Namespace" from the XPath copied from "Instance XPath". Do not need it.
// The variables are System.String. The Xpath require string to cast the extracted value.
BiztalkAppAdminDistList = xpath(ExceptionAssignVendorsEdiAdminInfoMsg,
  "string((/*[local-name()='BREEmailInfo']/*[local-name()='BSTAppAdminDistList'])[1])");
BADistList = xpath(ExceptionAssignVendorsEdiAdminInfoMsg,
  "string((/*[local-name()='BREEmailInfo']/*[local-name()='BADistList'])[1])");
ResURL = xpath(ExceptionAssignVendorsEdiAdminInfoMsg,
  "string((/*[local-name()='BREEmailInfo']/*[local-name()='ResolutionURL'])[1])");
SMTPESubject = xpath(ExceptionAssignVendorsEdiAdminInfoMsg,
  "string((/*[local-name()='BREEmailInfo']/*[local-name()='SMTPSubject'])[1])");
SysAdminDistList = xpath(ExceptionAssignVendorsEdiAdminInfoMsg,
  "string((/*[local-name()='BREEmailInfo']/*[local-name()='SystemAdminDistList'])[1])");

// Build the msg body
tempString  = System.String.Format("VendorsEDI Error Watcher BRE Information -");
tempString  = tempString  + System.String.Format(" BiztalkAppAdminDistList is: {0}" , BiztalkAppAdminDistList);
tempString  = tempString  + System.String.Format(" BADistList is: {0}" , BADistList);
tempString  = tempString  + System.String.Format(" ResURL is: {0}" , ResURL);
tempString  = tempString  + System.String.Format(" SMTPESubject is: {0}" , SMTPESubject);
tempString  = tempString  + System.String.Format(" SysAdminDistList is: {0}" , SysAdminDistList);

// Eventlog information
System.Diagnostics.EventLog.WriteEntry("VendorsEDI", tempString , System.Diagnostics.EventLogEntryType.Information, 1000);

// If the field is Null or Empty
if(System.String.IsNullOrEmpty(BiztalkAppAdminDistList))
{
  tempString  = System.String.Format("Error Watcher Error: the BiztalkApplicationAdministersDistributionList BRE String is not valid: {0}" , "It is Null or Empty. ") + tempString ;
  // Log event. For simplicity, let us log the same message.
  System.Diagnostics.EventLog.WriteEntry("VendorsEDI", tempString , System.Diagnostics.EventLogEntryType.Error, 1009);
}


// If the field is Null or Empty
if(System.String.IsNullOrEmpty(BADistList))
{
  tempString  = System.String.Format("Error Watcher Error: the BusinessAnalystDistributionList BRE String is not valid: {0}" , "It is Null or Empty. ") + tempString ;
  // Log event. For simplicity, let us log the same message.
  System.Diagnostics.EventLog.WriteEntry("VendorsEDI", tempString , System.Diagnostics.EventLogEntryType.Error, 1009);
}


// If the field is Null or Empty
if(System.String.IsNullOrEmpty(ResURL))
{
  tempString  = System.String.Format("Error Watcher Error: the ResolutionURL BRE String is not valid: {0}" , "It is Null or Empty. ") + tempString ;
  // Log event. For simplicity, let us log the same message.
  System.Diagnostics.EventLog.WriteEntry("VendorsEDI", tempString , System.Diagnostics.EventLogEntryType.Error, 1009);
}


// If the field is Null or Empty
if(System.String.IsNullOrEmpty(SMTPESubject))
{
  tempString  = System.String.Format("Error Watcher Error: the SMTPEmailSubject BRE String is not valid: {0}" , "It is Null or Empty. ") + tempString ;
  // Log event. For simplicity, let us log the same message.
  System.Diagnostics.EventLog.WriteEntry("VendorsEDI", tempString , System.Diagnostics.EventLogEntryType.Error, 1009);
}


// If the field is Null or Empty
if(System.String.IsNullOrEmpty(SysAdminDistList))
{
  tempString  = System.String.Format("Error Watcher Error: the SystemAdministersDistributionList BRE String is not valid: {0}" , "It is Null or Empty. ") + tempString ;
  // Log event. For simplicity, let us log the same message.
  System.Diagnostics.EventLog.WriteEntry("VendorsEDI", tempString , System.Diagnostics.EventLogEntryType.Error, 1009);
}

h.      Add Construct Message with Message Constructed matching the output message.


i.         Add create email message assignment. The wiki article “BizTalk Send Email and Post Event logs” outlines the details for email creation. Please feel free to refer to it.

j.         Add Send shape and connect to the dynamic port.


6-      Build and deploy the solution. In the BizTalk admin tool, the orchestration requires receive and send port.


7-      The Dynamic Send Port uses the XML Transmit pipeline.


8-      The receive port is a typical File type with XML Receive pipeline.


We are done. The BizTalk BRE and Orchestration is fully integrated.

Hints:
-          Instantiating schema in a map is a powerful method of initializing a schema.
-          I wonder if the inbound schema can be a generic XML document. It will enable us to reuse some of our orchestration. This could be another wiki article on its own.
-          The schema node properties have the xpath for the elements.
-          Deploying Orchestration can be a bit interesting. However, it makes perfect sense when you think thorough them.
o   When deploying BizTalk Orchestration with the same Assembly Information (Assembly Version and File Version), the Orchestration/s must be in the Unenlist status.
1.      Use the BizTalk Admin to Unenlist Orchestrations.
2.      Deploy the Orchestration/s and their dependent maps, together.
o   When deploying BizTalk Orchestration with the updated Assembly Information, Assembly Version and File Version, the Orchestration/s and Dynamic Ports must be in the Unenlist status.
1.      Use the BizTalk Admin to Unenlist Orchestrations and Dynamic Ports.
2.      Deploy all the schemas.
3.      Deploy the Orchestration/s and their dependent maps, together.

Enjoy coding. When designing, always think about the maintenance and production support. Push as much as possible logic in the BRE. Now that you learned how to use BRE, use the technology.

Cheers Toraj
References:
·         Walkthrough: Invoking the Policy from an Orchestration - http://msdn.microsoft.com/en-us/library/aa995582.aspx
·         Convert xml file to string inside BizTalk map using inline XSLT  http://stephenomo.blogspot.com/2011/11/convert-xml-file-to-string-inside.html

Version 1.0.1405.01

Biztalk Send Email and Post Event logs

Title: Biztalk Send Email and Post Event logs
Author: Toraj Khavari
Date: February 4, 2015
Objective: Solid enterprise solutions have sustainable system life cycles with embedded Productionability, Operationability, Maintainability, etc. I often refer to them the “*ability.” Two major components to support *abilities are sending emails, and posting events in the system event log. Email notification and system event logs are great tools for system exceptions and error handling. Event logs can be monitored and the system administrators can perform the initial root cause analysis using the Event Viewers.
Biztalk is the A-dec enterprise service bus. In this article we explore a design to use Biztalk Orchestration to send email and post / log events.
Article Body:
1-      Examine the Event Log Application and Service. If you do not have a pool for your application, create a pool using the following command.
New -EventLog -LogName "<LogName>" -Source "<Source>"

In this article, we will use the following “LogName” and “Source.”
New -EventLog -LogName "VendorsEDI" -Source "Adec"


2-      Dynamic Ports provides us XLANGs class libraries, which make the email / SMTP adaptors more user-friendly.


Hint:
-          If you wish to use none dynamic ports, that is very possible, too. In this article, we will focus on dynamic ports.
-          Add the following reference to your project.
Microsoft.XLANGs.BaseTypes

3-      Create an orchestration. Receive shape, followed by Construct Message, followed by Send Shape, and inside the Construct Message insert a Message Assignment. The orchestration should look as follows.


Hint:
-          Do not be concerned about all the error messages and red (!) marks, we will deal with them.
-          Set Receive “Activities” to True.
-          Complete all the shapes properties. In my case they are as follows.






4-      Create Receive Port



I already have one. You can create a new one.





Hint:
-          Add the references needed to identify the Request Operation Message, Message Type. In this article case it is, Adec.VendorsEDI.OutboundAdecSchema


5-      Create Send Port



There is an existing one for this article. Feel free to create a new one.


Select Port binding “Dynamic.”



Hint:
-          Add the references needed to identify the Request Operation Message, Message Type. In this article, for simplicity, it is the same as input schema, Adec.VendorsEDI.OutboundAdecSchema


6-      Wire the ports. Connect your Ports with the Receive and Send.


7-      The heart of this article is creating the email, logging a message, and sending the email. To make it interesting, I included prompted values, extracted values, and a few more items. Before getting started, setup a few references and identify a few variables.
Add the following references to your project
      System.XML
System.Configuration

Navigate to the Orchestration View TAB, Orchestration View, and expand the Messages node. Add the following Messages
POMessageOut – Message Type received schema, in this article is as follows.
Adec.VendorsEDI.OutboundAdecSchema.PurchaseRequisition_Purchase850
PurchaseOrderMsg - Message Type send schema, in this article, for simplicity, is the same as above.
Navigate to the Orchestration View TAB, Orchestration View, and expand the Variables node. Add the following variables.
emailMsgOut – Type System.String
tempString– Type System.String
OrderAccountStr – Type System.String
PurchNameStr - Type System.String


8-      Construct email. Create Email Message and Log Events. Double click “CreateEmail_MsgAssignment” Message Assignment. Double click on the Message Assignment, “CreateEmail_MsgAssignment”, in the Construct Message

Copy and paste the following code in the Message Assignment and select apply. Change the email address.
// Identify the email recipients. If there are more than one, separate them with <;>.
// The best option is have email group.
tempString = System.String.Format("mailto:{0}", "your.email@company.com");
WHOrchestrationDynamicSend(Microsoft.XLANGs.BaseTypes.Address)=tempString;

// Copy the inbound XML document
POMessageOut = PurchaseOrderMsg;

// Extract the Order Account. The Schema, Node, Properties, and Instance XPath is the best place to get the Xpath.
// Remove the "Namespace" from the XPath copied from "Instance XPath". Do not need it.
// The variables are System.String. The Xpath require string to cast the extracted value.
OrderAccountStr = xpath(POMessageOut,
  "string((/*[local-name()='PurchaseRequisition']/*[local-name()='VendPurchOrderJour']/*[local-name()='PurchTableAllVersions']/*[local-name()='OrderAccount'])[1])");
PurchNameStr = xpath(POMessageOut,
  "string((/*[local-name()='PurchaseRequisition']/*[local-name()='VendPurchOrderJour']/*[local-name()='PurchTableAllVersions']/*[local-name()='PurchName'])[1])");

// Assign email subject.
tempString = System.String.Format("Message from Vendors EDI Orchestration Server {0}", "GBTDEVAXBTS02");
POMessageOut (SMTP.Subject)=tempString;
// Assign email body text character set. It is very critical. Make sure it is setup correctly.
// Will cause you a lot of issue, if it is not 100% right.
tempString = System.String.Format("{0}", "utf-8");
POMessageOut (SMTP.EmailBodyTextCharset)=tempString;

// Build the email body
emailMsgOut = System.String.Format("VenderEDI Sender -");
emailMsgOut = emailMsgOut + System.String.Format(" Identification Number: {0}" , PurchaseOrderMsg.SenderId);
emailMsgOut = emailMsgOut + System.String.Format(" OrderAccount is: {0}" , OrderAccountStr);
emailMsgOut = emailMsgOut + System.String.Format(" PurchName is: {0}" , PurchNameStr);

// Set the email boddy
POMessageOut (SMTP.EmailBodyText)=emailMsgOut;
// Log event. For simplicity, let us log the same message.
System.Diagnostics.EventLog.WriteEntry("VendorsEDI", emailMsgOut);

Hint:
-          Minimize whatever has a potential of change from any code. Place all the “tempString” on the SSO Application or Biztalk Business Rule Engine (BRE). They are out of the scope of this paper. For BRE Interface refer to “BizTalk using Business Rule Engine Introduction” and for SSO Application refer to “SSO Application and its use in BizTalk.”

9-      Build and Deploy the project

10- The coding part of this application is completed. Biztalk provides SMTP Adaptors to communicate with email servers. To configure SMTP adaptors we need a Host Instance. I prefer to keep Host and Host Instances unique, as much as possible. It will enable us to support *ability.
Configure Hosts: Open Biztalk Admin Tool. Expand Biztalk Group > Hosts Node. Add a new Hosts “Send.”


Create a new “Send” Host Instance.


11- Configure a new Send Handler for SMTP Adaptor.


12- Application deployment configures the dynamic ports. Enlist and start it


13- Bind, Enlist and start the orchestration.


14- Refresh the Biztalk Group and Host Instances.
You are done. Drop an XML in the Receive Port and watch your email. In this article example the email looks as follows,


View the event log. In this article example, the log is as follows.


The potential for Biztalk emailing messages with out-of-box adaptors, logging events, promoting schema node, extracting data from schema, etc. have significant potentials to meet A-dec’s business needs, support *ability, error handling, exception handing, and the list goes on.
Confucius said, “Choose a job you love, and you will never work a day in your life.”
Enjoy coding.
Cheers Toraj
 References:
-          BizTalk using Business Rule Engine Introduction - http://torajkhavari.blogspot.com/2015/02/biztalk-using-business-rule-engine.html
-          Exception handling in BizTalk orchestrations explained - http://mitchvanhelden.blogspot.com/2012/10/exception-handling-in-biztalk.html
-          SendMail (BizTalk Server Sample) - http://msdn.microsoft.com/en-us/library/ee253647%28v=bts.10%29.aspx
-          BizTalk Training – Handling Exceptions inside orchestration - http://sandroaspbiztalkblog.wordpress.com/2009/10/26/biztalk-training-handling-exceptions-inside-orchestration/
-          Sending SMTP email from within BizTalk Orchestration - http://www.nullskull.com/a/1408/sending-smtp-email-from-within-biztalk-orchestration.aspx
-          The Code for above example is in the A-dec TFS site as follows.
o   $/VendorsEDI/Adec.VendorsEDI/Adec.VendorsEDI.POOrchErrorHandling


Version 1.0.1405.01