Code Monkey home page Code Monkey logo

camunda-platform-rest-api's Introduction

Camunda Platform REST API

Community Extension
Compatible with: Camunda Platform 8 Lifecycle: Unmaintained GitHub

Warning

This project is unmaintained - There are ongoing efforts to add a REST API to Zeebe and ideas about unifying the REST APIs of all Camunda Platform 8 components. With that, it's time to sunset this project.

Working on this project has taught me much about Spring and Kotlin and even more about REST APIs. I'm proud that Camunda is taking a path that was explored by this project and took note of our successes and mistakes to make a better product.

Thank you all for all your feedback and support. Happy RESTful orchestrating!

Introduction

Camunda Platform REST API is a REST API to interact with Camunda Platform 8.

Camunda Platform 8 has multiple different APIs. Typically, one for each component. There are gRPC, GraphQL, and REST APIs for you to connect to and learn, which can be difficult and time consuming. Camunda Platform REST API offers a single consistent REST API to interact with Camunda Platform 8.

  • Get Started Quickly

Camunda Platform REST API was designed to be easily installed, to get you connected to Camunda Platform 8 quickly.

  • Easy to Use

Thanks to a consistent API design and an OpenAPI specification, you can focus on interacting with Camunda Platform 8.

  • Community Driven

This project is community maintained. We welcome contributions for feature requests and bug reports, as well as for docs and code changes.

API

Method Resource Description
GET /status Retrieve the Topology of a Zeebe cluster
POST /process-instances Create a new Process Instance
GET /process-instances/{key} Retrieve the details of a Process Instance
GET /jobs Activate Jobs
PATCH /jobs/{key} Update a Job
.. .. Not yet implemented

You can find the full API reference documentation in the openapi.yaml specification, and in the Docs.

Getting Started

The easiest way to start the Camunda Platform REST API is using Docker.

docker pull ghcr.io/korthout/camunda-platform-rest-api:latest

Using the provided Docker Compose file you can start a new local Camunda Platform 8 cluster and connect the Camunda Platform REST API to it. This is a great way to try out the Camunda Platform REST API before connecting it to your production cluster.

docker compose -f ./docker/docker-compose.yml up -d

Once running, you can try it out the REST API.

curl localhost:8080/status

Or, explore the API in Swagger UI running at /swagger-ui.

Documentation

Read the docs for any further information:

Acknowledgements

This software would not be possible without these awesome projects:

A full list of projects we depend on can be found in the pom file.

License

Camunda Platform REST API is Open Source software released under the Apache 2.0 license.

camunda-platform-rest-api's People

Contributors

dependabot[bot] avatar github-actions[bot] avatar koevskinikola avatar korthout avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

camunda-platform-rest-api's Issues

Consider rescoping this repo

The current scope of this repo is to offer a rest API as a client alternative to zeebe. We could also use it as a single API to interact with camunda 8 entities.

This would enable querying the current state and history through the data in Operate, Optimize and Tasklist. Allow users to interact with their cluster, but also manage it through the console API. This repo could be used as a way to make all API interactions with camunda 8 components consistent through a singular REST API.

Such a change in scope should be reflected in its name as well. For example, camunda-platform-rest-api.

The API itself could consist of entities know from Zeebe like deployments, process-instances, jobs, messages, signals, decisions, etc. It can also consist of entities that are available in the other components like process-definitions, decision-requirements, tasks, clusters, clients, alerts, etc.

Clarify how to connect to your own zeebe cluster

The Zeebe REST Client can now be run as a docker container. Easy start up is available via a docker compose file, but that connects the client to a new locally running Zeebe cluster consisting of only a single broker. What if I want to connect this REST client to my already existing Zeebe cluster?

The README should clarify how a user can achieve this.

Publish container workflow fails when Dependabot merges

When a pull request is merged to main, a workflow is run to publish the package to ghcr.io. But, if that pull request was merged by @dependabot then this workflow fails.

During the step Login to the container registry, the following is logged:

Run docker/login-action@v2
with:
    registry: ghcr.io
    username: korthout
    ecr: auto
    logout: true
  env:
    REGISTRY: ghcr.io
    GHCR_USER: korthout
    JAVA_HOME: /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.6-10/x6[4](https://github.com/korthout/camunda-platform-rest-api/actions/runs/4263903410/jobs/7421242143#step:5:4)
    JAVA_HOME_17_X[6](https://github.com/korthout/camunda-platform-rest-api/actions/runs/4263903410/jobs/7421242143#step:5:6)4: /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/1[7](https://github.com/korthout/camunda-platform-rest-api/actions/runs/4263903410/jobs/7421242143#step:5:7).0.6-[10](https://github.com/korthout/camunda-platform-rest-api/actions/runs/4263903410/jobs/7421242143#step:5:10)/x64
Error: Username and password required

This does not happen when I merge the pull request.

CI should test the client

Currently the CI only builds and publishes the package. It should also perform some tests so we can be sure that some changes don't break it.

Check styling in CI

Spotless is automatically formatting the code on a maven build run, but nothing stops us from pushing and merging unstyled code. This often leads to style changes once work starts on a new issue.

We should check the styling in the CI, using mvn spotless:check

Improve cluster status

Retrieving the cluster status only reports on zeebe currently. However, Operate is now also part of the cluster components that the REST API connects to.

The status should report whether a connection with operate is configured, and if so, whether it is able to connect to it.

This would be useful to simplify the guide to connect to a Self-Managed cluster, because the checking the connection to operate can be done in the same way as checking the connection with zeebe.

This would be useful as this guide is currently quite large and may scare of potential users unnecessarily.

Set up a test against a real Zeebe broker

The idea I have now is to:

  • run current version of this project in a Testcontainer
  • run zeebe broker in a Testcontainer, for example with zeebe-process-test
  • write tests that call the API in the Testcontainer
  • verify responses
  • use zeebe-process-test to verify the state

Support most common requests

Common operations

The most common operations that we think we should cover.

  • get status
  • creating process instances (with variables) #15
  • #20
  • #21
  • #22
  • #23
  • #24
  • #25
  • list process instances (active, completed, terminated) (GET process-instances and ?status="activated|completed|terminated")
  • #95
  • cancel process instance (PATCH process-instances/{key})
  • list incidents (GET incidents)
  • resolve incident (PATCH incidents/{key})
  • set variables for process instance (PATCH process-instances/{key})
  • set variables for job (PATCH jobs/{key})
  • update job retries (PATCH jobs/{keys})
  • start process instance anywhere
  • modify process instance

In the future we can also add support for tasks (Tasklist), clients (Console), dashboards (Optimize), projects, files & milestones (Webmodeler #77), etc.

We want your input

Please let us know in a comment what operations you'd like to see next.

Document how to throw an error for a job

#41 added the ability to throw an error for a job. We should make sure that:

  • It's documented in the README.md
  • It's documented in the docs/api.md
  • The OpenAPI spec (in src/main/resources/api.yaml) is updated.

POST /process-instances: variables must not be null

When I try to POST /process-instances, I run into a 500 Interal Server Error.

The following error is logged: java.lang.IllegalArgumentException: variables must not be null

This happens when I use:

 curl --data '{"bpmnProcessId":"onetask"}' \
    --header 'Content-Type: application/json' \
    "localhost:8080/process-instances" | jq
{
  "timestamp": "2022-12-10T17:41:58.442+00:00",
  "status": 500,
  "error": "Internal Server Error",
  "path": "/process-instances"
}
Stacktrace

2022-12-10 17:41:58.438 ERROR 1 --- [nio-8080-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: variables must not be null] with root cause

java.lang.IllegalArgumentException: variables must not be null
	at io.camunda.zeebe.client.impl.command.ArgumentUtil.ensureNotNull(ArgumentUtil.java:22) ~[zeebe-client-java-8.1.5.jar:8.1.5]
	at io.camunda.zeebe.client.impl.command.CreateProcessInstanceCommandImpl.variables(CreateProcessInstanceCommandImpl.java:81) ~[zeebe-client-java-8.1.5.jar:8.1.5]
	at io.camunda.zeebe.client.impl.command.CreateProcessInstanceCommandImpl.variables(CreateProcessInstanceCommandImpl.java:76) ~[zeebe-client-java-8.1.5.jar:8.1.5]
	at com.github.korthout.zeeberestclient.ProcessInstanceController.createProcessInstance(ProcessInstanceController.kt:41) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:681) ~[tomcat-embed-core-9.0.65.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.23.jar:5.3.23]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.65.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.65.jar:9.0.65]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.23.jar:5.3.23]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.65.jar:9.0.65]
	at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]

Generate OpenAPI spec

Currently, the API reference doc is hand written.

It would be cool to generate an OpenAPI specification and use this to generate the API reference documentation. For example, we could generate a website out of this which we host with github-pages where users can explore and try-out the API.

  • #38
  • use the OpenAPI specification to spin up SwaggerUI as part of the Docker image
  • #61

Version the docs

Now that version 0.1.0 is released, we can start making changes for the next release. In order to help users we should version the docs.

This should be possible with Docusaurus' versioning capabilities.

How to fix 'Error response from daemon: Head "..": denied: denied' during docker pull?

If you cannot access the container image:

$ docker logout
Removing login credentials for https://index.docker.io/v1/

$ docker pull ghcr.io/korthout/camunda-platform-rest-api:latest
Error response from daemon: Head "https://ghcr.io/v2/korthout/camunda-platform-rest-api/manifests/latest": denied: denied

Then you need to log out of GHCR:

$ docker logout ghcr.io

$ docker pull ghcr.io/korthout/camunda-platform-rest-api:latest
latest: Pulling from korthout/camunda-platform-rest-ap

The error may occur when you were logged into GHCR before, but your token expired. You don't need to be logged in to pull any of the camunda-platform-rest-api images, so the problem is resolved by logging out.

Of course, you can log in with a new token (Authenticating with a personal access token (classic)) as well.

Adjust changelog in release workflow

The changelog contains an Unreleased section that should become the new version when a new version is released.

As we release new versions automated with the Release workflow, we need to adjust this file in that workflow.

  • add a new release section containing the contents of the unreleased section
  • add the new tag to the references (compared previous release with the new one)
  • adjust the unreleased reference (compares main with new tag)

We may need an additional input (previous release) to update the references correctly

Release v0.1

I'm eager to release v0.1.

At the current state of the project, the following should be completed before our first release:

  • #9
  • Improve the documentation
    • Finish #38
    • #60
    • #61
    • Update the readme to fit #3 (also add community badges)
  • #62
  • Perhaps more endpoints but that can also be released in 0.2+

Post release we need to:

  • Make repo public
  • Enable GitHub Pages
  • Announce it on the forums / slack and internal

Setup automated release workflow

We already have a workflow to deploy (publish) the docker image artifact. However, in the current state it will take the version from the pom. The release version should be decoupled from source using the maven revision property.

Note that openapi.yaml also contains the specific version.

GET /jobs: doesn't fetch variables by default

If I create a process instance with variables:

curl \
  --data '{"bpmnProcessId":"onetask","variables":{"foo":true,"bar":2,"baz":{}}}' \
  --header 'Content-Type: application/json' \
  "localhost:8080/process-instances"

And activate the jobs without specifying fetchVariables, then the variables are an empty object {}:

curl "localhost:8080/jobs?type=task" | jq
{
  "data": {
    "jobs": [
      {
        "key": 2251799813685425,
        "type": "task",
        "processInstanceKey": 2251799813685417,
        "bpmnProcessId": "onetask",
        "processDefinitionVersion": 1,
        "processDefinitionKey": 2251799813685254,
        "elementId": "Activity_0q59ktq",
        "elementInstanceKey": 2251799813685424,
        "customHeaders": {},
        "worker": "default",
        "retries": 3,
        "deadline": 1670695324179,
        "variables": {}
      }
    ]
  },
  "error": null
}

But, if I specify the fetchVariables, then the variables are provided correctly:

curl "localhost:8080/jobs?type=task&fetchVariables=foo,baz,bar" | jq
{
  "data": {
    "jobs": [
      {
        "key": 2251799813685413,
        "type": "task",
        "processInstanceKey": 2251799813685405,
        "bpmnProcessId": "onetask",
        "processDefinitionVersion": 1,
        "processDefinitionKey": 2251799813685254,
        "elementId": "Activity_0q59ktq",
        "elementInstanceKey": 2251799813685412,
        "customHeaders": {},
        "worker": "default",
        "retries": 3,
        "deadline": 1670695182477,
        "variables": {
          "bar": 2,
          "baz": {},
          "foo": true
        }
      }
    ]
  },
  "error": null
}

Swagger UI doesn't display the full openapi spec

There appears to be a difference between the openapi.yaml file and the specification used to produce the Swagger UI.

For example, the Swagger UI in version 0.1.0 does not contain the API stability warning.


I wonder whether Swagger UI is a useful feature or irrelevant with the full specification being available from the Docs.

๐Ÿ“ฃ Please let me know what you think ๐Ÿ‘ (I like Swagger UI) / ๐Ÿ‘Ž (I don't need Swagger UI)

Version the API

The API may see breaking changes in its future. We should make sure these don't break functionality for existing users. Let's version the API so users can update without having to overhaul their existing code.

Note that at the start the API should be version v0 and breaking changes will be allowed until v1 is released.

Reword consistent API to unified API

The Docs and the README refer to the API as Consistent. Consistent typically means something else in software than what is meant here. This leads to confusion.

Let's call the API unified, as it unifies the different APIs into a single API.

Document how to fail a job

#37 added the ability to fail a job. We should make sure that:

  • It's documented in the README.md
  • It's documented in the docs/api.md
  • The OpenAPI spec (in src/main/resources/api.yaml) is updated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.