Package com.veeva.vault.sdk.api.job
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.
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 processor code. The following illustrates the 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.
Next, configure the job metadata for your job processor in the Vault UI. Learn more in Vault Help.@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(); List<JobTask> tasks = jobCompletionContext.getSuccessTasks(); for (JobTask task : tasks) { TaskOutput taskOutput = task.getTaskOutput(); logger.log(task.getTaskID() + " completed successfully " + taskOutput.getValue(s: "task: ", JobValueType.STRING)); } } 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.getErrorTasks(); 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)); } else if (TaskState.FAILED_TO_RUN.equals(taskOutput.getState())) { logger.log(task.getTaskID() + " failed to run " + 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:
- Participants control: To start a workflow with
JobService
, this must be set to Use roles as participants or Use custom action to define participants. - Date control: If a workflow has start options containing Date control, you can set this value when starting the workflow.
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.
-
ClassDescriptionInvoked by
JobService
to start a Job with the Vault Java SDK.A sequence of instructions that can be chained together, building a job cancellation operation which can be executed withJobCancelOperation.execute()
.Represents an unsuccessful attempt to cancel a job.Valid values for error types encountered during job cancellation.Represents a job cancellation request which can be submitted throughJobService.cancel(JobCancelRequest)
.Creates a new instance ofJobCancelRequest
.Represents a successful attempt to cancel a job.Context given toJob
's complete methods.Contains contextual information about the current job.Indicates a class is a job processor.Context given toJob.init(JobInitContext)
.An object returned byJob.init(com.veeva.vault.sdk.api.job.JobInitContext)
which allows the job to be chunked and processed correctly.Contains data about a single item in aJob
.Allows logging to the job log file.Contains information about a job's owner.Valid values for the job owner type, either a single user or a group.Provides methods to set values for job parameters.An interface to store data in a job context.Type of data supported by the Vault Java SDK for job parameters set onJobParameters
when invoking a job throughJobService
.Context given toJob.process(JobProcessContext)
.Contains information about aJob
's task results.Contains information about a job started throughJobService.runJob(JobParameters)
.Service interface to run jobs with specified parameters.Provides methods to get task information.An interface to store data in a job context.JobValueType<T>Type of data supported by the Vault Java SDK for parameters setting viaJob.init(JobInitContext)
andJob.process(JobProcessContext)
.Methods to get and set output parameters for a job task.Contains valid values to define the state of a task.