OSGi extensions & BPM/EIP integration

When the standard apps and scripts aren't enough, you can add advanced extensions as OSGi bundles. The BPM and EIP runtimes also publish events to OSGi EventAdmin, which bundles, scripts and Camel routes can integrate with.

How an OSGi bundle is structured

A bundle looks like this:

com.example.myfeature/
├── META-INF/MANIFEST.MF      # OSGi bundle metadata
├── OSGI-INF/*.xml            # Declarative Services (DS) component descriptors
├── src/...                   # Java source
└── build.properties

In MANIFEST.MF you declare the symbolic name, version, dependencies (Import-Package / Require-Bundle), public API (Export-Package) and DS components (Service-Component). A DS component (OSGI-INF/*.xml) receives the services it needs via <reference> and activates automatically once they are all available.

<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.3.0"
    immediate="true" name="com.example.myfeature.MyService">
  <reference cardinality="1..1" field="fRepository"
      interface="javax.jcr.Repository" name="fRepository" policy="static"/>
  <implementation class="com.example.myfeature.internal.MyService"/>
</scr:component>

Felix loads bundles at startup. Manage and inspect them at runtime from the OSGi Console (/en/docs/user-guide/osgi-console/).

BPM / EIP EventAdmin integration

Both engines publish their runtime lifecycle to OSGi EventAdmin. The topic and property conventions are shared, and every event carries a workspace property (for the operational overview, see "BPM & EIP configuration").

  • Topic: <fully/qualified/Type>/<ACTION> (the fully-qualified type name with ./, suffixed with an upper-case action)
  • Examples: org/camunda/bpm/engine/task/Task/CREATED, org/apache/camel/Exchange/FAILED
  • Delivery is asynchronous (postEvent); BPM publishes only on transaction commit

The eventadmin: Camel component

Camel routes can consume and produce EventAdmin events.

Consume events:

from("eventadmin:org/camunda/bpm/engine/runtime/ProcessInstance/*?filter=(workspace=web)")
    .to("log:bpm-notifications");

The endpoint is eventadmin:<topic>?filter=<ldap-filter> — the topic supports wildcards and the filter narrows by, for example, workspace. Internally it registers an OSGi EventHandler.

Produce events:

from("...")
    .to("eventadmin:org/my/custom/Event/TRIGGERED");

If the message body is a Map, it becomes the event properties, and a TOPIC header can override the topic.

Integrating with processes & routes

  • Start a process — the GraphQL startProcess mutation, or the ProcessEngine API
  • Send to a routeCamelContext's ProducerTemplate#sendBody(endpointUri, body), or the GraphQL sendToEndpoint
  • React to activity — subscribe to EventAdmin topics (an OSGi EventHandler, a Camel from("eventadmin:..."), or a GraphQL subscription)

Run automation as a service account

It's safest to give an integration the permissions of a passwordless service account. Create it via provisioning and grant ACLs through a group.

users:
  - id: myapp-service
    service: true
    displayName: MyApp Integration
    memberOf: [myapp-service-group]
groups:
  - id: myapp-service-group
    displayName: MyApp Service Users
nodes:
  - path: /content/myapp
    primaryType: nt:folder
    acl:
      - group: myapp-service-group
        privileges: jcr:read, jcr:write
        effect: allow

See "Provisioning" and "Users, roles & permissions".