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.