> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/reference/shipped-batch-tasks.md).

# Shipped batch tasks

Every batch task OpenIAM ships with its task ID, cron expression, backing bean and shipped enabled state, the thirteen beans a task may run, and the rows that cannot run at all.

## What this is, and when you need it

Several OpenIAM behaviours administrators expect to be automatic are batch tasks that ship **disabled**, and several they expect to be manual are batch tasks that ship **enabled**. This page states both, and settles the count.

**Fifteen named batch tasks ship, and four of them ship enabled.** The seed also contains nine legacy numeric rows, task IDs `100` to `108`, which are all disabled and carry no bean — so the raw `BATCH_CONFIG` row count on a fresh installation is 24. That is where the two different numbers in circulation come from: 15 is the number of tasks, 24 is the number of rows. Use 15.

Each row is a `BATCH_CONFIG` row. The **task ID** is the stable identifier; the **name** is what **Administration → Batch Tasks** shows; the **bean and method** is what the batch-task-manager service log prints when a run starts, which is what you look for when a task's outcome is in doubt. Confirm any row's live state on that screen — this table is what ships, not what your deployment currently runs, and `LAST_EXEC_TIME` on each row tells you whether it has in fact been running.

## The fifteen named tasks

| Task ID                          | Name                                              | Cron             | Ships enabled | Bean and method                                                             |
| -------------------------------- | ------------------------------------------------- | ---------------- | ------------- | --------------------------------------------------------------------------- |
| `ACTIVATION_REMINDER_BATCH_TASK` | Activation reminder                               | `0 0 0 ? * *`    | no            | —                                                                           |
| `AUTO_REVOCATION`                | Notification of expiring/revoke of expired access | `0 0 20 * * ?`   | no            | `revocationOfEndDatedAccess.initializeRevocationOfEndDatedAccess`           |
| `CLEANUP_CSV`                    | Cleanup OLD CSV Files                             | `0 0 1 * * ?`    | no            | `cleanOldCSVInitializer.start`                                              |
| `CLEAN_AUTH_STATE_TABLE`         | Clean Auth State table                            | `0 0 0 1/1 * ?`  | **yes**       | `cleanAuthStateTableInitializer.initializeCleanAuthStateTable`              |
| `DELETE_PENDING`                 | Delete/Deactivate by last Data                    | `0 0/30 * * * ?` | no            | —                                                                           |
| `FAILED_REQ_REPORT`              | Failed provision requests report                  | `0 0 0 1/1 * ?`  | no            | —                                                                           |
| `FUTURE_USER_PROV`               | Provision Deprovision on date                     | `0 0 0 1/1 * ?`  | no            | `provisionDeprovisionOnDateInitializer.initializeProvisionDeprovisonOnDate` |
| `LEAVER_PROCESS`                 | Disable by last date                              | `0 0 17 * * ?`   | **yes**       | `leaverProcessInitializer.initializeLeaverProcess`                          |
| `PERFORM_BR_REPROVISION`         | Perform Business Rules recalculation              | `0 0 0 * * ?`    | no            | `businessRuleRecalculationInitializer.perform`                              |
| `PROV_BY_START_DATE_FUT`         | Activate by Start Date                            | `0 0 0 1/1 * ?`  | **yes**       | `provisionAfterStartDateInitializer.initializeProvisionAfterStartDate`      |
| `PRUNE_AUDIT_LOGS`               | Prune Audit Logs                                  | `0 0 0 1/1 * ?`  | no            | `pruneAuditLogsInitializer.prune`                                           |
| `REQUEST_ESCALATION`             | Escalation of expired requests                    | `0 0 0 1/1 * ?`  | no            | `requestEscalationInitializer.initializeEscalation`                         |
| `REQUEST_REMINDERS`              | Notification reminders for approvers              | `0 0 0 1/1 * ?`  | no            | `requestRemindersInitializer.initializeSendReminders`                       |
| `RISK_NIGHTLY_SWEEP`             | Risk Manager nightly sweep                        | `0 0 2 * * *`    | **yes**       | `riskNightlySweepInitializer.perform`                                       |
| `TASK_EMAIL_NOTIFICATION`        | Task Email Notification                           | `0 0 0 1 1/3 ?`  | see below     | `taskEmailNotifier.sweep`                                                   |

## The four tasks that run on a default installation

* `CLEAN_AUTH_STATE_TABLE` — Clean Auth State table, midnight daily.
* `LEAVER_PROCESS` — Disable by last date, 17:00 daily.
* `PROV_BY_START_DATE_FUT` — Activate by Start Date, midnight daily.
* `RISK_NIGHTLY_SWEEP` — Risk Manager nightly sweep, 02:00 daily.

Two of those four take a value on the task row that changes what they select:

* **`LEAVER_PROCESS` reads its window from Parameter 1.** The shipped script searches for End dates between *n* days ago and midnight this morning, where *n* is the task's first parameter, and **an empty Parameter 1 selects nobody** — the task runs every evening, searches an empty range, finds nothing and reports success. It applies whatever the script named by `org.openiam.idm.leaver.script` does, shipped `batch/LeaverProcess.groovy`; editing that script means editing a live nightly job that disables people. The days-before-leaver value moved onto the task row in 4.2.1.3 from a property that no longer exists, so that number is on the task, not in a property file.
* **`PROV_BY_START_DATE_FUT` ships with Parameter 1 set to `1`**, so it activates identities whose start date falls within the next day.

## The tasks people assume are automatic and are not

* **`PRUNE_AUDIT_LOGS`.** Combined with the `-1` retention defaults, nothing prunes the audit log until you change both the task and the properties. See [Audit actions and retention](/administration-guide/reference/audit-actions-and-retention.md).
* **`REQUEST_ESCALATION` and `REQUEST_REMINDERS`.** Approval reminders and escalation of expired requests do not happen out of the box. This is the usual root cause of "approvals just sit there".
* **`AUTO_REVOCATION`.** An end date on a membership does not by itself revoke anything on the day it passes.
* **`PERFORM_BR_REPROVISION`.** Business-rule recalculation is **not** scheduled. The task was seeded enabled in `4.2.1.0` and deliberately disabled again as of `4.2.1.5`, so a fresh install has it off. Rule changes therefore apply to users who are saved, not overnight — plan an explicit recalculation after a rule change, and confirm the state on **Administration → Batch Tasks** before you assume either way, since an installation upgraded from `4.2.1.0` may still carry the enabled row. See [Build a business rule](/administration-guide/access/business-rules.md).

## The row that cannot run

`TASK_EMAIL_NOTIFICATION` has no explicit enabled value in its seed and takes the column default, which is `N` — so it ships disabled by omission. Read its state from the deployed database rather than assuming.

{% hint style="danger" %}
**Do not enable it.** Its Spring bean, `taskEmailNotifier`, exists only in the **workflow** service, and a batch task can only run a bean the batch-task-manager service itself holds. It is absent from the thirteen pairs the Webconsole offers, which is why the Webconsole refuses to re-save the row at all and answers *Spring Bean is invalid…*. Enabling it produces a failed run logging `Can't invoke spring thread`. Approver reminders come from `REQUEST_REMINDERS` instead. Raise it with support rather than inventing a bean name.
{% endhint %}

`FUTURE_USER_PROV`, from 4.2.1.6 onward, names `provisionDeprovisionOnDateInitializer`, which exists in the batch-task-manager service but is **not** declared runnable from a batch task and so is not in the thirteen offered pairs. The row still runs; you simply cannot edit and re-save it from the Webconsole without changing the bean, because the save is rejected with *Spring Bean is invalid…*.

## The thirteen executable beans

These are the only `bean.method` pairs a batch task may name, and they are exactly what the **Execution Script** dropdown renders when you choose **Execute a Spring Bean**. The list is built once when the batch-task-manager service starts, so the dropdown on your release — not this page — is authoritative.

| Bean name                              | Method                                 | Takes `param1`?        |
| -------------------------------------- | -------------------------------------- | ---------------------- |
| `autoUnlockInitializer`                | `perform`                              | no                     |
| `businessRuleRecalculationInitializer` | `perform`                              | no                     |
| `accessCertificationInitializer`       | `initializeAccessCertification`        | yes (certification ID) |
| `cleanAuthStateTableInitializer`       | `initializeCleanAuthStateTable`        | no                     |
| `cleanOldCSVInitializer`               | `start`                                | yes (days)             |
| `leaverProcessInitializer`             | `initializeLeaverProcess`              | yes (date range)       |
| `provisionAfterStartDateInitializer`   | `initializeProvisionAfterStartDate`    | yes (days)             |
| `pruneAuditLogsInitializer`            | `prune`                                | no                     |
| `requestEscalationInitializer`         | `initializeEscalation`                 | no                     |
| `requestRemindersInitializer`          | `initializeSendReminders`              | no                     |
| `revocationOfEndDatedAccess`           | `initializeRevocationOfEndDatedAccess` | no                     |
| `riskNightlySweepInitializer`          | `perform`                              | no                     |
| `sodViolationDigestInitializer`        | `perform`                              | no                     |

Note the bean name for revocation is `revocationOfEndDatedAccess`, without the `Initializer` suffix every one of its siblings carries. Note also that `autoUnlockInitializer` and `sodViolationDigestInitializer` are offered by the dropdown but no shipped task row names either of them: they are available for a task you create.

**How `param1` reaches a bean method.** OpenIAM chooses the method by whether **Parameter 1** is populated: with `PARAM1` empty it looks for a no-argument method, and with `PARAM1` set it looks for one that takes a single string. So putting a value in **Parameter 1** for a no-argument method such as `pruneAuditLogsInitializer.prune` makes the lookup find nothing, the run does nothing, and `LAST_EXEC_TIME` never advances — with no error to read. `PARAM2`–`PARAM4` are never passed to a bean at all.

## Tasks whose behaviour comes from a property, not the row

Three shipped tasks run a product-provided method that itself instantiates a Groovy **class** chosen by a property. Those scripts are classes rather than script bodies, and they do **not** return an integer:

| Property                                                                               | Shipped default                                                | Your script extends               |
| -------------------------------------------------------------------------------------- | -------------------------------------------------------------- | --------------------------------- |
| `org.openiam.provision.after.start.date.initializer`                                   | `batch/ActivateProcess.groovy`                                 | `AbstractActivateProcess`         |
| `org.openiam.idm.leaver.script`                                                        | `batch/LeaverProcess.groovy`                                   | `AbstractLeaverProcess`           |
| `org.openiam.batch.synchronization.script` / `org.openiam.batch.reconciliation.script` | `batch/synchronization.groovy` / `batch/reconciliation.groovy` | nothing — these are script bodies |

`AbstractActivateProcess` declares exactly one method for you to implement:

{% code overflow="wrap" %}

```groovy
void activate(User user, String auditLogId)
```

{% endcode %}

### Which inherited service fields your script can use

Both base classes give your script a set of OpenIAM service fields it can call without declaring them — `context`, `propertyValueCache`, `provisionService`, `userRabbitMQService`, `resourceService`, `roleDataWebService`, `groupDataWebService`, `activitiService`, `managedSystemWebService`, `mailService`, `passwordMQService`, `certMqService`, `auditLogHelper`, `jacksonMapper` and `scriptRunner`. **The two tasks do not fill them the same way, and this is the single most common reason a working leaver script fails when its shape is copied into an activation script.**

**On the leaver path every inherited field is populated.** `LEAVER_PROCESS` constructs your `AbstractLeaverProcess`, then calls `init()`, which wires the whole set through Spring. That is why the shipped `batch/LeaverProcess.groovy` calls `userRabbitMQService` and `provisionService` bare and works, and it is the supported style: write your leaver script the same way. If you override `init()`, call the inherited one first or nothing is wired at all.

**On the activate path nothing is wired, and ten names are injected by hand.** `PROV_BY_START_DATE_FUT` constructs your `AbstractActivateProcess` and never calls `init()`. Instead it sets values onto fields matching exactly ten names: `context`, `propertyValueCache`, `provisionService`, `resourceService`, `mailRabbitMQService`, `activitiRabbitMQService`, `activitiService`, `userRabbitMQService`, `groupDataWebService` and `roleDataWebService`. Two of those ten — `mailRabbitMQService` and `activitiRabbitMQService` — are not the names of any inherited field, so they land nowhere unless your own class declares a field of that name; a name with no matching field is skipped, and the line saying so appears only when the service is running with debug logging on. So the fields you can use on the activate path are `context`, `propertyValueCache`, `provisionService`, `resourceService`, `userRabbitMQService`, `groupDataWebService`, `roleDataWebService` and `activitiService`, plus either of the two mismatched names if you declare it yourself. Everything else the class inherits — `mailService`, `passwordMQService`, `managedSystemWebService`, `certMqService`, `auditLogHelper`, `jacksonMapper` and `scriptRunner` — is **null**. For mail on that path, declare your own `mailRabbitMQService` field; for anything not on the list of ten, resolve it from the injected `context` rather than inheriting it.

{% hint style="danger" %}
**The shipped `batch/ActivateProcess.groovy` cannot complete on this build, and `PROV_BY_START_DATE_FUT` ships enabled.** It uses `passwordMQService` and `mailService`, both of which are null on the activate path. Its first two steps work — the identity is saved with its new status through `provisionService`, so the account is created — and it then fails on a null reference before it generates the password-reset token or sends `NEW_USER_ACTIVATION_NOTIFICATION`. The observable result is an activated identity that never receives its activation mail, a null-reference stack in the batch-task-manager log, and the rest of that window's identities left unprocessed because the run stops at the first one. Prove it on one disposable future-dated identity before you rely on activation by start date, and raise it with support; a replacement script must obtain those two services itself. See [Disable leavers automatically](/administration-guide/lifecycle/disable-leavers-automatically.md) for a leaver script written against the fields that *are* populated.
{% endhint %}

## The nine legacy numeric rows

Task IDs `100`, `101`, `102`, `103`, `104`, `105`, `106`, `107` and `108` ship disabled, with no cron expression and, with one exception, no bean. Their names describe behaviours that later moved elsewhere: `ACCOUNT_LOCKED_NOTIFICATION`, `INACTIVE_USER`, `PASSWORD_NEAR_EXP`, `TERMINATE_EXP_ACCT`, `AUTO_UNLOCK`, `RESET_PSWD_CHNG_COUNT`, `PUBLISH_AUDIT_EVENT`, `PASSWORD_EXPIRED` and `PROV_ON_STARTDATE`. Only `104`, `AUTO_UNLOCK`, carries a bean — `autoUnlockInitializer.perform`.

They are not part of the supported task set. Do not enable them; where the behaviour is still wanted, create a task of your own naming the bean or script you intend.

## Tasks withdrawn by a later release

These task IDs were seeded by an earlier release and removed by a later one. A runbook or document that names one is out of date, and a row still present under one of these IDs on an upgraded installation is a leftover:

`ACC_CERT_GEN_REPORT`, `ACC_NTFC_REMINDER_BT_`, `ATTESTATION`, `CANCEL_UAR_CAMPAIGN_REQ`, `GROUP_ATTESTATION`

## Tasks are seeded across more than one schema

Most tasks are seeded in the `openiam` schema, but not all — `RISK_NIGHTLY_SWEEP` lives in `batchtasks`. A break-glass query for a task ID that only looks in `openiam` will come back empty and tell you the task does not exist, which is wrong. Query `BATCH_CONFIG` in both schemas, or read the state from **Administration → Batch Tasks**, which shows tasks from both.

## Related

* [Create a batch task](/administration-guide/automation/batch-tasks.md) — creating one, the bindings, the validation errors and the two timers
* [Restart batch tasks that have all stopped](/administration-guide/automation/batch-tasks/diagnose-stalled-batch-tasks.md) — the schedule table and the backlog that stops everything
* [Run a synchronization on a schedule](/administration-guide/automation/batch-tasks/schedule-a-synchronization.md) — the commonest task you will create
* [Shipped Groovy scripts](/administration-guide/reference/shipped-groovy-scripts.md) — the fourteen scripts under `batch/`
* [Audit actions and retention](/administration-guide/reference/audit-actions-and-retention.md) — `BATCH_TASK_EXECUTE` and the `-1` retention defaults

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/reference/shipped-batch-tasks.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
