> 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/connector-configuration/scriptconnector/script-development.md).

# Developing Groovy scripts for the Script connector

How to write, deploy and register the Groovy scripts that a Script connector runs — the handlers, the libraries they need, and what each one must return

[Configuring the Groovy Script connector](/connector-configuration/scriptconnector/groovyscriptconnector.md) covers setting one up against a target that already has scripts. This page is the other half: **writing those scripts**.

The connector itself is finished code. You do not build a connector — you write the Groovy that runs at four points in its lifecycle, and point the managed system at your scripts.

{% hint style="info" %}
The samples linked below are reference implementations, not drop-in code. The Script connector exists precisely because every target system differs, so expect to change them.
{% endhint %}

## How a request reaches your script

OpenIAM never calls your script directly. A provisioning request travels to the connector over RabbitMQ, and the connector looks up which Groovy script to run from the **object rule** fields on the managed system.

```mermaid
sequenceDiagram
    autonumber
    participant O as OpenIAM
    participant Q as RabbitMQ
    participant C as Script connector
    participant G as Your Groovy handler
    participant T as The target system
    O->>Q: Provisioning request, on the connector's queue
    Q->>C: The request, with the managed system's attributes
    C->>C: Read the object rule for this operation
    C->>G: Run the script at that path
    G->>T: Whatever the target needs — REST, SQL, anything Groovy can call
    T-->>G: The target's own response
    G-->>C: A connector object, or a status
    C-->>Q: The response, on the reply queue
    Q-->>O: Success or failure, recorded against the request
```

The script is the only part that knows the target. Everything either side of it is the connector's job, and you do not write it.

## The handlers

A handler is the absolute path to a Groovy script, stored in an object rule field on the managed system. Four fields, three scripts in most implementations:

| Object rule on the managed system | What the script is given                       | What it must return                                |
| --------------------------------- | ---------------------------------------------- | -------------------------------------------------- |
| **Test Connection Object Rule**   | The managed system's attributes                | A success or failure status                        |
| **Search Object Rule**            | A search query and the requested attributes    | Connector objects built from the target's response |
| **Add Object Rule**               | The user and the policy map's attribute values | A status, after creating the record                |
| **Modify Object Rule**            | The same, for an existing record               | A status, after updating the record                |

**Add and Modify usually share one script.** The script checks whether the record exists in the target, creates it if not, and updates or deletes it if so, branching on the request. One script for both rules means one place to maintain the logic, and it is the shape the samples use.

{% hint style="info" %}
If the target has no connectivity check of its own, the Test Connection script may simply return success without calling anything. It still has to exist — the connector runs whatever the field points at.
{% endhint %}

### Group operations use the same handlers

The object rules are the same for groups, but the scripts are not interchangeable: group scripts extend different base classes. Example group scripts are in [`iamscripts/dev/group/`](https://bitbucket.org/openiam/connector/src/test_run/conf/iamscripts/dev/group/).

## Writing each handler

Start from the sample closest to your target and replace the parts that talk to it. All three live in the [OpenIAM connector repository](https://bitbucket.org/openiam/connector/src/test_run/).

{% stepper %}
{% step %}
**Test connection.** Verifies that OpenIAM can reach the target. Returns a status and nothing else.

[`TestConnectionScriptConnector.groovy`](https://bitbucket.org/openiam/connector/src/test_run/conf/iamscripts/dev/sample_api/TestConnectionScriptConnector.groovy)
{% endstep %}

{% step %}
**Search.** Turns the target's own response — JSON from a REST API, rows from a database — into OpenIAM connector objects. Synchronization reads whatever this returns, so the attribute names it produces are the ones the policy map and the sync configuration will have to match.

[`SearchAPICallScriptConnector.groovy`](https://bitbucket.org/openiam/connector/src/test_run/conf/iamscripts/dev/sample_api/SearchAPICallScriptConnector.groovy)
{% endstep %}

{% step %}
**Add, modify and delete.** Saves, updates and deletes records, driven by the policy map configured on the managed system — the policy map decides which attributes reach the script, and the script decides what the target does with them.

[`SaveAPICallUserScriptConnector.groovy`](https://bitbucket.org/openiam/connector/src/test_run/conf/iamscripts/dev/sample_api/SaveAPICallUserScriptConnector.groovy)
{% endstep %}
{% endstepper %}

## Libraries available to a script

| Library                       | Used for                                         |
| ----------------------------- | ------------------------------------------------ |
| Jackson                       | JSON parsing and serialization                   |
| Apache HTTP Components        | HTTP requests and responses                      |
| Apache Commons Logging        | Logging script execution                         |
| OpenIAM API connector classes | Provisioning and metadata handling               |
| Spring Framework              | Dependency injection and the application context |
| Java Collections              | Lists, maps and the rest                         |
| Apache Commons Collections    | Utilities over those collections                 |

{% hint style="warning" %}
**A script can fail to save because a package is not whitelisted.** The Groovy sandbox refuses calls into packages that have not been allowed, and the error appears when you save rather than when the script runs. Add the package prefix to `org.openiam.groovy.extra.whitelist.package` — see [Groovy script reference](/administration-guide/reference/groovy-script-reference.md).
{% endhint %}

## Deploying the connector

A Script connector runs either beside OpenIAM or away from it:

|            | Where it runs               | How it reaches OpenIAM                                        |
| ---------- | --------------------------- | ------------------------------------------------------------- |
| **Local**  | The same machine as OpenIAM | Directly                                                      |
| **Remote** | Any other machine           | Over the RabbitMQ queue named in its `application.properties` |

[Add a connector](/installation/rpm/rpm-single-node/add-a-connector.md) covers installing and starting one on an RPM deployment.

### A remote connector needs RabbitMQ credentials

It gets them from Vault, which is where OpenIAM keeps them — so a remote host that cannot reach Vault cannot start.

{% hint style="warning" %}
**If the remote host has no route to Vault**, put the RabbitMQ credentials directly in `application.properties` instead. They are credentials in a file on a host you do not fully control, so encrypt them with whatever your deployment already uses rather than leaving them in plain text.
{% endhint %}

## Registering the connector

Register it in the Webconsole under **Provisioning → Connectors**, and make sure the **Connector Queue** on the record matches the queue the connector is listening on, character for character. A mismatch is silent: the connector starts, OpenIAM publishes, and nothing is ever delivered.

## One connector, several managed systems

A single Script connector can serve more than one target, as long as the targets work alike — two REST APIs of similar shape, or two databases with a similar schema. The handlers stay the same and the managed system supplies what differs.

{% stepper %}
{% step %}
**Create a managed system for each target.** Both point at the same connector, and both name the same handler scripts in their object rules.
{% endstep %}

{% step %}
**Put what differs in managed system attributes.** The API endpoint, the database name, anything else specific to that target. Custom attributes on the managed system are how the two are told apart.
{% endstep %}

{% step %}
**Read those attributes in the handler.** The script receives the calling managed system's attributes with the request, so the same logic runs against whichever target invoked it.
{% endstep %}
{% endstepper %}

This keeps one set of scripts for several applications instead of copies that drift apart.


---

# 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/connector-configuration/scriptconnector/script-development.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.
