Skip navigation links

Package com.veeva.vault.sdk.api.job

This package provides interfaces to create job processors and execute asynchronous jobs.

See: Description

Package com.veeva.vault.sdk.api.job Description

This package provides interfaces to create job processors and execute asynchronous jobs.

You can invoke a job processor through any custom Vault Java SDK code. For example, you can create a trigger or action which executes the job processor under certain conditions.

You can also use a job processor as logic for a new Job Definition. For example, you can create a custom job definition available to Vault Admins to execute your custom code at scheduled or recurring intervals.

Job Limitations

Custom Job Processor: Update Managers

The following illustrates running a custom SDK job to update managers when a manager becomes inactive.

First, create the job metadata for your job processor using MDL:

 
 RECREATE Jobmetadata update_managers__c(
  active (true),
  label ('Update Managers'),
  description('Update manager when they become inactive'),
  chunk_size(10),
  job_code('Sdkjob.com.veeva.vault.custom.triggers.UpdateManagersJob')
 );
 
 
Next, create the job processor code. The following illustrates job processor code to update the manager for all Persons after a manager becomes inactive. The job replaces all references to the inactive manager with the 2nd-level manager.
  @JobInfo(adminConfigurable = true)
  public class UpdateManagersJob implements Job {
    public JobInputSupplier init(JobInitContext jobInitContext) {
       QueryService queryService = ServiceLocator.locate(QueryService.class);
       JobLogger logger = jobInitContext.getJobLogger();

       String oldManagerId = jobInitContext.getJobParameter("oldManagerId", JobParamValueType.STRING);
       String newManagerId = jobInitContext.getJobParameter("newManagerId", JobParamValueType.STRING);

       List<JobItem> jobItems = VaultCollections.newList();

       // Get ID's of all Persons who have the old manager
       String query = "SELECT id, (SELECT id FROM persons__sysr) from person__sys WHERE id = '" + oldManagerId +"'";
       logger.log("Running VQL query: " + query);
       QueryResponse response = queryService.query(query);
       logger.log("VQL query returned " + response.getResultCount() + " results");
       response.streamResults().forEach(queryResult -> {
       QueryResponse subResults = queryResult.getSubqueryResponse("persons__sysr");
       subResults.streamResults().forEach(subResult -> {
           JobItem employeeItem = jobInitContext.newJobItem();
           String employeeId = subResult.getValue("id", ValueType.STRING);
           employeeItem.setValue("employeeId", employeeId);
           employeeItem.setValue("newManagerId", newManagerId);
           jobItems.add(employeeItem);
           logger.log("Added new job item, employeeId = " + employeeId + ", newManagerId = " + newManagerId);
       });
       });
       return jobInitContext.newJobInput(jobItems);
    }

    public void process(JobProcessContext jobProcessContext) {
       RecordService recordService = ServiceLocator.locate(RecordService.class);
       JobLogger logger = jobProcessContext.getJobLogger();

       List<JobItem> items = jobProcessContext.getCurrentTask().getItems();
       List<Record> newRecords = VaultCollections.newList();
       for (JobItem employeeItem : items) {
           String employeeId = employeeItem.getValue("employeeId", JobValueType.STRING);
           String newManagerId = employeeItem.getValue("newManagerId", JobValueType.STRING);

           Record employeeRecord = recordService.newRecordWithId("person__sys", employeeId);
           employeeRecord.setValue("manager__sys", newManagerId);
           newRecords.add(employeeRecord);
           logger.log("Updated employee record, employeeId = " + employeeId + ", newManagerId = " + newManagerId);
       }

       JobTask task = jobProcessContext.getCurrentTask();
       TaskOutput taskOutput = task.getTaskOutput();
       BatchOperation<PositionalRecordId, BatchOperationError> batchResult = recordService.batchSaveRecords(newRecords);
       batchResult.onSuccesses(positionalRecordIds -> {
          taskOutput.setState(TaskState.SUCCESS);
          logger.log("Task successful");
       });
       batchResult.onErrors( batchOperationErrors -> {
          taskOutput.setState(TaskState.ERRORS_ENCOUNTERED);
          taskOutput.setValue("firstError", batchOperationErrors.get(0).getError().getMessage());
           logger.log("Task unsuccessful");
       });
       batchResult.execute();
    }

    public void completeWithSuccess(JobCompletionContext jobCompletionContext) {
       JobLogger logger = jobCompletionContext.getJobLogger();
       logger.log("All tasks completed successfully");
    }

    public void completeWithError(JobCompletionContext jobCompletionContext) {
       JobResult result = jobCompletionContext.getJobResult();

       JobLogger logger = jobCompletionContext.getJobLogger();
       logger.log("completeWithError: " + result.getNumberFailedTasks() + "tasks failed out of " + result.getNumberTasks());

       List<JobTask> tasks = jobCompletionContext.getTasks();
       for (JobTask task : tasks) {
           TaskOutput taskOutput = task.getTaskOutput();
           if (TaskState.ERRORS_ENCOUNTERED.equals(taskOutput.getState())) {
              logger.log(task.getTaskId() + " failed with error message " + taskOutput.getValue("firstError", JobValueType.STRING));
           }
       }
    }
  }
 
 
Finally, the following illustrates an SDK trigger which fires when a manager becomes inactive, and calls the job to update managers.
      @RecordTriggerInfo(object = "person__sys", events = {RecordEvent.AFTER_UPDATE})
      public class RunUpdateManagersJob implements RecordTrigger {
        public void execute(RecordTriggerContext recordTriggerContext) {
            JobService jobService = ServiceLocator.locate(JobService.class);
            JobParameters jobParameters = jobService.newJobParameters("update_managers__c");

            List<RecordChange> recordChanges = recordTriggerContext.getRecordChanges();
            for (RecordChange recordChange : recordChanges) {
                 Record newRecord = recordChange.getNew();
                 // When a Person becomes inactive, update the manager of all related Person objects
                 List<String> statusL = newRecord.getValue("status__v", ValueType.PICKLIST_VALUES);
                 if (statusL != null && "inactive__v".equals(statusL.get(0))) {
                     String oldManagerId = newRecord.getValue("id", ValueType.STRING);
                     String newManagerId = newRecord.getValue("manager__sys", ValueType.STRING);
                     jobParameters.setValue("oldManagerId", oldManagerId);
                     jobParameters.setValue("newManagerId", newManagerId);

                     JobRunResult result = jobService.runJob(jobParameters);
                 }
            }
        }
     }
     
 

Invoke Standard Job: Change State

The following illustrates running a job to invoke a lifecycle user action to change state:
     
     //Get an instance of job for invoking user actions
     JobService jobService = ServiceLocator.locate(JobService.class);
     JobParameters jobParameters = jobService.newJobParameters("record_user_action__v");

     //Run job to invoke user action to change state
     jobParameters.setValue("user_action_name", "change_state_to_in_use_useraction__c");
     jobParameters.setValue("records", records);
     jobService.run(jobParameters);
     
 
The user_action_name parameter value, change_state_to_in_use_useraction__c, is from the configured lifecycle. It is derived by taking the lifecycle user action label in lower case, replacing any spaces with underscore, and appending _useraction__c.

The records parameter specifies the set of records to change state.

Invoke Standard Job: Start Workflow

JobService supports the following controls: Learn more about start step controls in Vault Help.

JobService cannot start a workflow from a RecordAction with the LIFECYCLE_ENTRY_ACTION Usage.

The following illustrates running a job to invoke a lifecycle user action to start a workflow.

     
     //Get an instance of job for invoking user actions
     JobService jobService = ServiceLocator.locate(JobService.class);
     JobParameters jobParameters = jobService.newJobParameters("record_user_action__v");

     //Run job to invoke user action to start workflow
     jobParameters.setValue("user_action_name", "evaluate_country_brand_useraction__c");
     jobParameters.setValue("records", records);
     jobParameters.setValue("review_date__c", LocalDate.now().plusMonths(1));
     jobService.run(jobParameters);
     
 
The user_action_name parameter value, e.g. evaluate_country_brand_useraction__c, is from the configured lifecycle. It is derived by taking the lifecycle user action label in lower case, replacing any spaces with underscore, and appending _useraction__c. Note that your vault may name actions differently. To get the names of actions in your vault, Retrieve Object Record User Actions with the Vault REST API.

The records parameter specifies the set of records to start the workflow.

Skip navigation links

Copyright © Veeva Systems 2017–2020. All rights reserved.