{"id":13590115,"url":"https://github.com/amalagaura/camunda-workflow","last_synced_at":"2025-04-14T07:08:21.139Z","repository":{"id":36328340,"uuid":"213751127","full_name":"amalagaura/camunda-workflow","owner":"amalagaura","description":"Camunda Workflow - Ruby interface to the Camunda REST api","archived":false,"fork":false,"pushed_at":"2024-02-21T23:42:43.000Z","size":342,"stargazers_count":31,"open_issues_count":4,"forks_count":8,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-14T07:08:15.260Z","etag":null,"topics":["bpmn","bpmn-engine","camunda","camunda-api","camunda-bpm-platform","camunda-workflow","ruby","ruby-gem","ruby-on-rails","rubygems","workflow","workflow-engine"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amalagaura.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-08T20:49:08.000Z","updated_at":"2024-12-02T00:53:24.000Z","dependencies_parsed_at":"2024-01-14T04:35:11.202Z","dependency_job_id":"4cd24049-a6ee-4a28-8d40-9b633bd405a6","html_url":"https://github.com/amalagaura/camunda-workflow","commit_stats":{"total_commits":116,"total_committers":6,"mean_commits":"19.333333333333332","dds":0.5517241379310345,"last_synced_commit":"b94443ba5ba9fd4e38ebe9aa0570ccf184619c97"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amalagaura%2Fcamunda-workflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amalagaura%2Fcamunda-workflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amalagaura%2Fcamunda-workflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amalagaura%2Fcamunda-workflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amalagaura","download_url":"https://codeload.github.com/amalagaura/camunda-workflow/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248837280,"owners_count":21169374,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bpmn","bpmn-engine","camunda","camunda-api","camunda-bpm-platform","camunda-workflow","ruby","ruby-gem","ruby-on-rails","rubygems","workflow","workflow-engine"],"created_at":"2024-08-01T16:00:39.496Z","updated_at":"2025-04-14T07:08:21.109Z","avatar_url":"https://github.com/amalagaura.png","language":"Ruby","funding_links":[],"categories":["Community Supported"],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.com/amalagaura/camunda-workflow.svg?branch=master)](https://travis-ci.com/amalagaura/camunda-workflow)\n[![Gem Version](https://badge.fury.io/rb/camunda-workflow.svg)](https://badge.fury.io/rb/camunda-workflow)\n[![Inline docs](http://inch-ci.org/github/amalagaura/camunda-workflow.svg?branch=master)](http://inch-ci.org/github/amalagaura/camunda-workflow)\n# Camunda Workflow\n\n## An opinionated interface to Camunda for Ruby/Rails apps\n\nCamunda Workflow uses [Spyke](https://github.com/balvig/spyke) to communicate with the [Camunda REST API](https://docs.camunda.org/manual/latest/reference/rest/). It executes [External Service Tasks](https://docs.camunda.org/manual/latest/user-guide/process-engine/external-tasks/) using a Ruby class corresponding to each Camunda external task.\n\n\n## Camunda Integration with Ruby\n\nThe Camunda model process definition key is the module name of your implementation classes.\n\n  ![image](https://user-images.githubusercontent.com/498234/71268690-82934480-231b-11ea-9c58-0500b7ace028.png)\n\nAn external task is created with a Ruby class name for the id. And the process definition key should be set as the topic name.\n\n![image](https://user-images.githubusercontent.com/498234/71268753-af475c00-231b-11ea-8b39-89d2f306539b.png)\n\nTasks are fetched, locked and then queued. We expect classes (ActiveJob) to implement each external task. So, according to the above screenshots, the poller and queuer will expect a class called `SomeProcess::SomeTask` to be implemented in your app.\n\n### Integration with your worker classes\n\nWorker classes should inherit from `CamundaJob`. It is generated with `rails g camunda:install`.\n\n`perform` is implemented on  `Camunda::ExternalTaskJob`. It calls `bpmn_perform` with variables from Camunda and returns the results back to Camunda.\n```\nclass CamundaJob \u003c ApplicationJob\n  # If using Sidekiq, change to include Sidekiq::Worker instead of inheriting from ApplicationJob\n  include Camunda::ExternalTaskJob\nend\n\nclass SomeProcess::SomeTask \u003c CamundaJob\n  def bpmn_perform(variables)\n    do_something(variables[:foo])\n\n    # A hash returned will become variables in the Camunda BPMN process instance\n    { foo: 'bar', foo2: { json: \"str\" }, array_var: [\"str\"] }\n  end\nend\n```\n\n### Exceptions create Camunda incidents\nIf your implementation throws an exception, it is caught and then sent to Camunda with a stack trace.\n![image](https://user-images.githubusercontent.com/498234/71266361-35f93a80-2316-11ea-96ed-6501ef68f849.png)\n\n![image](https://user-images.githubusercontent.com/498234/71269561-a22b6c80-231d-11ea-80af-b748ba7eb09a.png)\n### Supporting bpmn exceptions\n\nCamunda supports throwing bpmn exceptions on a service task to communicate logic errors and not underlying code errors. These expected errors are thrown with\n```ruby\nclass SomeProcess::SomeTask \u003c CamundaJob\n  def bpmn_perform(variables)\n    result = do_something(variables[:foo])\n\n    if result == :expected\n      { foo: 'bar', foo2: { json: \"str\" }, array_var: [\"str\"] }\n    else\n      raise Camunda::BpmnError.new error_code: 'bpmn-error', message: \"Special BPMN error\", variables: { bpmn: 'error' }\n    end\n  end\nend\n```\n\n## Generators\n\n### Java Spring Boot App install\n```bash\nrails generate camunda:spring_boot\n```\nCreates a skeleton Java Spring Boot app, which also contains the minimal files to run unit tests on a BPMN file. The Spring boot app can be used to\nstart a Camunda instance with a REST api and also be deployed to PCF by generating a Spring Boot jar and pushing it.\n\n ### BPMN ActiveJob install\n```bash\nrails generate camunda:install\n```\nCreates `app/jobs/camunda_job.rb`. A class that inherits from ApplicationJob and includes `ExternalTaskJob`. It can be changed to include  `Sidekiq::Worker` instead.\n\nAll of the BPMN worker classes will inherit from this class\n\n### BPMN Classes\n```bash\nrails generate camunda:bpmn_classes\n```\nParses the BPMN file and creates task classes according to the ID of the process file and the ID of each task. It checks each task and only creates it if the topic name is the same as the process ID. This allows one to have some tasks be handled outside the Rails app. It confirms that the ID's are valid Ruby constant names.\n\n#### Starting the Camunda server for development\n\n[Java 7](https://www.java.com/en/) and [Apache Maven](https://maven.apache.org/install.html) are requirements to run the Camunda server. We are using the [Spring](https://docs.spring.io/spring-boot/docs/1.5.21.RELEASE/reference/html/getting-started-system-requirements.html) distribution.  The Camunda application has a `pom.xml`, which Maven uses to install the required dependencies.\n\nStart the application:\n```bash\ncd bpmn/java_app\nmvn spring-boot:run\n\n# Or use the included rake task:\n# Start the Camunda spring boot app with `mvn spring-boot:run`\nrake camunda:run\n```\n\nIf you create Java based unit tests for your bpmn file they can be run with an included rake task as well.\n\n\n#### Running java unit tests\n```bash\ncd bpmn/java_app\nmvn clean test\n\n# Or use the included rake task:\n# Runs spring boot test suite with `mvn clean test`\nrake camunda:test\n```\n\nCamunda-workflow defaults to an in-memory, h2 database engine. If you rather use a Postgres database engine, comment out the h2 database engine settings in the `pom.xml` file located in `bpmn/java_app`. Default settings for using Postgres are available in the `pom.xml` file.\nYou will need to create a Postgres database on localhost called `camunda`.\n\n### Configuration\n#### Engine Route Prefix of the Java Spring Boot app\nThe default engine route prefix for the provided Java Spring Boot app is `rest`. If you choose to download and use the Camunda distribution, the engine prefix is `rest-engine`. Camunda-workflow is configured to use `rest` by default.\n\nTo override the default engine route prefix, you need to add an initializer file in your rails app.\n\n```ruby\n# filename initializers/camunda.rb\nCamunda::Workflow.configure do |config|\n  config.engine_route_prefix = 'rest-engine'\nend\n```\n#### Enable HTTP Basic Auth for Java Spring Boot app\n\nAuthentication can be enabled in the Camunda Java Spring Boot app by setting an environment variable `CAMUNDA_AUTH` to `true` or `false` or by setting the `camunda.authentication` variable  located in the  `application.properties` (bpmn/java_app/src/main/resources) file to `true`.\n\nWhen HTTP Basic Auth is enabled, it's required that a user with the appropriate permissions is setup in Camunda.  Otherwise, the request will return as `401 unauthorized`. Users are set up within the admin dashboard of Camunda and used to authenticate by passing an Authorization header during requests to the REST API. Below is how to configure the `camunda_user` and `camunda_password` to be used in the header request to authenticate using HTTP Basic Auth.\n\n```ruby\n# filename initializers/camunda.rb\nCamunda::Workflow.configure do |config|\n  config.camunda_user = ENV['CAMUNDA_USER']\n  config.camunda_password = ENV['CAMUNDA_PASSWORD']\nend\n```\n#### Generating a jar for deployment\n`mvn package spring-boot:repackage`\n\nThe jar is in `target/camunda-bpm-springboot.jar`\n\n#### Deploying to PCF\n`cf push app_name -p target/camunda-bpm-springboot.jar`\n\nIt will fail to start. Create a postgres database as a service in PCF and bind it to the application. The Springboot application is configured for Postgres and will then be able to start.\n\n## Usage\n\n### Add to your Gemfile\n```ruby\n  gem 'camunda-workflow'\n```\n\n### Deploying a model\nUses a default name, etc. Below outlines how to deploy a process using the included sample.bpmn file created by the generator. Alternatively you can deploy using Camunda Modeler\n\n```ruby\n Camunda::Deployment.create file_names: ['bpmn/diagrams/sample.bpmn']\n```\n### Processes\n\n#### Starting a process\n\n```ruby\n  start_response = Camunda::ProcessDefinition.start_by_key'CamundaWorkflow', variables: { x: 'abcd' }, businessKey: 'WorkflowBusinessKey'\n```\n**Camunda cannot handle snake case variables, all snake_case variables are serialized to camelCase before a request is sent to the REST api. Variables returned back from the Camunda API will be deserialized back to snake_case.**\n\n`{ my_variable: \"xyz\" }`\n\nwill be converted to:\n\n`{ myVariable: \"xyz\" }`\n\n#### Destroy a process\n```ruby\n Camunda::ProcessInstance.destroy_existing start_response.id\n ```\n\n### Tasks\n\n#### Fetch tasks and queue with ActiveJob\n\nThe poller runs an infinite loop with long polling to fetch tasks, queue, and run them. The topic is the process definition key, as shown in the screenshot example from the Camunda Modeler.\n\nBelow will run the poller to fetch, lock, and run a task for the example process definition located in the `starting a process` detailed above.\n\nPoller will need to run in a separate process or thread and needs to be running constantly in order to poll Camunda and queue jobs.\n\n```ruby\n Camunda::Poller.fetch_and_queue %w[CamundaWorkflow]\n ```\n\n#### Running the poller in a separate thread\nWe have had success with running a long running thread in a Rails app using [Rufus Scheduler](https://github.com/jmettraux/rufus-scheduler). Something like:\n\n```\nrufus_scheduler.in('10.seconds') do\n  Camunda::Poller.fetch_and_queue %w[Topics]\nend\n```\n\n\n#### Fetch tasks For testing from the console\n\n```ruby\ntasks = Camunda::ExternalTask.fetch_and_lock %w[CamundaWorkflow]\n```\n#### Run a task\n\n```ruby\ntasks.each(\u0026:run_now)\n ```\n\n\n### User Tasks\n#### Mark a user task complete\n```ruby\n # Or you can query Camunda::Task with other parameters like assignee task.complete!(var1: 'value')\nCamunda::Task.find_by_business_key_and_task_definition_key!(instance_business_key, task_key).complete!\n```\n\n### Rspec Helpers\nRSpec helpers validate your application to make sure it has a class for every External task in a given BPMN file.\n```ruby\nrequire 'camunda/matchers'\n\nRSpec.describe \"BPMN Diagrams\" do\n  describe Camunda::BpmnXML.new(File.open(\"bpmn/diagrams/YourFile.bpmn\")) do\n    it { is_expected.to have_module('YourModule') }\n    it { is_expected.to have_topics(%w[YourModule]) }\n    it { is_expected.to have_defined_classes }\n  end\nend\n```\n\n## Contributing\n\nSee [CONTRIBUTING](CONTRIBUTING.md) for additional information.\n\n## Public domain\n\nThis project is in the worldwide [public domain](LICENSE.md). As stated in [CONTRIBUTING](CONTRIBUTING.md):\n\n\u003e This project is in the public domain within the United States, and copyright and related rights in the work worldwide are waived through the [CC0 1.0 Universal public domain dedication](https://creativecommons.org/publicdomain/zero/1.0/).\n\u003e\n\u003e All contributions to this project will be released under the CC0 dedication. By submitting a pull request, you are agreeing to comply with this waiver of copyright interest.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famalagaura%2Fcamunda-workflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famalagaura%2Fcamunda-workflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famalagaura%2Fcamunda-workflow/lists"}