Skip to content

Replace activiti-osgi OsgiScriptingEngines with stock Activiti ScriptingEngines#179

Merged
vharseko merged 7 commits into
OpenIdentityPlatform:masterfrom
vharseko:workflow-errors2
May 14, 2026
Merged

Replace activiti-osgi OsgiScriptingEngines with stock Activiti ScriptingEngines#179
vharseko merged 7 commits into
OpenIdentityPlatform:masterfrom
vharseko:workflow-errors2

Conversation

@vharseko
Copy link
Copy Markdown
Member

Summary

Removes the use of org.activiti.osgi.OsgiScriptingEngines from the OpenIDM
workflow bundle and wires the stock org.activiti.engine.impl.scripting.ScriptingEngines
with an explicitly registered Groovy ScriptEngineFactory.

This eliminates noisy ClassNotFoundException warnings emitted during every
script-task execution and makes the script-engine resolution deterministic
under OSGi without touching the rest of activiti-osgi (BPMN auto-deployment
via ProcessEngineFactory is preserved).

Motivation

activiti-osgi 5.15 ships Extender$BundleScriptEngineResolver, which is
invoked by OsgiScriptingEngines for every script execution. Its implementation
parses META-INF/services/javax.script.ScriptEngineFactory line by line and
calls Class.forName(...) on each line including #-prefixed comments,
producing a ClassNotFoundException warning per script-task invocation:

WARNING: Cannot create ScriptEngineFactory: # Licensed to the Apache Software Foundation ... java.lang.ClassNotFoundException: # Licensed to the Apache Software Foundation ... at org.activiti.osgi.Extender$BundleScriptEngineResolver.resolveScriptEngine(Extender.java:367)

These warnings pollute CI logs and trip the OpenIDM CI log-scan that fails the
build on Exception / ERROR patterns.

activiti-osgi 5.15 has been unmaintained since 2014; this change avoids
that code path entirely instead of forking the Extender or filtering CI logs.

Changes

openidm-workflow-activiti/.../ActivitiServiceImpl.java

  • Removed unused imports tied to OsgiScriptingEngines:
    javax.script.ScriptEngine, org.activiti.osgi.Extender,
    org.activiti.osgi.OsgiScriptingEngines, org.osgi.framework.Bundle,
    org.osgi.framework.ServiceFactory, org.osgi.framework.ServiceRegistration.
  • Replaced new OsgiScriptingEngines(...) with stock
    new ScriptingEngines(ScriptEngineManager) configured with an explicitly
    registered org.codehaus.groovy.jsr223.GroovyScriptEngineFactory.
  • Removed the registration of the OSGi Extender.ScriptEngineResolver service
    in bindScriptRegistry — nothing invokes it anymore.
  • Kept org.activiti.osgi.blueprint.ProcessEngineFactory (used for BPMN/BAR
    auto-deployment via felix.fileinstall).
  • Updated the CDDL header to add Portions Copyright 2024-2026 3A Systems LLC..

Why register Groovy explicitly under multiple names

  1. The JDK ScriptEngineManager discovers factories via ServiceLoader using
    the thread-context classloader. Under OSGi the TCCL does not see the
    groovy-all bundle, so auto-discovery fails and Activiti throws
    Can't find scripting engine for 'groovy'.
  2. Activiti's ScriptingEngines.addScriptEngineFactory(factory) registers only
    under factory.getEngineName(), which for Groovy returns "Groovy" (capital G).
    BPMN script tasks use scriptFormat="groovy" (lowercase), and lookup is
    case-sensitive — registration under the engine name alone is insufficient.

The fix builds a ScriptEngineManager, registers GroovyScriptEngineFactory
under the engine name, all getNames() aliases (including the lowercase
"groovy"), MIME types and extensions, then passes the fully populated
manager to new ScriptingEngines(mgr). ScriptBindingsFactory is wired via
the setter (the two-arg constructor that accepts both does not exist in
Activiti 5.15).

Order of initialization

The scripting/resolver/variableType wiring lives after
processEngineFactory.init() — same as the original code. init() calls
buildProcessEngine(), which is what populates getVariableTypes() and
getResolverFactories(); calling them before init() returns null and
throws NullPointerException during activation.
ScriptTaskActivityBehavior reads
Context.getProcessEngineConfiguration().getScriptingEngines() on every
invocation, so replacing the reference in the configuration after init()
takes effect immediately.

Compatibility

  • activiti-osgi dependency is kept at 5.15 — only its
    OsgiScriptingEngines is no longer used. ProcessEngineFactory from the
    same artifact continues to handle blueprint / BAR auto-deployment.
  • No changes to public APIs, configuration files, or BPMN samples.
  • Groovy version unchanged (groovy-all 2.4.21).

Risk

Low. Script execution path is now stock Activiti, and the explicit Groovy
factory registration avoids the OSGi-classloader pitfall that affected the
auto-discovery code path. The change is internal to
openidm-workflow-activiti.

Verification

  • mvn -pl openidm-workflow-activiti -am install -DskipTests — green.
  • Repackaged openidm-zip, unpacked, started OpenIDM with samples/workflow.
  • BPMN script tasks (scriptFormat="groovy") execute without
    Can't find scripting engine for 'groovy'.
  • openidm0.log.0 no longer contains Cannot create ScriptEngineFactory: #
    warnings during workflow execution.
  • CI ui-smoke-tests workflow scenarios pass without log-scan failures.

vharseko added 7 commits May 13, 2026 12:06
Add org.apache.felix.prefs bundle to provide org.osgi.service.prefs
package (including BackingStoreException class) at runtime, fixing:
  INFO: org.apache.felix.webconsole.internal.compendium.PreferencesConfigurationPrinter
  not enabled. Reason: Class org/osgi/service/prefs/BackingStoreException missing
Select-String in PowerShell is case-insensitive by default, so the
Windows smoke-test step was matching benign INFO records such as
"ErrorServletComponent activate" / "Registered servlet at /error"
against the ERROR|SEVERE|Exception|Throwable pattern and failing
the build. The equivalent Unix step uses `grep -E`, which is
case-sensitive, so the same lines pass on Linux/macOS.

Add the -CaseSensitive flag to both Select-String invocations in the
"Test on Windows" step of .github/workflows/build.yml so the check
behaves identically across OSes.
…script

### Problem

The `samples/workflow` end-to-end smoke job
`ui-smoke-tests (… , /myidm, samples/workflow)` consistently fails on
both Java 17 and Java 26 in
[Build run #25805813364](https://github.com/OpenIdentityPlatform/OpenIDM/actions/runs/25805813364)
while every other matrix combination is green:

| context_path | sample              | result   |
|--------------|---------------------|----------|
| (default)    | samples/workflow    | ✅ pass |
| /myidm       | samples/getting-started | ✅ pass |
| /myidm       | (no sample)         | ✅ pass |
| **/myidm**   | **samples/workflow**| ❌ fail |

The job's final step (`Print openidm logs`) scans
`openidm/logs/*` for `ERROR|SEVERE|Exception|Throwable` and exits 1 if
anything matches. With `-Dopenidm.context.path=/myidm` the workflow
sample's `Accept Notice` Groovy script task in
`contractorOnboarding.bpmn20.xml` was calling a hard-coded REST URL:

```groovy
"url": "https://localhost:" + identityServer.getProperty('openidm.port.https')
       + "/openidm/selfservice/reset?_action=submitRequirements"
…iptingEngines`

## Summary
Removes the use of `org.activiti.osgi.OsgiScriptingEngines` from the OpenIDM
workflow bundle and wires the stock `org.activiti.engine.impl.scripting.ScriptingEngines`
with an explicitly registered Groovy `ScriptEngineFactory`.

This eliminates noisy `ClassNotFoundException` warnings emitted during every
script-task execution and makes the script-engine resolution deterministic
under OSGi without touching the rest of `activiti-osgi` (BPMN auto-deployment
via `ProcessEngineFactory` is preserved).

## Motivation
`activiti-osgi` 5.15 ships `Extender$BundleScriptEngineResolver`, which is
invoked by `OsgiScriptingEngines` for every script execution. Its implementation
parses `META-INF/services/javax.script.ScriptEngineFactory` line by line and
calls `Class.forName(...)` on each line **including `#`-prefixed comments**,
producing a `ClassNotFoundException` warning per script-task invocation:
@vharseko vharseko requested a review from maximthomas May 14, 2026 08:40
@vharseko vharseko merged commit 11934f6 into OpenIdentityPlatform:master May 14, 2026
41 of 56 checks passed
@vharseko vharseko deleted the workflow-errors2 branch May 14, 2026 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants