Update subject and message for all Notification Actions

Languages: C#, VB.NET

View on GitHub to download or comment.

See the Client API Examples Introduction for additional information and prerequisites.

Samples index

This script finds all Notification Actions that are run for a failed step and updates them with a new notification subject and message.

When you leave the Subject or Message blank for a NotificationAction, adTempus uses a default subject and message, but there is currently no way to customize the template that is used in this case.

In this scenario, a customer wanted to define their own template to be used for messages sent when a step fails.

To accomplish this, they defined two server-level Job Variables, FailedStepSubject and FailedStepMessage, which defined the templates for the subject and message. Because Job Variable values can contain other job variables, you can use predefined variable tokens to have the job name, step number, etc., automatically inserted.

Next the script below is run to modify the Notification Actions for failed steps to use the FailedStepSubject and FailedStepMessage variables as their subject and message.

  • The script retrieves all jobs
  • For each job it examines all Responses at the job and step level
  • If a Response is triggered by the "Step Failed" event, the script processes the Actions for the Response
  • For any Notification that does not already have a Subject or Message set, the script sets the Subject and Message to the variable tokens "%FailedStepSubject%" and "%FailedStepMessage%"

This script can be run once for initial conversion, and/or run periodically from an adTempus job to convert any new jobs that are created after the first run.

sample.cs
 public void Main()
    {

        // define the new subject and message.
        // in this case they are being set to Job Variables that are defined elsewhere
        string subject = "%FailedStepSubject%";
        string message = "%FailedStepMessage%";

        using (var session = Scheduler.Connect(".", LoginAuthenticationType.Windows, "", ""))
        {
            using (var context = session.NewDataContext())
            {
                // fetch all jobs on the server
                var jobs = context.GetJobs("*");
                foreach (var job in jobs)
                    UpdateJob(job, subject, message);
            }
        }
    }

    public void UpdateJob(Job job, string subject, string message)
    {
        var jobUpdated = false;

        // update job-level Responses
        if (UpdateResponses(job.Responses, subject, message))
        {
            Debug.WriteLine("Updated action(s) for " + job.FullyQualifiedName);
            jobUpdated = true;
        }

        // update the Responses for each step
        foreach (var jobStep in job.Steps)
        {
            if (UpdateResponses(jobstep.Responses, subject, message))
            {
                jobUpdated = true;
                Debug.WriteLine("Updated action(s) for " + job.FullyQualifiedName + " step " + jobStep.StepNumber);
            }
        }

        if (jobUpdated)
            job.Save();
    }


    // determines if the Response is triggered by the specified event
    private void ResponseContainsEvent(Response response, JobEvent targetEvent)
    {
        foreach (var item in response.Events)
        {
            if (item.Event == targetEvent)
                return true;
        }
        return false;
    }

    private bool UpdateResponses(System.Collections.ResponseCollection responses, string subject, string message)
    {
        var changesMade = false;

        foreach (var response in responses)
        {

            // in this example we are only looking for Responses that get triggered if the Step fails.
            // So we check the events for the Response to see if it is triggered by JobEvent.TaskFailed.
            // This way we don't update resonses for other events (e.g., job succeeded)
            if (ResponseContainsEvent(response, JobEvent.TaskFailed))
            {

                // response is triggered by the event we want.

                // look at all Actions for the Response and process NotificationActions
                foreach (var action in response.Actions)
                {
                    if (action.ClassID == ClassID.NotificationAction)
                    {
                        if (UpdateAction((NotificationAction)action, subject, message))
                            changesMade = true;
                    }
                }
            }
        }

        return changesMade;
    }

    // Update a NotificationAction to use a new Subject and Message if those values are not already set
    private bool UpdateAction(NotificationAction action, string subject, string message)
    {
        var actionUpdated = false;

        if (string.IsNullOrEmpty(action.NotificationMessage))
        {
            actionUpdated = true;
            action.NotificationMessage = message;
        }

        if (string.IsNullOrEmpty(action.NotificationSubject))
        {
            actionUpdated = true;
            action.NotificationSubject = subject;
        }

        return actionUpdated;
    }
sample.vb
Sub Main
	
	'define the new subject and message.
	'in this case they are being set to Job Variables that are defined elsewhere
	Dim subject As String="%FailedStepSubject%"
	Dim message As String = "%FailedStepMessage%"
	
	Using session = Scheduler.Connect(".", LoginAuthenticationType.Windows, "", "")
		Using context=session.NewDataContext()
			'fetch all jobs on the server
			Dim jobs=context.GetJobs("*")
			For Each job In jobs
				UpdateJob(job, subject, message)
			Next
		End Using
	End Using
End Sub

Sub UpdateJob(job As Job, subject as String, message as string)
	Dim jobUpdated = False

	'update job-level Responses
	If UpdateResponses(job.Responses, subject, message) Then
		Debug.WriteLine("Updated action(s) for " & job.FullyQualifiedName )
		jobUpdated=True
	End If

	'update the Responses for each step
	For Each jobStep In job.Steps
		If UpdateResponses(jobstep.Responses, subject, message) Then
			jobUpdated = True
			Debug.WriteLine("Updated action(s) for " & job.FullyQualifiedName & " step " & jobStep.StepNumber)
		End If
	Next

	If jobUpdated Then
		job.Save()
	End If
End Sub


'determines if the Response is triggered by the specified event
Private Function ResponseContainsEvent(response As Response, targetEvent As JobEvent)
	For Each item In response.Events
		If item.Event = targetEvent Then
			Return True
		End If
	Next
	Return False	
End Function

Private Function UpdateResponses(responses As Collections.ResponseCollection, subject As String, message As String) As Boolean
	Dim changesMade = False
	
	For Each response In responses
		
		'in this example we are only looking for Responses that get triggered if the Step fails.
		'So we check the events for the Response to see if it is triggered by JobEvent.TaskFailed.
		'This way we don't update resonses for other events (e.g., job succeeded)
		If ResponseContainsEvent(response, JobEvent.TaskFailed) Then
			
			'response is triggered by the event we want.
			
			'look at all Actions for the Response and process NotificationActions
			For Each action In response.Actions
				If action.ClassID = ClassID.NotificationAction Then
					If UpdateAction(Ctype(action, NotificationAction), subject, message) Then
						changesMade = True
					End If
				End If
			Next
		End If
	Next

	Return changesMade
End Function

'Update a NotificationAction to use a new Subject and Message if those values are not already set
Private Function UpdateAction(action As NotificationAction,subject As String,message As String) As Boolean
	Dim actionUpdated=False

	If String.IsNullOrEmpty(action.NotificationMessage) Then
		actionUpdated = True
		action.NotificationMessage=message
	End If

	If String.IsNullOrEmpty(action.NotificationSubject) Then
		actionUpdated = True
		action.NotificationSubject = subject
	End If
	
	Return actionUpdated
End Function

Comments

View on GitHub to comment.