Using RedwoodScript in Job Definitions
RedwoodScript is the ideal language to automate complex tasks, adding custom code to a Job Definition, for example. The following code illustrates some features you might like to implement.
Note: The easiest way to develop your code is to use the web-based shell first. If it runs in there, it should run in a Job Definition. However, the web-based shell does not have parent processes, so parent/child examples will not run in it.
See the RedwoodScript, Redwood Expression Language, and Scripting Contexts sections for a list of examples, functions, contexts and predefined objects.
Note: Redwood Software does not warrant that this is the most effective way in solving your specific problem. The examples are provided to illustrate the use of RedwoodScript.
Note: If you set the Requested Start Time of a Job, pay attention to not specify dates before 1901 or your Job will be vetoed.
Creating a Job Definition
To create a Job Definition, you first need to know if the Definition Type requires a source. Then you create the Job Definition and source (in a Script object) and link the source to the process.
{
JobDefinition jDefinition = jcsSession.createJobDefinition();
jDefinition.setName("JD_GetCurrentSales");
jDefinition.setPartition(jcsSession.getPartitionByName("SALES"));
jDefinition.setJobDefinitionType(jcsSession.getJobDefinitionTypeByName("JDBC"));
Script script = jcsSession.createScript();
script.setLibrary(jcsSession.getLibraryByName("Custom"));
script.setJobDefinition(jDefinition);
script.setRunAsUser("Example");
script.setSource("select prod_ID,prod_name,prod_inc,prod_out from prod where prod_mon = 123");
jcsSession.persist();
}
Accessing Parameters
To access the current Parameters, remember that the current Job is already defined as jcsJob
and the SchedulerSession
is defined as jcsSession
.
{
jcsOut.println(Name);
jcsOut.println(Address);
jcsOut.println(City);
jcsOut.println(Zip);
}
You can also use the Job (technical name Job
) to retrieve the Parameters and then their values. The below code can also be used if you want to retrieve the values of Parameters of other Jobs (replace the otherJob
object with an object that points to the correct Job).
{
// Replace this line with code to get the other process
Job otherProcess = jcsJob;
//get the In value of parameter pName and print its value
JobParameter pNameVal = otherProcess.getJobParameterByName("pName");
jcsOut.println(pNameVal);
//or, without retrieving the parameter
jcsOut.println(pName);
//set the Out value of the parameter
pName = "GoodBye World!";
//print out the Out value
jcsOut.println(pName);
//write it to the database
jcsSession.persist();
}
Running a Simple Job Definition
Basic code to create a Job from a Job Definition, without specifying any Parameters. If the Job Definition has Parameters, the defaults will be used.
{
// code to submit a job running System_Sleep
// get the job definition
JobDefinition jDefinition = jcsSession.getJobDefinitionByName("System_Sleep");
// create the job from the job definition
Job process = jDefinition.prepare();
// submit the job definition and write unsaved data to the database
jcsSession.persist();
}
Submitting a Simple Job with Parameters
The following is the same basic code as above, but this time with Parameters. If you do not specify a value for a Parameter, the default value will be used. If a Job Definition has a required parameter with no default value, you must specify a value or the Job will not run.
{
// code to submit SAP_AbapRun that runs the ABAP program RSUSR000
// get the job definition SAP_AbapRun
JobDefinition jDefinition = jcsSession.getJobDefinitionByName("SAP_AbapRun");
// create the job
Job process = jDefinition.prepare();
// assign parameters
process.getJobParameterByName("SAP_SYSTEMS").setInValueString("TR1");
process.getJobParameterByName("ABAP_PROGRAM_NAME").setInValueString("RSUSR000");
process.getJobParameterByName("JOBNAME").setInValueString("RSUSR000 made with RedwoodScript");
// assign queue as SAP jobs require a queue
Partition Partition = jcsSession.getPartitionByName("RW_DEMO");
Queue queue = jcsSession.getQueueByName(partition, "TR1_Queue");
process.setQueue(queue);
// submit the job definition and write unsaved data to the database
jcsSession.persist();
// wait for all children
jcsSession.waitForAllChildren(process);
}
Running a Simple Job Definition with Parameters Using REL Evaluation
The following is the same basic code as above, but this time specifying a REL expression as a value. The expression will be evaluated and the Parameter value will be set to the result of the expression.
{
// code to submit SAP_AbapRun that runs the ABAP program RSUSR003
// get the job definition SAP_AbapRun
JobDefinition jDefinition = jcsSession.getJobDefinitionByName("SAP_AbapRun");
// create the job
Job process = jDefinition.prepare();
// assign parameters
process.getJobParameterByName("SAP_SYSTEMS").setInValueString("TR1");
process.getJobParameterByName("ABAP_PROGRAM_NAME").setInValueString("RSUSR003");
process.getJobParameterByName("JOBNAME").setInValueByEvaluatingREL(jcsSession, "='From ' + getSystemId()");
// assign queue as SAP jobs require a queue
Partition Partition = jcsSession.getPartitionByName("RW_DEMO");
Queue queue = jcsSession.getQueueByName(partition, "TR1_Queue");
process.setQueue(queue);
// submit the job definition and write unsaved data to the database
jcsSession.persist();
// wait for all children
jcsSession.waitForAllChildren(process);
}
Accessing Parent/Child Parameters
In this example, a child Job retrieves the Parameter values of its direct parent. Remember that a Job Call has a Step as a parent, and a Step has no Parameters.
{
//get the parent job
Job parent = jcsJob.getParentJob();
//get the job parameters and respective values
JobParameter parentName = parent.getJobParameterByName("pName");
JobParameter parentName2 = parent.getJobParameterByName("pName2");
Object parentNameInValue = parentName.getInValue();
Object parentName2InValue = parentName2.getInValue();
//log the values of the parent parameters
jcsOutLog.info("Parent Parameter pName is set to " + parentNameInValue);
jcsOutLog.info("Parent Parameter pName2 is set to " + parentName2InValue);
//set the Out value of the current (child) job
jcsJob.getJobParameterByName("childParam").setOutValue("Done");
jcsSession.persist();
}
Accessing Workflow Parameters
In this example, a Job Call retrieves Workflow-level Parameters.
{
//get the step job (up one level)
Job step = jcsJob.getParentJob();
//get the inner-most chain process (up another level)
Job parent = step.getParentJob();
//get the parameters and respective values
JobParameter chainName = parent.getJobParameterByName("pName");
JobParameter chainName2 = parent.getJobParameterByName("pName2");
Object chainNameInValue = parentName.getInValue();
Object chainName2InValue = parentName2.getInValue();
//log the values of the parameters
jcsOutLog.info("Parent Parameter pName is set to " + chainNameInValue);
jcsOutLog.info("Parent Parameter pName2 is set to " + chainName2InValue);
//set the Out value of the current job
jcsJob.getJobParameterByName("JobpName").setOutValue("Done");
jcsSession.persist();
}
Another example:
{
//get the parameters and respective values
JobParameter chainName = jcsJob.getParentJob().getParentJob().getJobParameterByName("pName");
JobParameter chainName2 = jcsJob.getParentJob().getParentJob().getJobParameterByName("pName2");
//log the values of the parent parameters
jcsOutLog.info("Parent Parameter pName is set to " + chainName);
jcsOutLog.info("Parent Parameter pName2 is set to " + chainName2);
//set the Out value of the current (child) job
childParam = "Done";
jcsSession.persist();
}
Deleting Jobs that Ran on a Job Server Using executeObjectQuery
Assume you want to delete all the Jobs on a Job Server because you want to delete the Job Server. The following example illustrates how to delete all the processes that ran on Job Server MSLN_WINS3
.
{
// Note that the following query uses query parameters for the
// query. User content should never be injected directly into
// the SQL query that is sent to the database.
String query = "select Job.* from Job where ProcessServer = ?";
for (Job process : jcsSession.executeObjectQuery(Job.TYPE, query, new Object[] {jcsSession.getProcessServerByName("MSLN_WINS1").getUniqueId()}))
{
if(process.getStatus().getState() == JobStatusState.Final)
{
jcsOut.println("Deleting process "
+ process.getDescription()
+ ", which has the status "
+ process.getStatus()
+ ".");
process.deleteObject();
}
jcsSession.persist();
}
}
Counting the Number of Jobs on a Job Server using executeQuery
{
LongCallBack callback = new LongCallBack(1);
String query = "select count(*) from Job where Job.ProcessServer = ?";
try
{
jcsSession.executeQuery(query, new Long[] { jcsSession.getProcessServerByName("MSLN_WINS3").getUniqueId() }, callback);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
Long myCount = (Long) callback.getResult().get(0);
if (myCount != null)
{
jcsOut.println(myCount);
}
}
Creating Workflow Definitions in RedwoodScript
Creating Workflow Definitions in RedwoodScript is a multi-step process. You must first create a JobDefinition
, then create a JobChain
and set the Workflow Definition to your newly created Job Definition. You can then create child Steps and Job Call children of the Steps.
{
String pName = "RW_DEMO";
String jDefinitionName = "JC_Sleep";
String stepName = "Step 1";
//get or create a Partition (here we create one if it does not exist)
Partition Partition = jcsSession.getPartitionByName(pName);
if (partition == null)
{
Partition = jcsSession.createPartition();
Partition.setName(pName);
}
JobDefinition jDefinition = jcsSession.getJobDefinitionByName(partition, jDefinitionName);
if (jDefinition == null)
{
//Create JobDefinition of type JOB_CHAIN
jDefinition = jcsSession.createJobDefinition();
jDefinition.setName(jDefinitionName);
jDefinition.setJobDefinitionType(jcsSession.getJobDefinitionTypeByName(JobDefinitionType.JOB_CHAIN));
jDefinition.setPartition(partition);
//Create jobchain object with one step and one job chain call
JobChain jWorkflow = jcsSession.createJobChain();
jWorkflow.setJobDefinition(jDefinition);
//step
JobChainStep jcStep = jWorkflow.createJobChainStep();
jcStep.setSequenceNumber(Long.valueOf(0));
jcStep.setName(stepName);
//job chain call (chain process)
JobChainCall jcCall = jcStep.createJobChainCall();
JobDefinition jDefinitionSleep = jcsSession.getJobDefinitionByName("System_Sleep");
jcCall.setJobDefinition(jDefinitionSleep);
jcCall.setSequenceNumber(Long.valueOf(0));
}
else
{
jcsOut.println("JobDefinition " + jDefinitionName + " exists!");
jcsOut.println("You can change the name of the JobDefinition on the line:\n String jDefinitionName = \"JC_Sleep\";");
}
jcsSession.persist();
}
Creating User Messages in RedwoodScript
{
String pName = "RW_DEMO";
String uMessageName = "UM_ReviewWorldSalesReport";
//get or create a Partition (here we create one if it does not exist)
Partition Partition = jcsSession.getPartitionByName(pName);
if (partition == null)
{
Partition = jcsSession.createPartition();
Partition.setName(pName);
}
JobDefinition jDefinition = jcsSession.getJobDefinitionByName(partition, uMessageName);
if (jDefinition == null)
{
JobDefinition jd = jcsSession.createJobDefinition();
jd.setName(uMessageName);
jd.setPartition(partition);
JobDefinitionType um = jcsSession.getJobDefinitionTypeByName("UserMessage");
jd.setJobDefinitionType(um);
UserMessageDefinition umd = jcsSession.createUserMessageDefinition();
umd.setJobDefinition(jd);
umd.setText("Please review world sales report.");
UserMessageDefinitionResponse umr = umd.createUserMessageDefinitionResponse();
umr.setStatus(JobStatus.Completed);
umr.setName("Done");
umr.setReturnCode(Long.valueOf(0));
umr = umd.createUserMessageDefinitionResponse();
umr.setStatus(JobStatus.Error);
umr.setName("Failed");
umr.setReturnCode(Long.valueOf(1));
UserMessageDefinitionParticipant umdp = umd.createUserMessageDefinitionParticipant();
umdp.setType(SubjectType.Role);
umdp.setName("scheduler-user");
//The following only works in a chain with a process at position 1,
//in the step named "Step 1" producing output in a file named stdout.log - for illustration
//purposes, only.
//UserMessageDefinitionAttachment umda = umd.createUserMessageDefinitionAttachment();
//umda.setDescription("World Sales Report");
//umda.setSpecification("Step 1, Job 1:stdout.log");
}
else
{
jcsOut.println("JobDefinition " + uMessageName + " exists!");
jcsOut.println("You can change the name of the JobDefinition on the line:\n String uMessageName = \"UM_ReviewWorldSalesReport\";");
}
jcsSession.persist();
}
Creating a Job File in RedwoodScript
{
JobFile jf = jcsJob.createJobFile();
jf.setFileType(JobFileType.Output);
jf.setName("SomeTextFile.txt");
jf.setFormat(jcsSession.getFormatByName("HTMLText")); //You can also create your own in Definitions > Formats
jf.setOrder(JobFile.CUSTOMER_ORDER_START); //Sort order must be >= CUSTOMER_ORDER_START
jcsOut.println(jf.getType().getCodeExString());
jf.setFileNameAutomatic(); //Filename must be generated
jcsSession.persist();
String fileToWriteTo = jf.getFileName();
//Standard Java code to create and populate the actual file
java.io.PrintWriter writer = new java.io.PrintWriter(fileToWriteTo, "UTF-8");
writer.println("The first line");
writer.println("The second line");
writer.close();
}