Table of Contents

Bulk actions

Bulk actions were introduced to IdM in order to make actions, applied to items in a table, more efficient and safe. Higher efficiency means that there is sent to BE only a list of IDs of affected items or items can also be selected by filter. Filter is accompanied with the list of IDs of items excluded from that action. Safety is reached by adding a validation feature which is, if implemented for particular action, evaluated before bulk action itself and is intended for notification of users that there may occur some conflicts which may prevent from successful action completion.

How it works?

Ways of item selection:

* Applying action without item specification - The last supported option is to apply bulk action to the whole agenda without any item specification. All items are included. This option is by default disabled and needs to by enabled in BE bulk action implementation by overloading method showWithoutSelection returning true value.

Every agenda is allowed to have more implemented bulk actions for different purposes. It is possible to combine all selection strategies. First two selection strategies are controlled by another method showWithSelection with default returning value set to true.

Available bulk actions are shown with respect currently logged user authorities - required authority can be specified in bulk action getAuthoritiesForEntity method.

After that controller receives a new bulk action request (rest post method), it transforms given map<String, Object> to filter and executes new bulk action as new long running task. Abstract parent of all bulk action classes AbstractBulkAction provides basic validation method for form attributes and functionality of sending notification message. It also ensures processing of the set filter or received set of IDs. In case of using filter, IDs to process are obtained by findIds method invocation with given filter. From this moment the set of IDs cannot be changed. All bulk actions has implementation of processEntities method. This method processes supplied entities and returns operation result. If this method throws an exception it is caught by parent method and a new failure log record is created.

After processing entity (regardless whether successful or not) a new log with result is created. These log items are saved into processed items in the same table as schedulable tasks are but without removing or checking that item exists. It is necessary to check permission for every processed item and return exception (ForbiddenEntityException) or ResultModels with NOT_EXECUTED state. This check is provided by abstract class method checkPermissionForEntity.

Prevalidate

In some cases, we need to obtain additional information and show it to user before bulk operation starts. For example operation invoking account management for all identities with specific role. In this case we want to show how many identities has assigned that role (before operation starts).

Prevalidate feature was developed exactly for this purpose. Every bulk operation implements method `prevalidate` which is supposed to be overloaded by developer. Overloaded method implements entire process of validation and its result is stored into info list of the `ResultModels` object which is returned from this method. Items in the info list are ResultModel objects consisting of AccResultCode and a Map of values which are then rendered on the FE.

Every `ResultModel` record in `infos` list will be shown on the bulk action detail.
Messages are defined as standard result codes. See code `AccResultCode.ROLE_ACM_BULK_ACTION_NUMBER_OF_IDENTITIES` in the example below.

There is example implementation of the prevalidate method in the `RoleAccountManagementBulkAction`:

@Override
	public ResultModels prevalidate() {
		IdmBulkActionDto action = getAction();
		List<UUID> entities = getEntities(action, new StringBuilder());
		ResultModels result = new ResultModels();
 
		Map<ResultModel, Long> models = new HashMap<>();
		entities.forEach(roleId -> {
			IdmIdentityRoleFilter identityRoleFilter = new IdmIdentityRoleFilter();
			identityRoleFilter.setRoleId(roleId);
			IdmRoleDto role = getService().get(roleId);
 
			long count = identityRoleService.find(identityRoleFilter, null).getTotalElements();
			if (count > 0) {
				models.put(new DefaultResultModel(AccResultCode.ROLE_ACM_BULK_ACTION_NUMBER_OF_IDENTITIES,
						ImmutableMap.of("role", role.getName(), "count", count)), count);
			}
		});
 
		boolean someIdentitiesFound = models.values() //
				.stream() //
				.filter(count -> count > 0) //
				.findFirst() //
				.isPresent(); //
 
		if (!someIdentitiesFound) {
			result.addInfo(new DefaultResultModel(AccResultCode.ROLE_ACM_BULK_ACTION_NONE_IDENTITIES));
		} else {
			// Sort by count
			List<Entry<ResultModel, Long>> collect = models //
					.entrySet() //
					.stream() //
					.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) //
					.limit(5) //
					.collect(Collectors.toList()); //
			collect.forEach(entry -> {
				result.addInfo(entry.getKey());
			});
		}
 
		return result;
	}

Configuration

@since 10.6.0

Bulk action order, icon, level and other properties can be configured by application setting.

Available bulk action can be shown in bulk action agenda available from menu - Settings - Modules - Bulk actions

All configurable properties (e.g. order) are shown in frontend agenda. Bulk Action can be disabled (or enabled) directly from this agenda (other configurable properties will be added in future).

How can I add new bulk action?

New bulk action creation

For easy start of creating a new bulk action you need just extend the abstract class AbstractBulkAction. Descendant then simply overrides used methods:

If one wants to use some settings of the bulk action it is necessary to override getFormAttributes method too. This method returns list of form attributes displayed in the window on FE.

Bulk actions don't use persistent form definition kept in IdmFormAttributeDto. This definition is created ad hoc by calling getFormAttributes method.

After implementation of all BE parts enabling support of the required bulk action, it is also necessary to add its localization. It needs to be put into section following this path eav.bulk-action.<my-new-bulk-action> in all localization files. Form attribute localization parts are placed into eav.bulk-action.<my-new-bulk-action>.attributes section.

"provisioning-operation-cancel-bulk-action": {
   "label": "Cancel operation",
   "help": "Cancel provisioning operations.",
   "icon": "fa:ban",
   "attributes": {
      "retrywholebatch": {
         "label": "Cancel full batch",
         "help": "Cancel all operations for entity in queue? After uncheck will be canceled only selected operation in queue."
      }
   }
}

How can I add support for bulk action?

In order to add support of bulk actions for particular agenda, it is necessary to implement following methods.

  1. in BE controller class (for example you can check IdmIdentityController):
    • getAvailableBulkActions - returns all available bulk actions (mandatory)
    • bulkAction - processes the bulk action (mandatory)
    • prevalidateBulkAction - invokes the bulk action prevalidation (optional)
  2. in FE service class (for inspiration see IdentityService)
    • supportsBulkAction - has to return true
    • showRowSelection - this Advanced.Table property needs to be set true without any permission conditions (permissions are resolved on BE)

Now you can start using bulk actions.