Using RedwoodScript in Processes

RedwoodScript is the ideal language to automate complex tasks, adding custom code to a Chain Definition, for example. The following code will illustrate some example features you would like to implement. 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 Process Definition, please see the RedwoodScript, Redwood Expression Language, and Scripting Contexts sections for a list of examples, functions, contexts and predefined objects, respectively. Please note that the web-based shell does not have parent processes, so parent/child examples will not run in it.

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: When you set the Requested Start Time of a process, pay attention to not specify dates before 1901 or your process will be vetoed.

Create a Process Definition

To create a Process Definition, you first need to know if the Definition Type requires a source, then you create the Process Definition and source (in a Script object) and link the source to the process.

Copy
{
  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();
}

Access the Parameters

To access the current parameters, remember that the current process is already defined as jcsJob and the SchedulerSession is defined as jcsSession.

Copy
{
  jcsOut.println(Name);
  jcsOut.println(Address);
  jcsOut.println(City);
  jcsOut.println(Zip);
}

You can also use the process (technical name Job ) to retrieve the parameters and then their values. The below code is also used when you want to retrieve the values of parameters of other processes (replace the otherJob object with an object that points to the correct process).

Copy
{
  // 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();
}

Submit a Simple Job

Basic code to create a process from a Process Definition and submit the process, without specifying any parameters. If the Process Definition has parameters, the defaults will be used.

Copy
{
  // 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();
}

Submit a Simple Process with Parameters

The same basic code to submit a process used previously but this time with parameters. If you do not specify a value for a parameter, the default value will be used. Special care needs to be taken, if a Process Definition has a required parameter with no default value you must specify a value, or the process will not get submitted.

Copy
{
  // 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);
}

Submit a Simple Process with Parameters using REL Evaluation

The same basic code to submit a process with parameters used previously 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.

Copy
{
  // 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);
}

Access Parent/Child Parameters

A child process retrieves the parameter values of its direct parent. Remember that a Chain Process has a Step as a parent and a Step has no parameters.

Copy
{
  //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();
}

Access Chain Parameters

A Chain Process retrieves Chain-level parameters.

Copy
{
  //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:

Copy
{
  //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();
}

Delete Processes that ran on a Process Server, using executeObjectQuery

You want to delete all the processes of a Process Server because you want to delete the Process Server, you may proceed as follows:

The following example illustrates how to delete all the processes that ran on Process Server MSLN_WINS3.

Copy
{
  // 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();
  }
}

Count the number of Processes on a Process Server using executeQuery

Copy
{
  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 Chain Definitions in RedwoodScript

Creating Chain Definitions in RedwoodScript is a multi-step process, you first create a JobDefinition, you then create a JobChain and set the Chain Definition to your newly created JobDefinition. You can then create child Steps and Chain Process children of the Steps.

Copy
{
  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 jChain = jcsSession.createJobChain();
    jChain.setJobDefinition(jDefinition);
    //step
    JobChainStep jcStep = jChain.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

Copy
{
  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 JobFile in RedwoodScript

Copy
{
    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();
}