my-sql-connector/
└── src/main/resources/
├── connector.manifest.json
├── Messages.properties
├── schema/
│ └── users.groovy
└── handlers/
└── user_ops.groovy
Custom connector classes and bundles
|
Since 4.11
This functionality is available since version 4.11.
|
Most connectors can be built without any Java code, just a manifest and scripts. This page covers both the manifest-based route and the Java subclass route.
This article is part of the SQL connector development reference and guidance materials. See How to develop connectors using the SQL framework for the section introduction.
Option 1: manifest-based connector (no Java)
ManifestBasedConnector reads connector.manifest.json / .yaml / .yml from the classpath of the connector bundle (the bundle JAR together with the JARs in its lib/ directory) and loads the declared schema and operation scripts (see Declarative YAML).
Bundle layout:
{
"connector": {
"schema": [
{ "script": "/schema/users.groovy" }
],
"operation": [
{ "script": "/handlers/user_ops.groovy" }
]
}
}
The connector class is com.evolveum.polygon.sql.base.groovy.impl.ManifestBasedConnector.
The generic SQL bundle in the repository ships with an empty manifest — add your scripts and rebuild, or reference the base bundle from your own assembly.
Notes:
-
Exactly one manifest may be bundled (
connector.manifest.json,.yamlor.yml) — bundling more than one is a packaging error. -
A script entry may carry
"disabled": true— the script is skipped in both real loading and script validation, as if it were not bundled at all. Useful to toggle a script without repackaging. -
Script paths are classpath resources; a leading
/means the classpath root.
Option 2: custom connector class (Java)
For programmatic control, use subclass AbstractGroovySqlConnector:
package com.example;
import com.evolveum.polygon.sql.base.AbstractGroovySqlConnector;
import com.evolveum.polygon.sql.base.SqlConnectorConfiguration;
import com.evolveum.polygon.sql.base.groovy.SqlHandlerLoader;
import com.evolveum.polygon.sql.base.groovy.SqlSchemaDefinitionLoader;
public class ExampleSqlConnector extends AbstractGroovySqlConnector<SqlConnectorConfiguration> {
public ExampleSqlConnector() {
super(false); // production: initialize once per instance
}
@Override
protected void initializeSchema(SqlSchemaDefinitionLoader loader) {
loader.loadFromResource("/schema/users.groovy");
// loadFromResource resolves .yaml/.yml when the .groovy file is missing
}
@Override
protected void initializeObjectClassHandler(SqlHandlerLoader loader) {
loader.loadFromResource("/handlers/user_ops.groovy");
// loader.loadFromString(...) and loader.register(objectClass, operationType, operation)
// are available for fully programmatic handler registration
}
}
Notes:
-
constructor argument
reinitializeOnEachCall— usetruein development (re-runs discovery and script loading on every call so script edits are picked up), andfalsein production (pool and handlers are initialized once). The manifest-basedManifestBasedConnectoralways usesfalse. -
When the configuration is incomplete (no
jdbcUrl/usernameor nopassword),schema()builds the schema from the bundled scripts alone — no connection pool is created and no discovery runs. This is useful for wizards and tooling that introspect a connector before a connection is configured. -
operation scripts share a single Groovy shell, so helper functions defined in one script are available to later scripts:
// /handlers/shared.groovy -- loaded first def activeUsers(int status) { return { e -> e.col("status").eq(status) } }
Java extension points
For behavior that goes beyond the DSL, the framework exposes programmatic hooks:
-
Custom mapping rules —
SqlSchemaTranslator.addResourceRule(…)andaddAttributeRule(…)register additional schema-mapping rules into the rule chain that runs after the built-in rules (see built-in mapping rules). -
Fully custom operations — the per-object-class operation support builder accepts
register(Class<T> operationType, T operation)to register a custom operation implementation;SqlHandlerLoaderalso providesloadFromString(…)andregister(objectClass, operationType, operation)for programmatic handler registration. -
Script loading —
SqlSchemaDefinitionLoader.loadFromResource(…)resolves a.yaml/.ymldocument when the referenced.groovyfile is missing from the bundle.
Script validation from the management system
In development mode (developmentMode true), the connector supports the ConnId runScriptOnResource SPI hook: the management system can submit a candidate Groovy script with the operation build or compile, and the connector validates it by evaluating the script against all sibling deployed scripts (the candidate replaces its own previous content; cross-references between scripts resolve). The validation result — compile errors or the built schema — is returned to the caller.
-
The hook is only enabled with
developmentMode true; outside development mode it fails withUnsupportedOperationException. -
Only
groovyscripts and thebuild/compileoperations are supported.
Packaging the bundle
The connector is packaged as a Java archive with all runtime dependencies in lib/:
mvn clean package
target/my-sql--connector*.jar
├── connector.manifest.json
├── Messages.properties
├── schema/...
├── handlers/...
└── lib/
├── (sql framework base jar)
├── hikariCP
├── groovy
├── querydsl-sql
└── your JDBC driver (e.g., postgresql-*.jar)
Make sure the JDBC driver for your database is in the dependency set (the SQL framework itself does not bundle drivers).
The Messages.properties file (at the root of the bundle, next to the manifest) provides the display labels for the configuration form: each entry maps a configuration property name (for example jdbcUrl) to the label shown on the midPoint connector form, so the form displays human-readable names instead of raw property keys.
Troubleshooting
| Issue | Solution |
|---|---|
Schema is empty |
Check |
|
Verify |
No object class for a table |
Check the |
Scripts not loading |
The script path in the manifest must match the classpath resource exactly ( |
|
The object class is read-only (view or |
Groovy script fails at runtime |
Script errors are wrapped with the resource name; review connector logs. In development mode you can validate a script from the management system before deployment (see above). |