how can I specify source filename having current value of job variable defined by previous step?

asmirnov (5 posts)
November 30, 2016 03:49 PM
Accepted Answer

Hi

I am trying to create two-step job.

First step: python script creating report file somewhere on network file system. Newly created report filename then is stored into job variable REPORT_PN using C# command line utility (which uses adTempus .NET API).

Second step is to copy resulting file using SFTP. I have created job step 'File Transfer Task'. In Source I was trying to specify report file via expression %REPORT_PN%

After few tests I found that step uses value of REPORT_PN which was saved when step was created.

Question: how can I specify source filename having current value of job variable defined by previous step.

Regards

Andrei

Bill Staff (599 posts)
November 30, 2016 05:00 PM
Accepted Answer

How are you setting the variable from your utility? I don't think we expose anything in the API that lets you set variables for a running instance.

asmirnov (5 posts)
November 30, 2016 05:14 PM
Accepted Answer

We have made C# console app which takes job name and variable name and value.

C# executable is then called from python by os.system. ArcanaDevelopment API calls used to set variable value. I placed code at the bottom of the message.

We don't have any problem to set and change job variable after report generation from inside of running step. However second step being adTempus supplied SFTP uploader need to access job variable value at the time of run.

==================================================

using System;
using System.Reflection;
using ArcanaDevelopment.adTempus.Client;
using ArcanaDevelopment.adTempus.Shared;

namespace AdTempusVariableUtility
{
class Program
{
static void Main(string[] args)
{
var isGet = args.Length == 3 && args[0] == "get";
var isSet = args.Length == 4 && args[0] == "set";
if (!isGet && !isSet)
{
Console.WriteLine("This utility sets or gets the value of the given variable, for the given adTempus job.");
Console.WriteLine("Set usage: {0} set [job name] [variable name] [variable value]", AppDomain.CurrentDomain.FriendlyName);
Console.WriteLine("If a variable does not exist, it will be created, with type String.");
Console.WriteLine();
Console.WriteLine("Get usage: {0} get [job name] [variable name]", AppDomain.CurrentDomain.FriendlyName);
Environment.Exit(1);
}
string jobName = args[1];
string variableName = args[2];

using (var connection = Scheduler.Connect())
{
using (var context = connection.NewDataContext())
{
var job = context.GetJob(jobName);
var jobVariable = job.JobVariables.GetVariable(variableName);
if (isSet)
{
string variableValue = args[3];
if (jobVariable == null)
{
var newJobVariable = CreateStringVariable(context, variableName, variableValue);
job.JobVariables.Add(newJobVariable);
}
else
{
SetVariableValue(jobVariable, variableValue);
}
job.Save();
}
else if (isGet)
{
if(jobVariable==null)
throw new ApplicationException(string.Format("Variable {0} not found for job {1}", variableName, jobName));
Console.WriteLine(jobVariable.Value);
}
}
}
}

private static JobVariable CreateStringVariable(DataContext context, string variableName, string variableValue)
{
var newJobVariable = (JobVariable) context.CreateObject(ClassID.JobVariable);
newJobVariable.Name = variableName;
newJobVariable.VariableType = JobVariableType.String;
newJobVariable.StringValue = variableValue;
return newJobVariable;
}

private static void SetVariableValue(JobVariable jobVariable, string variableValue)
{
switch (jobVariable.VariableType)
{
case JobVariableType.Boolean:
jobVariable.BooleanValue = bool.Parse(variableValue);
break;
case JobVariableType.Date:
int d;
if (int.TryParse(variableValue, out d))
jobVariable.DateValue = new DateTime(d/10000, (d/100)%100, d%100);
else
jobVariable.DateValue = DateTime.Parse(variableValue).Date;
break;
case JobVariableType.DateTime:
jobVariable.DateTimeValue = DateTime.Parse(variableValue);
break;
case JobVariableType.Time:
jobVariable.TimeValue = DateTime.Parse(variableValue);
break;
case JobVariableType.Decimal:
jobVariable.DecimalValue = decimal.Parse(variableValue);
break;
case JobVariableType.Integer:
jobVariable.IntegerValue = int.Parse(variableValue);
break;
default:
jobVariable.StringValue = variableValue;
break;
}
}
}
}
asmirnov (5 posts)
November 30, 2016 05:16 PM
Accepted Answer
The same code with better formatting...

================================================================

using System;
using System.Reflection;
using ArcanaDevelopment.adTempus.Client;
using ArcanaDevelopment.adTempus.Shared;
 
namespace AdTempusVariableUtility
{
    class Program
    {
        static void Main(string[] args)
        {
            var isGet = args.Length == 3 && args[0] == "get";
            var isSet = args.Length == 4 && args[0] == "set";
            if (!isGet && !isSet)
            {
                Console.WriteLine("This utility sets or gets the value of the given variable, for the given adTempus job.");
                Console.WriteLine("Set usage: {0} set [job name] [variable name] [variable value]", AppDomain.CurrentDomain.FriendlyName);
                Console.WriteLine("If a variable does not exist, it will be created, with type String.");
                Console.WriteLine();
                Console.WriteLine("Get usage: {0} get [job name] [variable name]", AppDomain.CurrentDomain.FriendlyName);
                Environment.Exit(1);
            }
            string jobName = args[1];
            string variableName = args[2];
 
            using (var connection = Scheduler.Connect())
            {
                using (var context = connection.NewDataContext())
                {
                    var job = context.GetJob(jobName);
                    var jobVariable = job.JobVariables.GetVariable(variableName);
                    if (isSet)
                    {
                        string variableValue = args[3];
                        if (jobVariable == null)
                        {
                            var newJobVariable = CreateStringVariable(context, variableName, variableValue);
                            job.JobVariables.Add(newJobVariable);
                        }
                        else
                        {
                            SetVariableValue(jobVariable, variableValue);
                        }
                        job.Save();
                    }
                    else if (isGet)
                    {
                        if(jobVariable==null)
                            throw new ApplicationException(string.Format("Variable {0} not found for job {1}", variableName, jobName));
                        Console.WriteLine(jobVariable.Value);
                    }
                }
            }
        }
 
        private static JobVariable CreateStringVariable(DataContext context, string variableName, string variableValue)
        {
            var newJobVariable = (JobVariable) context.CreateObject(ClassID.JobVariable);
            newJobVariable.Name = variableName;
            newJobVariable.VariableType = JobVariableType.String;
            newJobVariable.StringValue = variableValue;
            return newJobVariable;
        }
 
        private static void SetVariableValue(JobVariable jobVariable, string variableValue)
        {
            switch (jobVariable.VariableType)
            {
                case JobVariableType.Boolean:
                    jobVariable.BooleanValue = bool.Parse(variableValue);
                    break;
                case JobVariableType.Date:
                    int d;
                    if (int.TryParse(variableValue, out d))
                        jobVariable.DateValue = new DateTime(d/10000, (d/100)%100, d%100);
                    else
                        jobVariable.DateValue = DateTime.Parse(variableValue).Date;
                    break;
                case JobVariableType.DateTime:
                    jobVariable.DateTimeValue = DateTime.Parse(variableValue);
                    break;
                case JobVariableType.Time:
                    jobVariable.TimeValue = DateTime.Parse(variableValue);
                    break;
                case JobVariableType.Decimal:
                    jobVariable.DecimalValue = decimal.Parse(variableValue);
                    break;
                case JobVariableType.Integer:
                    jobVariable.IntegerValue = int.Parse(variableValue);
                    break;
                default:
                    jobVariable.StringValue = variableValue;
                    break;
            }
        }
    }
}
Bill Staff (599 posts)
November 30, 2016 05:30 PM
Accepted Answer

Your code is updating the job definition, but doing this doesn't affect the variables for the instance that's currently running.

There's another class (ApplicationIntegration) that's designed to let a running program interact with adTempus, but right now it doesn't let you get/set variables. I think we can pretty easily make a change to support this. Please open a support case and I'll see if we can get the change done for you this week.

By the way, your SetVariableValue method isn't necessary--you can just set JobVariable.Value to your string value. All variables get stored as strings, the JobVariable.xxxValue properties are just helpers that convert the underlying value to/from the required data type. Sorry the API docs are still rather sparse.

asmirnov (5 posts)
November 30, 2016 05:39 PM
Accepted Answer

I will consider adding support request. Meanwhile can you describe what can I do to finish the thing I am doing.

I was going to investigate adTempus scripts... If somehow job variables are not accessible I could store the value I need in some temp file on local disk. Can you describe how to write code reading the value from the file and the process of calling script to set up source location for SFTP upload step?

Bill Staff (599 posts)
November 30, 2016 05:54 PM
Accepted Answer

Yes, you could pass the value back in a file, then use a script to read the file and stick the value in a variable to be used by the upload step.

Just add a new step that runs a script, and put it between the python step and the upload step. You can write the script in C# or VB.NET and add code to read the file that you created outside adTempus. Once you have the value from the file, use this to set the variable:

adTempus.JobVariables["REPORT_PN"]=value;

This will set the variable only for the executing instance of the job, and the new value will be available when the upload step runs.

adTempus creates a temporary folder for each job instance that it runs, so you could put the file in that folder. The folder name is stored in the "ADTJobTemp" variable, and that variable is set as an environment variable when your python script gets run. So from that script, get the ADTJobTemp variable, and create a file in that folder named "reportname.txt" or whatever you want to call it.

In the script that you run in adTempus, you can used

System.IO.Path.Combine(adTempus.JobVariables["ADTJobTemp"],"reportname.txt")

to construct the name of the file that you need to read.

Or you could just use a hard-coded path for the file, as long as you won't have multiple instances of the job running at the same time.

asmirnov (5 posts)
December 1, 2016 10:18 AM
Accepted Answer

Hi Bill

You advice was helpful and I am now done with the task. It is a bit inconvenience to pass things via file but I will survive. Thanks a lot for your help.

Regards

Andrei

 

Bill Staff (599 posts)
December 1, 2016 10:26 AM
Accepted Answer

We are making the change to allow the variable to be set through the ApplicationIntegration class in the API, and also adding additional capabilities so the same features are available that are available to a script being run by adTempus.

If you want to go that route, open a support case so I can send you the updated software. For anyone else who comes upon this later, the change will be in the adTempus 4.5 release.

Replies are disabled for this topic.