I start off the
process with either a BizTalk Scheduler (http://biztalkscheduledtask.codeplex.com/releases/view/50363) or a manual file drop
of the XML message. The manual file drop is to allow the SQL
Job to call a "File Copy" SSIS step to copy the trigger file for the next
process and allows SQL
Job to be linked back into BizTalk processing.
The
Process Trigger XML looks like the following. It is basically the configuration hub
of the business
process
<ns0:MsgSchedulerTriggerSQLJobReceive xmlns:ns0="urn:com:something something">
<ns0:IsProcessAsync>YES</ns0:IsProcessAsync>
<ns0:IsPermissionRequired>YES</ns0:IsPermissionRequired>
<ns0:BusinessProcessName>Data Push</ns0:BusinessProcessName>
<ns0:EmailFrom>
[email protected]</ns0:EmailFrom>
<ns0:EmailRecipientToList>
[email protected]</ns0:EmailRecipientToList>
<ns0:EmailRecipientCCList>
[email protected]</ns0:EmailRecipientCCList>
<ns0:EmailMessageBodyForPermissionRequest>This message was sent to request permission to start the Data Push
process. The SQL Job to be run is WeeklyProcessing_DataPush</ns0:EmailMessageBodyForPermissionRequest>
<ns0:SQLJobName>WeeklyProcessing_DataPush</ns0:SQLJobName>
<ns0:SQLJobStepName>Push_To_Production</ns0:SQLJobStepName>
<ns0:SQLJobMinToWait>1</ns0:SQLJobMinToWait>
<ns0:PermissionRequestTriggerPath>\\server\ETL-BizTalk\Automation\TriggerCreatedByBizTalk\</ns0:PermissionRequestTriggerPath>
<ns0:PermissionRequestApprovedPath>\\server\ETL-BizTalk\Automation\Approved\</ns0:PermissionRequestApprovedPath>
<ns0:PermissionRequestNotApprovedPath>\\server\ETL-BizTalk\Automation\NotApproved\</ns0:PermissionRequestNotApprovedPath>
</ns0:MsgSchedulerTriggerSQLJobReceive>
Every node
of this schema was promoted to a distinguished field so that the values can be used for decision making in the orchestration. The first decision made is on the "IsPermissionRequired" field.
If permission is required (IsPermissionRequired=="YES"), BizTalk will use the configuration info in the XML trigger to format the email message. Here is the snippet
of how the email message is constructed.
SQLJobEmailMessage.EmailBody
= new Eai.OrchestrationHelpers.XlangCustomFormatters.RawString(
MsgSchedulerTriggerSQLJobReceive.EmailMessageBodyForPermissionRequest +
"<br><br>" +
"By moving the file, you are either giving permission to the
process, or disapprove
of the
process." +
"<br>" +
"This is the file to move: \"" + PermissionTriggerToBeGenereatedHere +
"\"<br>" +
"(You may find it easier to open the destination folder first, then navigate to the sibling folder to get to this file)" +
"<br><br>" +
"To approve, move(NOT copy) the file here: " + MsgSchedulerTriggerSQLJobReceive.PermissionRequestApprovedPath +
"<br><br>" +
"To disapprove, move(NOT copy) the file here: " + MsgSchedulerTriggerSQLJobReceive.PermissionRequestNotApprovedPath +
"<br><br>" +
"The file will be IMMEDIATELY picked up by the automated
process. This is normal. You should receive a message soon that the file is processed." +
"<br>" +
"Thank you!"
);
SQLJobSendNotification(Microsoft.XLANGs.BaseTypes.Address) = "mailto:" + MsgSchedulerTriggerSQLJobReceive.EmailRecipientToList;
SQLJobEmailMessage.EmailBody(Microsoft.XLANGs.BaseTypes.ContentType) = "text/html";
SQLJobEmailMessage(SMTP.Subject) = "Requesting Permission to Start the " + MsgSchedulerTriggerSQLJobReceive.BusinessProcessName;
SQLJobEmailMessage(SMTP.From) = MsgSchedulerTriggerSQLJobReceive.EmailFrom;
SQLJobEmailMessage(SMTP.CC) = MsgSchedulerTriggerSQLJobReceive.EmailRecipientCCList;
SQLJobEmailMessage(SMTP.EmailBodyFileCharset) = "UTF-8";
SQLJobEmailMessage(SMTP.SMTPHost) = "localhost";
SQLJobEmailMessage(SMTP.MessagePartsAttachments) = 2;
After the Permission request email is sent, the next step is to generate the actual Permission Trigger file. A correlation set is used here on SQLJobName and a newly generated GUID field.
<?xml version="1.0" encoding="utf-8"?><ns0:SQLJobAuthorizationTrigger xmlns:ns0="somethingsomething"><SQLJobName>Data Push</SQLJobName><CorrelationGuid>9f7c6b46-0e62-46a7-b3a0-b5327ab03753</CorrelationGuid></ns0:SQLJobAuthorizationTrigger>
The end user (the human intervention piece) will either grant permission for this
process, or deny it, by moving the Permission Trigger file to either the "Approved" folder or the "NotApproved" folder. A parallel Listen shape is waiting for either response.
The next set
of steps decide how the SQL Job is to be called, or whether it is called at all. If permission denied, it simply sends
out a notification. If permission is granted, then the flag (IsProcessAsync) in the original
Process Trigger is used. The synchonous part is not really synchronous, but a loop timer to check the status within the calling stored procedure (for more information, check
out my previous post: http://geekswithblogs.net/LifeLongTechie/archive/2010/11/01/execute-sql-job-synchronously-for-biztalk-via-a-stored-procedure.aspx) If it's async, then the sp starts the job and BizTalk sends
out an email.
And
of course, some error notification:
Footnote: The next version
of this orchestration will have an additional parallel line near the Listen shape with a Delay built in and a Loop to send
out a daily reminder if no response has been received from the end user. The synchronous part is used to gather results and execute a data clean up
process so that the SQL Job can be re-tried. There are manu possibilities here.