Loading [Contrib]/a11y/accessibility-menu.js
Skip to content

Working with Jobs

This section is aimed at answering some questions that often arise with regard to the designing and writing of jobs. The explanations take the outset in the job XML which, as already stated, does not imply that the user will work directly with the XML or need to understand XML. The user interface completely shields the XML for the user, but in order to design well-structured and well-behaved jobs a good understanding of the basic concepts, as best explained through the XML, is required.

How to specify the targets to execute

Specification of the target(s) within the job that shall be executed can be done in two ways:

  • From the job execution dialog. (See the section Execute a job further down in the document.)

  • From the Default attribute in the job's Project element. (See Listing 4).

Listing 4 Specification of default targets

In both cases the target specification can include a comma-separated list and the targets will be executed in order from left to right.

How to sequentially order tasks

Tasks are always executed sequentially within a target on a first defined - first executed basis. It is possible to skip some of the tasks in the sequence, (not during execution) and redefining the order.

How to have targets depending on each other

Targets can be defined to have mutual dependencies, i.e. so that a target T1 depends on a target T2, in the sense that a job will automatically ensure that T2 is executed before T1.

Listing 5 below shows an example of this.

Listing 5 Target dependencies

Execution specifying target T1 as the target to execute will result in first executing target T3, then target T2 and finally target T1.

How to conditionally execute targets

A task may be omitted or included from execution due to a specific condition. The example in Listing 6 demonstrates such a situation Task1 has an output parameter that governs the execution of the following two tasks in the target. Task2 shall only be executed in case the output parameter is larger than a certain threshold value and Task3 only if the parameter is smaller than the threshold value.

Listing 6 Task Condition processing instruction

It should be noted from the listing how the threshold value is defined at point 1 and ii used at point 3 and point 4. The Task1 output parameter is converted into a property at point 2. Also note the comparison operators used in the conditions strings at point 3 and 4 $gt; and $le; are XML operators that compares to > and <=. The strange XML versions are necessary to distinguish them from XML elements.

Users use the normal <, >, <= and >= versions when working from the user interface.

The supported set of comparison operators are shown in Table 1 below.

Condition Description
'stringA' == 'stringB' Evaluates to true if stringA equals stringB.

For example:

Condition="'$(CONFIG)'=='DEBUG'"

Single quotes are not required for simple alphanumeric strings or boolean values. However, single quotes are required for empty values.
'stringA' != 'stringB' Evaluates to true if stringA is not equal to stringB.

For example:

Condition="'$(CONFIG)'!='DEBUG'"

Single quotes are not required for simple alphanumeric strings or boolean values. However, single quotes are required for empty values.
<, >, <=, >= Evaluates the numeric values of the operands. Returns true if the relational evaluation is true. Operands must evaluate to a decimal or hexadecimal number. Hexadecimal numbers must begin with "0x".
Exists('stringA') Evaluates to true if a file or folder with the name stringA exists.

For example:

Condition="!Exists('$(builtdir)')"

Single quotes are not required for simple alphanumeric strings or boolean values. However, single quotes are required for empty values.
HasTrailingSlash('stringA') Evaluates to true if the specified string contains either a trailing backward slash (\) or forward slash (/) character.

For example:

Condition="!HasTrailingSlash('$(OutputPath)')"

Single quotes are not required for simple alphanumeric strings or boolean values. However, single quotes are required for empty values.
! Evaluates to true if the operand evaluates to false.
And Evaluates to true if both operands evaluate to true.
Or Evaluates to true if at least one of the operands evaluates to true.
() Grouping mechanism that evaluates to true if expressions contained inside evaluate to true.

Table 1 Condition operators

The above solution works fine in cases where a single or just a few tasks within a target need to be conditionally executed. Where a larger number of tasks need to be executed conditionally, it is often more convenient to factor the conditional tasks out in a separate target and have that target executed through a special CallTarget task. This is demonstrated in Listing 7.

Listing 7 Conditional execution using CallTarget

Note how Target1 branches out to Target2 in case "some-condition" evaluates to true. After Target2 has finished, execution processing commences in Target1 with the task following the CallTarget task.

How to handle task output

Listing 1 includes a task the CalculateTimeseriesQuantile task that has an output parameter. In order to make use of such an output parameter, the parameter needs to be converted into a job property and this conversion happens through the Output element which is also shown in the same listing.

The formal XML syntax for the Output element is shown below in Listing 8.

Listing 8 Output element

The TaskParameter attribute is used for establishing a reference to the task's output parameter and the PropertyName defines the name of the job property that will receive the value of the output parameter.

A task can have multiple output parameters. An example of this is shown in Listing 9 below. The task GetSimulationPeriod has two output parameters, the start and end date of a model simulation.

Listing 9 Task with two output parameters

Note in the example how the GetSimulationPeriod task has two Output child elements, where the first maps StartDate output parameter to a Begin property and the second maps the EndDate output parameter to an End property. The two generated properties are then used in the Message task.

How to pass information from one target to another

Passing information from one task to another task is simple this was demonstrated in Listing 1. Unfortunately it is not that simple to pass information from one target to another in situations involving CallTarget. Listing 10 below, which would usually be an intuitive way of handling this, does just not work.

Listing 10 Erroneous way to pass information between targets with CallTarget

The reason for this is that the properties generated within a target are not made global (visible for all targets) until the target has finished. This expansion rule implies that when chaining targets through the DependsOnTarget target attribute or through providing a list of targets for execution, most things work as expected, e.g. the example in Listing 11 works as expected when executing Target2. Target2 depends on Target1 why this is executed in its entirety before Target2 actually starts execution and because Target1 has finished when Target2 starts, the Prop1 property is available for use within Target2.

Listing 11 Correct way to pass information between targets with static target dependency

This is all fine, but there is still the issue with CallTarget from Listing 10. There are existing workarounds for this and one of these involves writing the properties to a file in the calling target and then reading them from the called target. This is demonstrated in Listing 12.

Listing 12 Workaround for passing information between targets with CallTarget

Note how the calling target Target1writes the Prop1 property to a file which is then read by Target 2. It is not elegant but it gets the job done.

How to continue with a job despite failing tasks

The standard processing behaviour for a job is to completely terminate execution when a task execution fails. For example, in a job as the one shown in Listing 1, execution would terminate if, for instance, the CalculateTimeseriesQuantile task fails.

A task can fail for a number of different reasons, but typicaly an error situation occurs during task execution and the task itself cannot recover from the error. Again referring to Listing 1, in case the value of the Timeseries attribute was misspelled then the task would not be able to locate the time series and the task would have been put in a situation where it could not execute. The task execution would fail and the job processing thus terminated.

In some cases it might be undesirable to have a job terminated due to task execution failure. This can be avoided through the task attribute ContinueOnError if this attribute is provided with the value true, then a possible task execution error for a specific task will be ignored. Listing 13 below shows an example of this.

Listing 13 Use of the ContinueOnError task processing instruction

If the CalculateTimeseriesQuantile task in the above listing fails during execution, the job execution will not terminate but simply continue with the WriteLinesToFile task. This is because the ContinueOnError attribute value has been defined as true. In the event that either the ImportTimeseries or the WriteLinesToFile tasks fail, the job execution will terminate. These tasks have not been decorated with a true value for their ContinueOnError attribute.

How to handle errors

Task execution errors can be handled in three different ways:

  1. Terminate the job which is the default action.

  2. Ignore the error through the use of the ContinueOnError procession instruction. See section 3.7 How to have a job continue despite failing tasks?.

  3. Catch the error in an OnError element.

The OnError element which looks very much like a task, simply transfers execution to another task. In other words, it acts very similar to the CallTarget task. Listing 14 below shows the XML format of the OnError element.

Listing 14 The OnError element XML format

Listing 15 depicts an example on how to use the OnError element.

Listing 15 Use of OnError

In the example above the Error task raises an error which is caught by the OnError element. The OnError element branches execution to the Target2 target.

Note the following two aspects about the OnError element:

  1. Although The OnError element appears as a normal task, it is executed in context of the job and not in the context of the target it appears in. This implies that properties that have been defined within the failing target are globalized and thus available for use from within the target(s) that the OnError target branches to.

  2. A target can include multiple OnError elements and will in such cases be called in the order mentioned.

The Job Manager job editor treats the OnError as a task, see the The Job Editor View section.