Skip to content

camunda-community-hub/orchestration-api-client-java

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Orchestration API Client Java

Last Updated: April 2026

A Spring Boot application that provides REST and SOAP API endpoints for interacting with Camunda 8 SaaS Orchestration Cluster using the official Camunda Java Client. It exposes endpoints for topology retrieval, decision definition lookup, decision definition search, and DMN evaluation.


Table of Contents


Overview

This application acts as a Java-based REST and SOAP proxy for Camunda 8 Orchestration APIs. It is useful for:

  • Retrieving cluster topology and decision definitions.
  • Searching deployed DMN decision definitions with paging/filter criteria.
  • Evaluating decision definitions (DMN) with input variables.
  • Exposing SOAP/WSDL interfaces for enterprise integrations.
  • Serving as a reference implementation of camunda-client-java in Spring Boot.

Tech Stack

Technology Version
Java 21
Spring Boot 4.0.5
Spring Web MVC via spring-boot-starter-web
Spring Web Services (SOAP) via spring-boot-starter-web-services
Bean Validation via spring-boot-starter-validation
Camunda Java Client 8.9.0
OpenAPI + Swagger UI springdoc-openapi-starter-webmvc-ui:3.0.2
JAXB jakarta.xml.bind-api, jaxb-runtime
WSDL support io.github.librewsdl4j:libre-wsdl4j:1.12.0
Maven 3.x (via wrapper mvnw)

Project Structure

src/
├── main/
│   ├── java/org/camunda/community/api/
│   │   ├── OrchestrationApiClientApplication.java
│   │   ├── CamundaClientConfiguration.java
│   │   ├── DecisionEvaluationService.java
│   │   ├── DecisionDTO.java
│   │   ├── OpenApiConfig.java
│   │   ├── rest/
│   │   │   └── DecisionDefinitionController.java
│   │   └── soap/
│   │       ├── SoapWebServiceConfig.java
│   │       ├── DecisionEvaluationSoapEndpoint.java
│   │       ├── SoapUtils.java
│   │       └── model/
│   │           ├── EvaluateDecisionRequest.java
│   │           ├── EvaluateDecisionResponse.java
│   │           ├── SoapDecisionVariables.java
│   │           └── SoapVariableEntry.java
│   └── resources/
│       ├── application.yaml
│       └── decision-evaluation.xsd
└── test/
    └── java/org/camunda/community/api/
        ├── OrchestrationApiClientApplicationTests.java
        ├── rest/DecisionDefinitionControllerTest.java
        └── soap/
            ├── EvaluateDecisionRequestJaxbTest.java
            ├── SoapUtilsTest.java
            ├── DecisionEvaluationSoapEndpointTest.java
            └── DecisionEvaluationSoapEndpointContractTest.java

Prerequisites

  • Java 21+
  • Maven 3.x (or use ./mvnw)
  • Camunda 8 SaaS cluster credentials:
    • Cluster ID
    • Cluster Region
    • OAuth Client ID
    • OAuth Client Secret

Configuration

Environment Variables

Set the following variables before starting the app:

Environment Variable Description
CAMUNDA_CLUSTER_ID Camunda SaaS cluster UUID
CAMUNDA_CLUSTER_REGION Cluster region (for example cle-1)
CAMUNDA_CLIENT_ID OAuth M2M client ID
CAMUNDA_CLIENT_SECRET OAuth M2M client secret

These map to src/main/resources/application.yaml:

camunda:
  cluster:
    id: ${CAMUNDA_CLUSTER_ID}
    region: ${CAMUNDA_CLUSTER_REGION}
  client:
    id: ${CAMUNDA_CLIENT_ID}
    secret: ${CAMUNDA_CLIENT_SECRET}

Network Access Requirements

Allow outbound access to:

  • Zeebe endpoint: {CAMUNDA_CLUSTER_ID}.{CAMUNDA_CLUSTER_REGION}.zeebe.camunda.io:443
  • OAuth endpoint: https://login.cloud.camunda.io/oauth/token

Setting Environment Variables

macOS / Linux (zsh)

export CAMUNDA_CLUSTER_ID=your-cluster-id
export CAMUNDA_CLUSTER_REGION=your-cluster-region
export CAMUNDA_CLIENT_ID=your-client-id
export CAMUNDA_CLIENT_SECRET=your-client-secret

Windows (PowerShell)

$env:CAMUNDA_CLUSTER_ID = "your-cluster-id"
$env:CAMUNDA_CLUSTER_REGION = "your-cluster-region"
$env:CAMUNDA_CLIENT_ID = "your-client-id"
$env:CAMUNDA_CLIENT_SECRET = "your-client-secret"

Using direnv (macOS / Linux)

brew install direnv
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc

Create .envrc in the project root with your values, then allow it:

direnv allow .

Running the Application

./mvnw clean spring-boot:run

The app runs on http://localhost:8080.


Swagger UI / OpenAPI Docs

When the app is running:

  • http://localhost:8080/swagger-ui/index.html
  • http://localhost:8080/swagger-ui.html
  • http://localhost:8080/v3/api-docs
  • http://localhost:8080/v3/api-docs.yaml

REST API Endpoints

All REST endpoints are available under the /api/camunda prefix.


Get Cluster Topology

GET /api/camunda/topology

Returns Camunda cluster topology information.


Get a Decision Definition

GET /api/camunda/decision-definitions/{decisionDefinitionKey}
Path Parameter Description
decisionDefinitionKey Camunda decision definition key

Get Decision Definition XML

GET /api/camunda/decision-definitions/{decisionDefinitionKey}/xml
Path Parameter Description
decisionDefinitionKey Camunda decision definition key

Search Decision Definitions

POST /api/camunda/decision-definitions/search
Content-Type: application/json

The current implementation applies these request fields:

  • page.from
  • page.limit
  • filter.decisionDefinitionId
  • filter.name
  • filter.decisionDefinitionKey

sort and other filter fields may be accepted in payloads but are not currently applied by DecisionEvaluationService.

Example request:

{
  "page": {
    "from": 0,
    "limit": 100
  },
  "sort": [
    {
      "field": "decisionDefinitionKey",
      "order": "ASC"
    }
  ],
  "filter": {
    "decisionDefinitionId": "new-hire-onboarding-workflow",
    "name": "string",
    "decisionDefinitionKey": "2251799813326547"
  }
}

Evaluate a Decision Definition

POST /api/camunda/decision-definitions/evaluation
Content-Type: application/json

Rules enforced by the current implementation:

  • Either decisionDefinitionId or decisionDefinitionKey is required.
  • If both are present, decisionDefinitionId takes priority.
  • If only decisionDefinitionKey is present:
    • Numeric value -> evaluated as a Camunda decision key (long).
    • Non-numeric value -> treated as a decision ID fallback.

Request example using decisionDefinitionId:

{
  "decisionDefinitionId": "my-decision-id",
  "variables": {}
}

Request example using decisionDefinitionKey:

{
  "decisionDefinitionKey": "2251799813326547",
  "variables": {}
}

SOAP Endpoint

SOAP endpoint path: /ws/*

WSDL Access

  • http://localhost:8080/ws/decisionEvaluation.wsdl

SOAP Request Example

The SOAP operation is evaluateDecisionRequest in namespace http://camunda.org/consulting/decision-evaluation.

Request example using decisionDefinitionId:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:dec="http://camunda.org/consulting/decision-evaluation">
  <soapenv:Header/>
  <soapenv:Body>
    <dec:evaluateDecisionRequest>
      <dec:decisionDefinitionId>myDecisionId</dec:decisionDefinitionId>
      <dec:variables>
        <dec:entry>
          <dec:key>team</dec:key>
          <dec:value>East Regional</dec:value>
        </dec:entry>
        <dec:entry>
          <dec:key>state</dec:key>
          <dec:value>Alabama</dec:value>
        </dec:entry>
      </dec:variables>
    </dec:evaluateDecisionRequest>
  </soapenv:Body>
</soapenv:Envelope>

Complex nested object request example:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:dec="http://camunda.org/consulting/decision-evaluation">
  <soapenv:Header/>
  <soapenv:Body>
    <dec:evaluateDecisionRequest>
      <dec:decisionDefinitionId>discount-decision</dec:decisionDefinitionId>
      <dec:variables>
        <dec:entry>
          <dec:key>order</dec:key>
          <dec:value>
            <dec:customerType>VIP</dec:customerType>
            <dec:total>1000</dec:total>
            <dec:items>
              <dec:category>ELECTRONICS</dec:category>
              <dec:quantity>1</dec:quantity>
            </dec:items>
            <dec:items>
              <dec:category>ELECTRONICS</dec:category>
              <dec:quantity>1</dec:quantity>
            </dec:items>
          </dec:value>
        </dec:entry>
      </dec:variables>
    </dec:evaluateDecisionRequest>
  </soapenv:Body>
</soapenv:Envelope>

Note: repeated sibling elements (for example multiple <dec:items>) are normalized into Java lists by backend SOAP value normalization.

Both decisionDefinitionId and decisionDefinitionKey are optional at schema level, but the service requires at least one.

SOAP Response Example

Success response (example with object-like result payload):

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Body>
    <ns2:evaluateDecisionResponse xmlns:ns2="http://camunda.org/consulting/decision-evaluation">
      <ns2:success>true</ns2:success>
      <ns2:result>
        <outcome>approved</outcome>
      </ns2:result>
    </ns2:evaluateDecisionResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Success Response (detailed decision output):

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header/>
  <SOAP-ENV:Body>
    <ns2:evaluateDecisionResponse xmlns:ns2="http://camunda.org/consulting/decision-evaluation">
      <ns2:success>true</ns2:success>
      <ns2:result>
        <decisionEvaluationKey>6755399444437420</decisionEvaluationKey>
        <decisionId>discount-decision</decisionId>
        <decisionInstanceKey>6755399444437420</decisionInstanceKey>
        <decisionKey>2251799816375669</decisionKey>
        <decisionName>Discount Decision</decisionName>
        <decisionOutput>0.15</decisionOutput>
        <decisionRequirementsId>discount-decision-DRD</decisionRequirementsId>
        <decisionRequirementsKey>2251799816375667</decisionRequirementsKey>
        <decisionVersion>11</decisionVersion>
        <evaluatedDecisions>
          <item>
            <decisionEvaluationInstanceKey>6755399444437420-1</decisionEvaluationInstanceKey>
            <decisionId>discount-decision</decisionId>
            <decisionKey>2251799816375669</decisionKey>
            <decisionName>Discount Decision</decisionName>
            <decisionOutput>0.15</decisionOutput>
            <decisionType>DECISION_TABLE</decisionType>
            <decisionVersion>11</decisionVersion>
            <evaluatedInputs>
              <item>
                <inputId>Input_1</inputId>
                <inputName>Customer Type</inputName>
                <inputValue>&quot;VIP&quot;</inputValue>
              </item>
              <item>
                <inputId>InputClause_1ip3z40</inputId>
                <inputName>Total Amount</inputName>
                <inputValue>1000</inputValue>
              </item>
              <item>
                <inputId>InputClause_1nqicll</inputId>
                <inputName>Electronics Category Count</inputName>
                <inputValue>true</inputValue>
              </item>
            </evaluatedInputs>
            <matchedRules>
              <item>
                <evaluatedOutputs>
                  <item>
                    <outputId>Output_1</outputId>
                    <outputName>Discount</outputName>
                    <outputValue>0.15</outputValue>
                  </item>
                </evaluatedOutputs>
                <ruleId>DecisionRule_16s0n6q</ruleId>
                <ruleIndex>1</ruleIndex>
              </item>
            </matchedRules>
            <tenantId>&lt;default&gt;</tenantId>
          </item>
        </evaluatedDecisions>
        <failedDecisionId></failedDecisionId>
        <failureMessage></failureMessage>
        <tenantId>&lt;default&gt;</tenantId>
      </ns2:result>
    </ns2:evaluateDecisionResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Note: repeated XML nodes in decision output (for example <item> under evaluatedInputs or matchedRules) map to list-like structures during normalization.

Success response (example with scalar result field):

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Body>
    <ns2:evaluateDecisionResponse xmlns:ns2="http://camunda.org/consulting/decision-evaluation">
      <ns2:success>true</ns2:success>
      <ns2:result>
        <decision>approved</decision>
      </ns2:result>
    </ns2:evaluateDecisionResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Error response (business validation/service error):

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Body>
    <ns2:evaluateDecisionResponse xmlns:ns2="http://camunda.org/consulting/decision-evaluation">
      <ns2:success>false</ns2:success>
      <ns2:errorMessage>Either decisionDefinitionId or decisionDefinitionKey must be provided.</ns2:errorMessage>
    </ns2:evaluateDecisionResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

DecisionEvaluationSoapEndpoint returns business errors in the response payload (success=false) instead of emitting a SOAP Fault.


Request & Response Models

DecisionDTO

{
  "decisionDefinitionId": "string",
  "decisionDefinitionKey": "string",
  "variables": {
    "firstInputKey": "firstInputValue",
    "secondInputKey": "secondInputValue"
  }
}

variables is represented as Map<String, Object>.

SOAP Models

decision-evaluation.xsd defines:

  • evaluateDecisionRequest
  • evaluateDecisionResponse
  • SoapDecisionVariables with repeated entry
  • SoapVariableEntry (key + value, where value is xsd:anyType)

Running Tests

Run all tests:

./mvnw test

Run specific tests:

./mvnw test -Dtest=DecisionDefinitionControllerTest
./mvnw test -Dtest=DecisionEvaluationSoapEndpointTest
./mvnw test -Dtest=DecisionEvaluationSoapEndpointContractTest
./mvnw test -Dtest=EvaluateDecisionRequestJaxbTest
./mvnw test -Dtest=SoapUtilsTest
./mvnw test -Dtest=OrchestrationApiClientApplicationTests

Building a JAR

./mvnw clean package

Artifact:

target/orchestration-api-client-java-0.0.1-SNAPSHOT.jar

Run it:

java -jar target/orchestration-api-client-java-0.0.1-SNAPSHOT.jar

Troubleshooting

Missing environment variables

If startup fails with unresolved placeholders, make sure all four Camunda environment variables are set.

Swagger UI cannot load OpenAPI docs

  • Confirm app is running on port 8080.
  • Verify http://localhost:8080/v3/api-docs returns JSON.

WSDL not accessible

  • Confirm app is running.
  • Verify http://localhost:8080/ws/decisionEvaluation.wsdl.
  • Check logs for SOAP configuration issues.

Contributing

  1. Fork the repository.
  2. Create a branch: git checkout -b feature/my-feature
  3. Commit: git commit -m 'Add my feature'
  4. Push: git push origin feature/my-feature
  5. Open a pull request.

License

This project is licensed under the Apache License, Version 2.0. See LICENSE for details.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages