This is an old revision of the document!


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.

Ways of item selection:

  • Individual item selection - When user checks individual items in a table such items are chosen to be processed by bulk action. IDs of these items are sent to BE together with type of the selected bulk action.
  • Selection by items - In case of using of the checkbox which marks all items as selected, selection is controlled by filter. Individual items may be unchecked by which they are added to the list of items excluded from processing. Such filter setting is sent to BE together with the list of excluded items.

* Applying action without item specification - The last supported option is to apply bulk action to the whole agenda. This option is by default disabled and needs to by enabled in BE bulk action implementation by overloading method showWithoutSelection returning true value. This option may be combined with previous two ways of selection which are controlled by another method showWithSelection with default returning value set to true.

After controller reception 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. In abstract parent of all bulk action AbstractBulkAction provides basic validation method for form attributes and functionality of sending notification message.

Abstract parent for bulk actions 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 implemntation of processEntities method. This method processes supplied entities returns operation result. If this method throws an exception it is caught by parent method and will be created a new failure log item.

After every success or failed process for identity will be created log item with result model. This log items are saved into processed items. This is same table as for schedulable task, but without removing or check existing items. It is used only for log results from process items. There isn't any another logic.

It is necessary for check permission for every process items and return exception (ForbiddenEntityException) or result model with NOT_EXECUTED state. This check is for identity done by abstract class (AbstractBulkAction method checkPermissionForIdentity).

In some cases, we need obtain additional informations and show them to the user before bulk operation starts. For example operation for invoke account management for all identities witch the role. In this case we want to show how many identites has that role (before start).

Prevalidate feature was developed exactly for this case. Every bulk operations has method `prevalidate`, returns the `ModelResults`.

Every `ResultModel` in `infos` list will be show 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;
	}
Now is possible add new bulk action only for identites. In future will be implement bulk actions for another agendas.

For easy start with creating new bulk action you can simple extends from abstract class AbstractBulkAction. Child is simple override methods:

  • processIdentity - process one identity,
  • getName - name of bulk action, this will be used for key in localization,
  • getPermissionForIdentity - required permission for process one identity,
  • getOrder - order in selecbox in identity agenda.
  • getLevel - level for bulk action button (success by default).

If you want use some settings for the bulk action you also must override method getFormAttributes. The method returns list of form attributes. With create the list of form attributes you can see example bulk action.

For all bulk actions doesn't exist form definition. Bulk action only return IdmFormAttributeDto. The IdmFormAttributeDto isn't persist.

After you implement all required method's and behavior for bulk action is necessary add localization for bulk action. For bulk actions is separate section in each localization. The section starts with bulkAction. Next key is actions and then name of your bulk action. For example: eav.bulk-action.<my-new-bulk-action>. Localization for form attributes is placed in localization with key: eav.bulk-action.<my-new-bulk-action>.attributes.

When we need add new agenda that will be support bulk actions on backend is necessary made this required steps:

  1. implements two method's in controller for specific agenda (for example you can check IdmIdentityController):
    • getAvailableBulkActions - return all available bulk action for the entity,
    • bulkAction - process the bulk action.
    • prevalidateBulkAction - prevalidate the bulk action.
  2. into frontend service change service's boolean with bulk action to true
    • supportsBulkAction=true

Now you can start use bulk actions.

  • by husniko