You are viewing the documentation for an outdated or unreleased devel version.
This page is also available in versions: 8.1, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5 (current), devel

Bulk actions

Action types:

  • With items are selected - To backend is from frontend send whole filter definition or set of ids. When user check checkbox for select all entities is setup constat. The constant define that is selected all entities (constant can be found in basic table - Basic.Table.SELECT_ALL). When is this constant active user also can remove some entities from this select. The removed entities is saved to new set - removed entities and to backend is send in another property (removeIdentifiers).
  • Without items are selected - action can be executed without items are selected on frontend - can be used on the whole agenda for import / export feature or simply for all data in agenda.

Action type is defined by the action properties showWithoutSelection and showWithSelection and can be combined ⇒ one action could be executed with or without items are selected.

After specified controller receive new bulk action (rest post method). Controller transform given map<String, Object> to filter and execute new bulk action as new long running task. In abstract parent of all bulk action AbstractBulkAction provides basic validate method for form attributes and behavior with sending message.

Abstract parent for identity bulk actions has behavior with process filter or set of ids. If is used filter class perform method findIds by service with given filter. From this step is set of ids does't change. All identity bulk action has implemntation of method processIdentity. The method process one identity and return operation result. If this method throws exception is catch by parent method and it will be created new failed 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:

	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();
			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 -> {
		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.

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:

  • 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.
  • into frontend service change service's boolean with bulk action to true
    • supportsBulkAction=true

Now you can start use bulk actions.