Using GraphQL-API for custom tasklist

Hi guys,
I have a question about the setup in Camunda 8 regarding the Tasklist. We want to build a custom tasklist using GraphQL in an existing project that we have.

In there we have a docker-compose-setup where we put together all the containers (see below). And we are wondering, on which container can we access the GraphQL-API? Is this available via the tasklist(-container, so here port 8082) or can we also do this via Zebee?

Because it is a bit confusing, when despite implementing our own custom tasklist, we still need the container for the tasklist from Camunda? Also in terms of production, how is it distinguished if we are on a production-environment and using our own tasklist, in contrast to being on a non-prod-environment and using the Camunda Tasklist. Is there some kind of “switch” we can use to differentiate on which environment we are? Are there any “how to’s” or best pratices on how to handle this?

# While the Docker images themselves are supported for production usage,
# this docker-compose.yaml is designed to be used by developers to run
# an environment locally. It is not designed to be used in production.
# We recommend to use Kubernetes in production with our Helm Charts:
# https://docs.camunda.io/docs/self-managed/platform-deployment/kubernetes-helm/
# For local development, we recommend using KIND instead of `docker-compose`:
# https://docs.camunda.io/docs/self-managed/platform-deployment/kubernetes-helm/#installing-the-camunda-helm-chart-locally-using-kind

# This is a lightweight configuration with Zeebe, Operate, Tasklist, and Elasticsearch
# See docker-compose.yml for a configuration that also includes Optimize, Identity, and Keycloak.

services:

  zeebe: # https://docs.camunda.io/docs/self-managed/platform-deployment/docker/#zeebe
    image: camunda/zeebe:${CAMUNDA_PLATFORM_VERSION:-8.0.2}
    container_name: zeebe
    ports:
      - "26500:26500"
      - "9600:9600"
    environment: # https://docs.camunda.io/docs/self-managed/zeebe-deployment/configuration/environment-variables/
      - ZEEBE_BROKER_EXPORTERS_ELASTICSEARCH_CLASSNAME=io.camunda.zeebe.exporter.ElasticsearchExporter
      - ZEEBE_BROKER_EXPORTERS_ELASTICSEARCH_ARGS_URL=http://elasticsearch:9200
      - ZEEBE_BROKER_EXPORTERS_ELASTICSEARCH_ARGS_BULK_SIZE=1
      # allow running with low disk space
      - ZEEBE_BROKER_DATA_DISKUSAGECOMMANDWATERMARK=0.998
      - ZEEBE_BROKER_DATA_DISKUSAGEREPLICATIONWATERMARK=0.999
      - "JAVA_TOOL_OPTIONS=-Xms512m -Xmx512m"
    restart: always
    volumes:
      - zeebe:/usr/local/zeebe/data
    networks:
      - camunda-platform
    depends_on:
      - elasticsearch

  operate: # https://docs.camunda.io/docs/self-managed/platform-deployment/docker/#operate
    image: camunda/operate:${CAMUNDA_PLATFORM_VERSION:-8.0.2}
    container_name: operate
    ports:
      - "8081:8080"
    environment: # https://docs.camunda.io/docs/self-managed/operate-deployment/configuration/
      - CAMUNDA_OPERATE_ZEEBE_GATEWAYADDRESS=zeebe:26500
      - CAMUNDA_OPERATE_ELASTICSEARCH_URL=http://elasticsearch:9200
      - CAMUNDA_OPERATE_ZEEBEELASTICSEARCH_URL=http://elasticsearch:9200
    networks:
      - camunda-platform
    depends_on:
      - zeebe
      - elasticsearch

  tasklist: # https://docs.camunda.io/docs/self-managed/platform-deployment/docker/#tasklist
    image: camunda/tasklist:${CAMUNDA_PLATFORM_VERSION:-8.0.2}
    container_name: tasklist
    ports:
      - "8082:8080"
    environment: # https://docs.camunda.io/docs/self-managed/tasklist-deployment/configuration/
      - CAMUNDA_TASKLIST_ZEEBE_GATEWAYADDRESS=zeebe:26500
      - CAMUNDA_TASKLIST_ELASTICSEARCH_URL=http://elasticsearch:9200
      - CAMUNDA_TASKLIST_ZEEBEELASTICSEARCH_URL=http://elasticsearch:9200
    networks:
      - camunda-platform
    depends_on:
      - zeebe
      - elasticsearch

  elasticsearch: # https://hub.docker.com/_/elasticsearch
    image: docker.elastic.co/elasticsearch/elasticsearch:${ELASTIC_VERSION:-7.17.0}
    container_name: elasticsearch
    ports:
      - "9200:9200"
      - "9300:9300"
    environment:
          # disable security plug-in      
      - xpack.security.enabled=false
      - bootstrap.memory_lock=true
      - discovery.type=single-node
      # allow running with low disk space
      - cluster.routing.allocation.disk.threshold_enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    restart: always
    healthcheck:
      test: [ "CMD-SHELL", "curl -f http://localhost:9200/_cat/health | grep -q green" ]
      interval: 30s
      timeout: 5s
      retries: 3
    volumes:
      - elastic:/usr/share/elasticsearch/data
    networks:
      - camunda-platform

Hi

I will try to clarify things as I understand it.

The Docker compose file is provided by Camunda to make local development easy. You are not allowed to create a production setup using the Docker compose file and all the components used without a Camunda license.

As far as I recall, the only Camunda component you are allow to use without a license from Camunda is the Zeebe component (and there are limitations on that, so check the Zeebe license).

So to create a valid production setup without a Camunda license, you would then use the Zeebe broker(s) running either on a Kubernetes cluster, using Docker containers or as a local installation (Camunda Platform 8 deployment | Camunda Platform 8). You then need - some - access to the process instances / tasks to create your own tasklist. The Zeebe broker does not have a GraphQL API. You need to export the process data from the Zeebe brokers using the an exporter. You can use the Elasticsearch exporter, but a Hazelcast exporter is created by the community. That may also be an option.

Hope that helps.

BR
Michael

Hi @mimaom

okay, that cleares it up a little bit. So just for my better understanding the two scenarios:

With Camunda license in Production:

  • We can use the Tasklist-Container and the GraphQL-API that is integrated there to build our own tasklist.
  • And then we basically would have both tasklists running in parallel (on different ports, or can we overrite that, so only one of the is accessible)? The one that Camunda provides and our own?

Without Camunda license in Production:

  • We are NOT allowed to use the Tasklist-container provided by Camunda at all
  • And if we want to build our own tasklist, we also can NOT use the GraphQL-API directly, since this is integrated in the Tasklist-container?
  • In order to build a tasklist here, we need to export the data from the Zeebe brokers first (for example by using the Elasticsearch- or Hazelcast-exporter) and query this data somehow
  • Also the same holds true for Operate I guess?

Is my understanding correct now?

Hi @the-villain

I have not looked much at the task list application and I don’t know how tightly the UI is bound to the backend API. I don’t know if you can just have the API without the UI. Also, if you just want to use the task list API with your own task list UI, you - might - run into some issues around security.

And yes, I think Operate works the same way.

BR
Michael

Hello @the-villain ,

your understanding is correct on this.

Under the hood, tasklist and operate work in exactly the same way as you describe. They do not use internal apis from zeebe, they use the events to show the internal state of the engine. These events are exported to Elasticsearch by default. This exporter is also part of the docker-compose and if I am not terribly mistaken, it can be used under the same license as zeebe.

No fear there: Our license (source-available) works like open-source. The key difference is that you are not allowed to build a Saas offering for process automation using Zeebe (why would you, there is Camunda Cloud :wink: )

For production of a tasklist container, you could „hide“ the potentially unwanted UI to be accessed. I am not sure whether the tasklist container offers a „headless“ mode.

I hope this helps

Jonathan

@jonathan.lukas Okay, got it. Then just one follow-up question for querying the data:

  1. The Elasticsearch-exporter puts the data to ElasticSearch per default. Should we then go ahead and kind of “intercept” the data while its transported to Elasctic and read it from the exporter or should we in this case query the data directly from Elastic after the exporter has put it there?

  2. And is it then better/easier/more practical to either query the data from Elastic after the Elastic-exporter has put it there, or to use the Hazelcast-exporter and query the data directly from the exporter? Is there a preference?

Hello @the-villain ,

could you please open a.new topic on this and tag me there? I will answer your questions there. We came a bit off the gql topic :stuck_out_tongue:

Jonathan

Hello @the-villain ,

could you please open a.new topic on this and tag me there? I will answer your questions there. We came a bit off the gql topic :stuck_out_tongue:

Jonathan

Done: Extracting data from Zeebe-brokers for custom Tasklist :slightly_smiling_face:

1 Like