Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
tutorial:dev:scheduled_task [2017/11/04 08:55] poulm |
tutorial:dev:scheduled_task [2021/02/18 18:34] apeterova fixed links |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ===== Scheduled task with parameters ===== | ||
+ | {{tag> | ||
+ | CzechIdM supports three types of the so-called Scheduled tasks - business logic execution tasks running asynchronously outside of the main thread. There are following types: | ||
+ | * Long Running task - run from code, cannot be scheduled | ||
+ | * Scheduled task - run from Quartz scheduler, extends LRT | ||
+ | * Stateful task - run from Quartz scheduler, extends Scheduled task | ||
+ | |||
+ | You can find description of each tasks type in the [[devel: | ||
+ | |||
+ | ==== Scheduled task ==== | ||
+ | Simple scheduled tasks are the mostly used type of tasks. These are automatically registered in CzechIdM' | ||
+ | Following is an example of such task with parameters, which is supposed to read CSV from path passed as parameter and process it (not implemented for brevity purposes). Notice the `IMPORTANT` comments: | ||
+ | |||
+ | <code java> | ||
+ | package eu.bcvsolutions.idm.tutorial.scheduler; | ||
+ | |||
+ | import ...; | ||
+ | |||
+ | // IMPORTANT 1 | ||
+ | @Component | ||
+ | @Description(" | ||
+ | // IMPORTANT 2 | ||
+ | public class ImportCSVUserRolesTask extends AbstractSchedulableTaskExecutor< | ||
+ | |||
+ | private static final Logger LOG = LoggerFactory.getLogger(ImportCSVUserRolesTask.class); | ||
+ | private static final String PARAM_CSV_FILE_NAME = " | ||
+ | private static final String CSV_USERNAME_HEADER = " | ||
+ | private static final String CSV_ROLE_HEADER = " | ||
+ | |||
+ | private String csvPath; | ||
+ | |||
+ | @Autowired private IdmIdentityService identityService; | ||
+ | @Autowired private IdmRoleService roleService; | ||
+ | @Autowired private IdmIdentityRoleService identityRoleService; | ||
+ | @Autowired private IdmRoleRequestService roleRequestService; | ||
+ | @Autowired private IdmConceptRoleRequestService conceptRoleRequestService; | ||
+ | @Autowired private IdmIdentityContractService identityContractService; | ||
+ | |||
+ | // IMPORTANT 3 | ||
+ | @Override | ||
+ | public Boolean process() { | ||
+ | // path to CSV is required, also check file exists and is readable | ||
+ | if (csvPath == null) { | ||
+ | throw new IllegalArgumentException(" | ||
+ | } | ||
+ | // | ||
+ | // TODO processing :) | ||
+ | // | ||
+ | return Boolean.TRUE; | ||
+ | } | ||
+ | |||
+ | // IMPORTANT 4 | ||
+ | @Override | ||
+ | public List< | ||
+ | List< | ||
+ | params.add(PARAM_CSV_FILE_NAME); | ||
+ | return params; | ||
+ | } | ||
+ | |||
+ | // IMPORTANT 5 | ||
+ | @Override | ||
+ | public void init(Map< | ||
+ | super.init(properties); | ||
+ | csvPath = getParameterConverter().toString(properties, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | While implementing scheduled tasks, don't forget those 5 important pieces marked as comments in the code above: | ||
+ | * IMPORTANT 1 - all scheduled tasks are Spring Beans, don't forget to annotate the class as Spring' | ||
+ | * IMPORTANT 2 - all scheduled tasks extend the `AbstractSchedulableTaskExecutor` class | ||
+ | * IMPORTANT 3 - the `process` method contains the business logic you need to implement and is run by CzechIdM' | ||
+ | * IMPORTANT 4 - input parameters are defined by their names as list in the `getPropertyNames` method | ||
+ | * IMPORTANT 5 - input parameters (instance variables) are initialized in the `init` method, which is run before the `process`. Parameters and not strongly typed, `use parameters converter` for conversions. | ||
+ | ==== Stateful tasks ==== | ||
+ | It is also easily possible to execute workflow from a [[devel: | ||
+ | Following is an example of such task, which executes a workflow. | ||
+ | |||
+ | <code java> | ||
+ | package eu.bcvsolutions.idm.tutorial.scheduler; | ||
+ | |||
+ | import ...; | ||
+ | |||
+ | // IMPORTANT 1 | ||
+ | @Service | ||
+ | @Description(" | ||
+ | @DisallowConcurrentExecution | ||
+ | // IMPORTANT 2 | ||
+ | public class MyWorkflowProcess extends AbstractWorkflowStatefulExecutor< | ||
+ | |||
+ | private static final String PROCESS_NAME = " | ||
+ | |||
+ | @Autowired | ||
+ | private IdmIdentityContractService identityContractService; | ||
+ | |||
+ | /** | ||
+ | * Find all identity contracts, that are both valid and enabled. | ||
+ | */ | ||
+ | // IMPORTANT 3 | ||
+ | @Override | ||
+ | public Page< | ||
+ | IdentityContractFilter filter = new IdentityContractFilter(); | ||
+ | filter.setValid(Boolean.TRUE); | ||
+ | filter.setDisabled(Boolean.FALSE); | ||
+ | return identityContractService.find(filter, | ||
+ | } | ||
+ | |||
+ | // IMPORTANT 4 | ||
+ | @Override | ||
+ | public String getWorkflowName() { | ||
+ | return PROCESS_NAME; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | And following is the content of the [[devel: | ||
+ | * entity DTO which will be processed | ||
+ | * Long Running task's ID | ||
+ | * Stateful task ID | ||
+ | |||
+ | <code xml> | ||
+ | <?xml version=" | ||
+ | < | ||
+ | <process id=" | ||
+ | < | ||
+ | | ||
+ | // IMPORTANT 5 | ||
+ | Input: | ||
+ | longRunningTaskId - UUID | ||
+ | scheduledTaskId - UUID | ||
+ | dto - IdmIdentityContractDto</ | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | import org.slf4j.Logger; | ||
+ | import org.slf4j.LoggerFactory; | ||
+ | import eu.bcvsolutions.idm.core.api.domain.OperationState; | ||
+ | import eu.bcvsolutions.idm.core.api.entity.OperationResult; | ||
+ | import eu.bcvsolutions.idm.core.scheduler.api.service.SchedulableStatefulExecutor; | ||
+ | |||
+ | Logger LOG = LoggerFactory.getLogger(" | ||
+ | LOG.info(" | ||
+ | |||
+ | // TODO processing ... :) | ||
+ | |||
+ | def result = new OperationResult.Builder(OperationState.EXECUTED).build() | ||
+ | |||
+ | // IMPORTANT 6 | ||
+ | execution.setVariable(" | ||
+ | execution.setVariable(SchedulableStatefulExecutor.OPERATION_RESULT_VAR, | ||
+ | // | ||
+ | // process end | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | <!-- BPMN 2.0 diagram elements --> | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | While implementing stateful tasks with workflows, don't forget those important pieces marked as comments in the code above: | ||
+ | * IMPORTANT 1 - all workflow driven tasks are Spring Beans, don't forget to annotate the class as Spring' | ||
+ | * IMPORTANT 2 - all workflow driven tasks extend the `AbstractWorkflowStatefulExecutor` class | ||
+ | * IMPORTANT 3 - the `getItemsToProcess` method returns paged search criteria for all entities that should be processed | ||
+ | * IMPORTANT 4 - the `getWorkflowName` method returns the name of the Activiti workflow that will be run | ||
+ | * IMPORTANT 5 - input parameters of the workflow | ||
+ | * IMPORTANT 6 - execution result, the abstract base class `AbstractWorkflowStatefulExecutor` expects the OperationResult as a result of the workflow, for details see [[devel: | ||
+ | |||
+ | Scheduled and stateful tasks are a large topic in CzechIdM, definitely have a look at the documentation of [[devel: | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// |