Changeset 33:2a4ad6e54491

Added kogito example
author unexist
date Thu, 15 Jul 2021 13:00:46 +0200
parents e196efc41724
children b2bc3ab6ab7b
files todo-service-kogito/src/main/docker/Dockerfile.fast-jar todo-service-kogito/src/main/docker/Dockerfile.jvm todo-service-kogito/src/main/docker/Dockerfile.native todo-service-kogito/src/main/java/dev/unexist/showcase/todo/adapter/KogitoResource.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/adapter/TodoResource.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/adapter/tasks/CamundaTodoCheckTask.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/adapter/tasks/CamundaTodoTallyTask.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/application/RestApplication.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/domain/todo/DueDate.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/domain/todo/Todo.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoBase.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoRepository.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoService.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/infrastructure/health/SimpleHealthCheck.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/ListTodoRepository.java todo-service-kogito/src/main/java/dev/unexist/showcase/todo/infrastructure/serializer/DateSerializer.java todo-service-kogito/src/main/resources/META-INF/resources/index.html todo-service-kogito/src/main/resources/application.properties todo-service-kogito/src/main/resources/todo.bpmn todo-service-kogito/src/main/resources/todo.drl todo-service-kogito/src/test/java/dev/unexist/showcase/todo/application/TodoResourceTest.java
diffstat 21 files changed, 1427 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/docker/Dockerfile.fast-jar	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,57 @@
+####
+# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
+#
+# Before building the container image run:
+#
+# mvn package
+#
+# Then, build the image with:
+#
+# docker build -f src/main/docker/Dockerfile.fast-jar -t quarkus/quarkus-kubernetes-showcase-fast-jar .
+#
+# Then run the container using:
+#
+# docker run -i --rm -p 8080:8080 quarkus/quarkus-kubernetes-showcase-fast-jar
+#
+# If you want to include the debug port into your docker image
+# you will have to expose the debug port (default 5005) like this :  EXPOSE 8080 5050
+# 
+# Then run the container using : 
+#
+# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/quarkus-kubernetes-showcase-fast-jar
+#
+###
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1
+
+ARG JAVA_PACKAGE=java-11-openjdk-headless
+ARG RUN_JAVA_VERSION=1.3.8
+
+ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
+
+# Install java and the run-java script
+# Also set up permissions for user `1001`
+RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
+    && microdnf update \
+    && microdnf clean all \
+    && mkdir /deployments \
+    && chown 1001 /deployments \
+    && chmod "g+rwX" /deployments \
+    && chown 1001:root /deployments \
+    && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
+    && chown 1001 /deployments/run-java.sh \
+    && chmod 540 /deployments/run-java.sh \
+    && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security
+
+# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
+ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
+
+# We make four distinct layers so if there are application changes the library layers can be re-used
+COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/
+COPY --chown=1001 target/quarkus-app/*.jar /deployments/
+COPY --chown=1001 target/quarkus-app/app/ /deployments/app/
+COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/
+
+EXPOSE 8080
+USER 1001
+
+ENTRYPOINT [ "/deployments/run-java.sh" ]
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/docker/Dockerfile.jvm	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,54 @@
+####
+# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
+#
+# Before building the container image run:
+#
+# mvn package
+#
+# Then, build the image with:
+#
+# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/quarkus-kubernetes-showcase-jvm .
+#
+# Then run the container using:
+#
+# docker run -i --rm -p 8080:8080 quarkus/quarkus-kubernetes-showcase-jvm
+#
+# If you want to include the debug port into your docker image
+# you will have to expose the debug port (default 5005) like this :  EXPOSE 8080 5050
+# 
+# Then run the container using : 
+#
+# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/quarkus-kubernetes-showcase-jvm
+#
+###
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1
+
+ARG JAVA_PACKAGE=java-11-openjdk-headless
+ARG RUN_JAVA_VERSION=1.3.8
+
+ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
+
+# Install java and the run-java script
+# Also set up permissions for user `1001`
+RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
+    && microdnf update \
+    && microdnf clean all \
+    && mkdir /deployments \
+    && chown 1001 /deployments \
+    && chmod "g+rwX" /deployments \
+    && chown 1001:root /deployments \
+    && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
+    && chown 1001 /deployments/run-java.sh \
+    && chmod 540 /deployments/run-java.sh \
+    && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security
+
+# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
+ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
+
+COPY target/lib/* /deployments/lib/
+COPY target/*-runner.jar /deployments/app.jar
+
+EXPOSE 8080
+USER 1001
+
+ENTRYPOINT [ "/deployments/run-java.sh" ]
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/docker/Dockerfile.native	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,27 @@
+####
+# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode
+#
+# Before building the container image run:
+#
+# mvn package -Pnative -Dquarkus.native.container-build=true
+#
+# Then, build the image with:
+#
+# docker build -f src/main/docker/Dockerfile.native -t quarkus/quarkus-kubernetes-showcase .
+#
+# Then run the container using:
+#
+# docker run -i --rm -p 8080:8080 quarkus/quarkus-kubernetes-showcase
+#
+###
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1
+WORKDIR /work/
+RUN chown 1001 /work \
+    && chmod "g+rwX" /work \
+    && chown 1001:root /work
+COPY --chown=1001:root target/*-runner /work/application
+
+EXPOSE 8080
+USER 1001
+
+CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/adapter/KogitoResource.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,74 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Camunda resource
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.adapter;
+
+import dev.unexist.showcase.todo.domain.todo.TodoBase;
+import dev.unexist.showcase.todo.infrastructure.camunda.CamundaEngine;
+import org.camunda.bpm.engine.ProcessEngine;
+import org.camunda.bpm.engine.runtime.ProcessInstance;
+import org.camunda.bpm.engine.variable.Variables;
+import org.camunda.bpm.engine.variable.value.ObjectValue;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
+import org.eclipse.microprofile.openapi.annotations.tags.Tag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.net.URI;
+
+@Path("/camunda")
+public class KogitoResource {
+    private static final Logger LOGGER = LoggerFactory.getLogger(KogitoResource.class);
+
+    @Inject
+    CamundaEngine camundaEngine;
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(summary = "Create new todo")
+    @Tag(name = "Todo")
+    @APIResponses({
+            @APIResponse(responseCode = "201", description = "Todo created"),
+            @APIResponse(responseCode = "406", description = "Bad data"),
+            @APIResponse(responseCode = "500", description = "Server error")
+    })
+    public Response create(TodoBase base, @Context UriInfo info) {
+        ProcessEngine ProcEngine = this.camundaEngine.getProcessEngine();
+
+        ObjectValue todoAsJson = Variables.objectValue(base)
+                        .serializationDataFormat("application/json").create();
+
+        ProcessInstance processInstance = ProcEngine.getRuntimeService()
+                .createProcessInstanceByKey("todo")
+                .setVariable("todo", todoAsJson)
+                .executeWithVariablesInReturn();
+
+        String id = processInstance.getId();
+
+        URI uri = info.getAbsolutePathBuilder().path("/" + id).build();
+
+        LOGGER.info("Process {} started", id);
+
+        return Response.created(uri).build();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/adapter/TodoResource.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,157 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Todo resource
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.adapter;
+
+import dev.unexist.showcase.todo.domain.todo.Todo;
+import dev.unexist.showcase.todo.domain.todo.TodoBase;
+import dev.unexist.showcase.todo.domain.todo.TodoService;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
+import org.eclipse.microprofile.openapi.annotations.media.Content;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
+import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
+import org.eclipse.microprofile.openapi.annotations.tags.Tag;
+
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.List;
+import java.util.Optional;
+
+@Path("/todo")
+public class TodoResource {
+
+    @Inject
+    TodoService todoService;
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(summary = "Create new todo")
+    @Tag(name = "Todo")
+    @APIResponses({
+            @APIResponse(responseCode = "201", description = "Todo created"),
+            @APIResponse(responseCode = "406", description = "Bad data"),
+            @APIResponse(responseCode = "500", description = "Server error")
+    })
+    public Response create(TodoBase base) {
+        Response.ResponseBuilder response;
+
+        if (this.todoService.create(base)) {
+            response = Response.status(Response.Status.CREATED);
+        } else {
+            response = Response.status(Response.Status.NOT_ACCEPTABLE);
+        }
+
+        return response.build();
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(summary = "Get all todos")
+    @Tag(name = "Todo")
+    @APIResponses({
+            @APIResponse(responseCode = "200", description = "List of todo", content =
+                @Content(schema = @Schema(type = SchemaType.ARRAY, implementation = Todo.class))),
+            @APIResponse(responseCode = "204", description = "Nothing found"),
+            @APIResponse(responseCode = "500", description = "Server error")
+    })
+    public Response getAll() {
+        List<Todo> todoList = this.todoService.getAll();
+
+        Response.ResponseBuilder response;
+
+        if (todoList.isEmpty()) {
+            response = Response.noContent();
+        } else {
+            response = Response.ok(Entity.json(todoList));
+        }
+
+        return response.build();
+    }
+
+    @GET
+    @Path("{id}")
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(summary = "Get todo by id")
+    @Tag(name = "Todo")
+    @APIResponses({
+            @APIResponse(responseCode = "200", description = "Todo found", content =
+                @Content(schema = @Schema(implementation = Todo.class))),
+            @APIResponse(responseCode = "404", description = "Todo not found"),
+            @APIResponse(responseCode = "500", description = "Server error")
+    })
+    public Response findById(@PathParam("id") int id) {
+        Optional<Todo> result = this.todoService.findById(id);
+
+        Response.ResponseBuilder response;
+
+        if (result.isPresent()) {
+            response = Response.ok(Entity.json(result.get()));
+        } else {
+            response = Response.status(Response.Status.NOT_FOUND);
+        }
+
+        return response.build();
+    }
+
+    @PUT
+    @Path("{id}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(summary = "Update todo by id")
+    @Tag(name = "Todo")
+    @APIResponses({
+            @APIResponse(responseCode = "204", description = "Todo updated"),
+            @APIResponse(responseCode = "404", description = "Todo not found"),
+            @APIResponse(responseCode = "500", description = "Server error")
+    })
+    public Response update(@PathParam("id") int id, TodoBase base) {
+        Response.ResponseBuilder response;
+
+        if (this.todoService.update(id, base)) {
+            response = Response.noContent();
+        } else {
+            response = Response.status(Response.Status.NOT_FOUND);
+        }
+
+        return response.build();
+    }
+
+    @DELETE
+    @Path("{id}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(summary = "Delete todo by id")
+    @Tag(name = "Todo")
+    public Response delete(@PathParam("id") int id) {
+        Response.ResponseBuilder response;
+
+        if (this.todoService.delete(id)) {
+            response = Response.noContent();
+        } else {
+            response = Response.status(Response.Status.NOT_FOUND);
+        }
+
+        return response.build();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/adapter/tasks/CamundaTodoCheckTask.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,42 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Camunda todo check task
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.adapter.tasks;
+
+import dev.unexist.showcase.todo.domain.todo.TodoBase;
+import dev.unexist.showcase.todo.domain.todo.TodoService;
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.camunda.bpm.engine.delegate.JavaDelegate;
+import org.camunda.bpm.engine.variable.VariableMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.Dependent;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+@Dependent
+@Named
+public class CamundaTodoCheckTask implements JavaDelegate {
+    private static final Logger LOGGER = LoggerFactory.getLogger(CamundaTodoCheckTask.class);
+
+    @Inject
+    TodoService todoService;
+
+    @Override
+    public void execute(DelegateExecution execution) throws Exception {
+        VariableMap varMap = execution.getVariablesTyped();
+
+        final TodoBase todo = varMap.getValue("todo", TodoBase.class);
+
+        LOGGER.info("Todo check task: {}, total: {}", todo, this.todoService);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/adapter/tasks/CamundaTodoTallyTask.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,37 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Camunda todo tally task
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.adapter.tasks;
+
+import dev.unexist.showcase.todo.domain.todo.TodoBase;
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.camunda.bpm.engine.delegate.JavaDelegate;
+import org.camunda.bpm.engine.variable.VariableMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.Dependent;
+import javax.inject.Named;
+
+@Dependent
+@Named
+public class CamundaTodoTallyTask implements JavaDelegate {
+    private static final Logger LOGGER = LoggerFactory.getLogger(CamundaTodoTallyTask.class);
+
+    @Override
+    public void execute(DelegateExecution execution) throws Exception {
+        VariableMap varMap = execution.getVariablesTyped();
+
+        final TodoBase todo = varMap.getValue("todo", TodoBase.class);
+
+        LOGGER.info("Todo tally task: {}", todo);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/application/RestApplication.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,17 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Todo application
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.application;
+
+import javax.ws.rs.core.Application;
+
+public class RestApplication extends Application {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/domain/todo/DueDate.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,72 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file DueDate class
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.domain.todo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import dev.unexist.showcase.todo.infrastructure.serializer.DateSerializer;
+
+import java.time.LocalDate;
+
+public class DueDate {
+    @JsonSerialize(using = DateSerializer.class)
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
+    private LocalDate start;
+
+    @JsonSerialize(using = DateSerializer.class)
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
+    private LocalDate due;
+
+    /**
+     * Get start date
+     *
+     * @return
+     *      Start date
+     **/
+
+    public LocalDate getStart() {
+        return start;
+    }
+
+    /**
+     * Set start date
+     *
+     * @param start
+     *          Date to set
+     **/
+
+    public void setStart(LocalDate start) {
+        this.start = start;
+    }
+
+    /**
+     * Get due date
+     *
+     * @return
+     *          Due date
+     **/
+
+    public LocalDate getDue() {
+        return due;
+    }
+
+    /**
+     * Set due date
+     *
+     * @param due
+     *          Date to set
+     **/
+
+    public void setDue(LocalDate due) {
+        this.due = due;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/domain/todo/Todo.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,76 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Todo class and aggregate root
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.domain.todo;
+
+public class Todo extends TodoBase {
+    private int id;
+
+    /**
+     * Constructor
+     **/
+
+    public Todo() {
+    }
+
+    public Todo(final String title, final String description) {
+        this.setTitle(title);
+        this.setDescription(description);
+    }
+
+
+    /**
+     * Constructor
+     *
+     * @param base
+     *          Base entry
+     **/
+
+    public Todo(final TodoBase base) {
+        this.update(base);
+    }
+
+    /**
+     * Update values from base
+     *
+     * @param base
+     *          Todo base class
+     **/
+
+    public void update(final TodoBase base) {
+        this.setDueDate(base.getDueDate());
+        this.setTitle(base.getTitle());
+        this.setDescription(base.getDescription());
+        this.setDone(base.getDone());
+    }
+
+    /**
+     * Get id of entry
+     *
+     * @return
+     *          Id of the entry
+     **/
+
+    public int getId() {
+        return id;
+    }
+
+    /**
+     * Set id of entry
+     *
+     * @param id
+     *          Id of the entry
+     **/
+
+    public void setId(int id) {
+        this.id = id;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoBase.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,121 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Todo base class
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.domain.todo;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+public class TodoBase {
+
+    @NotBlank
+    private String title;
+
+    @NotBlank
+    private String description;
+
+    private Boolean done;
+
+    @NotNull
+    private DueDate dueDate;
+
+    /**
+     * Get title of the entry
+     *
+     * @return
+     *      Title of the entry
+     **/
+
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * Set title of the entry
+     *
+     * @param title
+     *          Title of the entry
+     **/
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    /**
+     * Get description of entry
+     *
+     * @return
+     *      Description of the entry
+     **/
+
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * Set description of the entry
+     *
+     * @param description
+     *          Description of the entry
+     **/
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    /**
+     * Get done state of entry
+     *
+     * @return
+     *      Done state of the entry
+     **/
+
+    public Boolean getDone() {
+        return done;
+    }
+
+    /**
+     * Set done state of entry
+     *
+     * @param done
+     *          Done state of the entry
+     **/
+
+    public void setDone(Boolean done) {
+        this.done = done;
+    }
+
+    /**
+     * Get due state of the entry
+     *
+     * @return
+     *          Due state of the entry
+     **/
+
+    public DueDate getDueDate() {
+        return dueDate;
+    }
+
+    /**
+     * Set due date of the entry
+     *
+     * @param dueDate
+     *          Due date of the entry
+     **/
+
+    public void setDueDate(DueDate dueDate) {
+        this.dueDate = dueDate;
+
+        if (null != dueDate.getStart() && null != dueDate.getDue()) {
+            this.done = dueDate.getStart().isBefore(dueDate.getDue());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoRepository.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,70 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Todo repository interface
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.domain.todo;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface TodoRepository {
+
+    /**
+     * Add {@link Todo} entry to list
+     *
+     * @param todo
+     *          {@link Todo} entry to add
+     * @return
+     *          Either {@code true} on success; otherwise {@code false}
+     **/
+
+    boolean add(Todo todo);
+
+    /**
+     * Update {@link Todo} with given id
+     *
+     * @param todo
+     *          A {@link Todo} to update
+     * @return
+     *          Either {@code true} on success; otherwise {@code false}
+     **/
+
+    boolean update(Todo todo);
+
+    /**
+     * Delete {@link Todo} with given id
+     *
+     * @param id
+     *          Id to delete
+     * @return
+     *          Either {@code true} on success; otherwise {@code false}
+     **/
+
+    boolean deleteById(int id);
+
+    /**
+     * Get all {@link Todo} entries
+     *
+     * @return List of all stored {@link Todo}
+     **/
+
+    List<Todo> getAll();
+
+    /**
+     * Find {@link Todo} by given id
+     *
+     * @param id
+     *          Id to find
+     * @return
+     *          A {@link Optional} with the result of the lookup
+     **/
+
+    Optional<Todo> findById(int id);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoService.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,100 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Todo service and domain service
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.domain.todo;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import java.util.List;
+import java.util.Optional;
+
+@ApplicationScoped
+public class TodoService {
+
+    @Inject
+    TodoRepository todoRepository;
+
+    /**
+     * Create new {@link Todo} entry and store it in repository
+     *
+     * @param base
+     *          A {@link TodoBase} entry
+     * @return
+     *          Either {@code true} on success; otherwise {@code false}
+     **/
+
+    public boolean create(TodoBase base) {
+        Todo todo = new Todo(base);
+
+        return this.todoRepository.add(todo);
+    }
+
+    /**
+     * Update {@link Todo} at with given id
+     *
+     * @param id
+     *          Id to update
+     * @param base
+     *          Values for the entry
+     * @return
+     *          Either {@code true} on success; otherwise {@code false}
+     **/
+
+    public boolean update(int id, TodoBase base) {
+        Optional<Todo> todo = this.findById(id);
+        boolean ret = false;
+
+        if (todo.isPresent()) {
+            todo.get().update(base);
+
+            ret = this.todoRepository.update(todo.get());
+        }
+
+        return ret;
+    }
+
+    /**
+     * Delete {@link Todo} with given id
+     *
+     * @param id
+     *          Id to delete
+     * @return
+     *          Either {@code true} on success; otherwise {@code false}
+     **/
+
+    public boolean delete(int id) {
+        return this.todoRepository.deleteById(id);
+    }
+
+    /**
+     * Get all {@link Todo} entries
+     *
+     * @return
+     *          List of all {@link Todo}; might be empty
+     **/
+
+    public List<Todo> getAll() {
+        return this.todoRepository.getAll();
+    }
+
+    /**
+     * Find {@link Todo} by given id
+     *
+     * @param id
+     *          Id to look for
+     * @return
+     *          A {@link Optional} of the entry
+     **/
+
+    public Optional<Todo> findById(int id) {
+        return this.todoRepository.findById(id);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/infrastructure/health/SimpleHealthCheck.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,35 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Simple health check
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.infrastructure.health;
+
+import org.eclipse.microprofile.health.HealthCheck;
+import org.eclipse.microprofile.health.HealthCheckResponse;
+import org.eclipse.microprofile.health.Liveness;
+
+import javax.enterprise.context.ApplicationScoped;
+
+@Liveness
+@ApplicationScoped
+public class SimpleHealthCheck implements HealthCheck {
+
+    /**
+     * Call of the healthcheck
+     *
+     * @return
+     *      Reponse of the healthcheck
+     **/
+
+    @Override
+    public HealthCheckResponse call() {
+        return HealthCheckResponse.up("Simple health check");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/ListTodoRepository.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,87 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Todo repository
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.infrastructure.persistence;
+
+import dev.unexist.showcase.todo.domain.todo.Todo;
+import dev.unexist.showcase.todo.domain.todo.TodoRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.ApplicationScoped;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+@ApplicationScoped
+public class ListTodoRepository implements TodoRepository {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ListTodoRepository.class);
+
+    private final List<Todo> list;
+
+    /**
+     * Constructor
+     **/
+
+    ListTodoRepository() {
+        this.list = new ArrayList<>();
+    }
+
+    @Override
+    public boolean add(final Todo todo) {
+        todo.setId(this.list.size() + 1);
+
+        return this.list.add(todo);
+    }
+
+    @Override
+    public boolean update(final Todo todo) {
+        boolean ret = false;
+
+        try {
+            this.list.set(todo.getId(), todo);
+
+            ret = true;
+        } catch (IndexOutOfBoundsException e) {
+            LOGGER.warn("update: id={} not found", todo.getId());
+        }
+
+        return ret;
+    }
+
+    @Override
+    public boolean deleteById(int id) {
+        boolean ret = false;
+
+        try {
+            this.list.remove(id);
+
+            ret = true;
+        } catch (IndexOutOfBoundsException e) {
+            LOGGER.warn("update: id={} not found", id);
+        }
+
+        return ret;
+    }
+
+    @Override
+    public List<Todo> getAll() {
+        return Collections.unmodifiableList(this.list);
+    }
+
+    @Override
+    public Optional<Todo> findById(int id) {
+        return this.list.stream()
+                .filter(t -> t.getId() == id)
+                .findFirst();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/java/dev/unexist/showcase/todo/infrastructure/serializer/DateSerializer.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,29 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Todo serializer
+ * @copyright 2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.infrastructure.serializer;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+import java.io.IOException;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+public class DateSerializer extends JsonSerializer<LocalDate> {
+
+    @Override
+    public void serialize(LocalDate value, JsonGenerator gen,
+                          SerializerProvider serializers) throws IOException {
+        gen.writeString(value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/resources/META-INF/resources/index.html	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,233 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>unexist.dev</title>
+    <style type="text/css">
+        :root {
+            /* Colors */
+            --font-color: #fff;
+            --font-color2: #aaa;
+            --link-color: #8cf;
+            --highlight-color: #ff8000;
+            --border-color: #446979;
+            --top-color: #313536;
+            --bottom-color: #1D2021;
+            --h1-color: #888;
+            --h2-color: #777;
+            --h3-color: #666;
+            --h4-color: #d7ba7d;
+            --code-color: #d7ba7d;
+            --cite-color: #777;
+
+            /* Misc */
+            --margin: 10px;
+            --padding: 10px;
+            --radius: 8px;
+            --border: 1px solid var(--top-color);
+        }
+
+        * {
+            margin: 0px;
+            padding: 0px;
+        }
+
+        /* Layout */
+        body {
+            background-color: var(--bottom-color);
+            color: var(--font-color);
+            font-family: HelveticaNeue,"Helvetica Neue",Helvetica,Arial,sans-serif;
+        }
+
+        nav {
+            background-color: var(--bottom-color);
+            border-radius: var(--radius) var(--radius) 0px 0px;
+            font-size: 90%;
+        }
+
+        footer {
+            color: var(--font-color2);
+            background-color: var(--top-color);
+            border-left: var(--border);
+            border-right: var(--border);
+            border-bottom: var(--border);
+            border-radius: 0px 0px var(--radius) var(--radius);
+            font-size: 70%;
+            text-align: center;
+        }
+
+        footer a:link, footer a:visited {
+            color: var(--font-color2);
+            text-decoration: underline;
+        }
+
+        footer a:hover {
+            color: var(--link-color);
+            text-decoration: none;
+        }
+
+        #container {
+            width: 100%;
+        }
+
+        #split {
+            display: table;
+            padding-top: var(--padding);
+            border-left: var(--border);
+            border-right: var(--border);
+        }
+
+        #content {
+            display: table-cell;
+            padding-right: var(--padding);
+        }
+
+        #content h1 {
+            text-decoration: none;
+            border-bottom: 1px solid var(--h1-color);
+            margin-bottom: 10px;
+        }
+
+        #content h2 {
+            text-decoration: none;
+            border-bottom: 1px solid var(--h2-color);
+            margin-bottom: 10px;
+        }
+
+        #sidebar a {
+            display: block;
+        }
+
+        #header {
+            background-color: var(--top-color);
+            width: 100%;
+        }
+
+        #headline, #split, nav, footer {
+            width: 70%;
+            margin: 0px auto;
+            padding: var(--padding);
+
+            /* Stupid hack */
+            min-width: 844px;
+        }
+
+        @media screen and (max-width: 899px) {
+            #headline, #split, nav, footer {
+                width: 100%;
+            }
+        }
+
+        #headline h1 {
+            display: inline-block;
+            text-decoration: none;
+            border-bottom: none;
+        }
+
+        #headline h2 {
+            display: inline-block;
+            padding-left: var(--padding);
+            border-bottom: none;
+        }
+
+        /* Text */
+        a:link, a:visited {
+            text-decoration: none;
+            color: var(--link-color);
+        }
+
+        a:hover {
+            color: var(--highlight-color);
+        }
+
+        h1 {
+            color: var(--h1-color);
+            text-decoration: none;
+            border-bottom: 1px solid var(--h1-color);
+        }
+
+        h2 {
+            color: var(--h2-color);
+            text-decoration: none;
+            border-bottom: 1px solid var(--h2-color);
+        }
+
+        h3 {
+            color: var(--h3-color);
+            text-decoration: underline;
+            display: inline;
+        }
+
+        h3, h4 {
+            padding-top: 10px;
+        }
+
+        h4 {
+            color: var(--h4-color);
+        }
+
+        .post-content li {
+            margin-left: 40px;
+            padding: 0px 0px var(--padding) 0px;
+            color: var(--font-color2);
+        }
+    </style>
+</head>
+<body>
+<div id="container">
+    <div id="header">
+        <div id="headline">
+            <h1>unexist.dev</h1>
+            <h2></h2>
+            <h2></h2>
+            <p>Showcase for @project.artifactId@</p>
+        </div>
+        <nav>
+            <a href="/">Home</a>
+            <a href="https://unexist.dev">Projects</a>
+            <a href="https://hg.unexist.dev">Repositories</a>
+        </nav>
+    </div>
+    <div id="split">
+        <div id="content">
+            <div id="posts">
+                <h2>Information</h2>
+
+                <div class="post-content">
+                    <ul>
+                        <li>
+                            <h3>Group</h3>: @project.groupId@
+                        </li>
+                        <li>
+                            <h3>Artifact</h3>: @project.artifactId@
+                        </li>
+                        <li>
+                            <h3>Version</h3>: @project.version@
+                        </li>
+                        <li>
+                            <h3>Build</h3> on @timestamp@ by @hg.author@
+                        </li>
+                    </ul>
+                </div>
+
+                <h2>Links</h2>
+
+                <div class="post-content">
+                    <ul>
+                        <li><a href="/q/dev">Developer console</a></li>
+                        <li><a href="/q/swagger-ui">Swagger UI</a></li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+    </div>
+    <footer>
+        <a href="/feed.xml">RSS</a>
+        &middot;
+        <a href="https://github.com/unexist">unexist @ GitHub</a>
+        &middot;
+        <a href="https://twitter.com/chkappel">unexist @ Twitter</a>
+    </footer>
+</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/resources/application.properties	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,38 @@
+# Configuration file
+# key = value
+#quarkus.swagger-ui.always-include=true
+#quarkus.servlet.context-path=/todo
+
+# Disable pass-though of infrastructure health
+#quarkus.datasource.health=false
+#quarkus.reactive-messaging.enabled=false
+#kafka.health.enabled=false
+
+# Opencontainers labels (https://github.com/opencontainers/image-spec/blob/master/annotations.md)
+quarkus.jib.labels."org.opencontainers.image.created"=@timestamp@
+quarkus.jib.labels."org.opencontainers.image.authors"=@hg.author@
+quarkus.jib.labels."org.opencontainers.image.url"=https://unexist.dev
+#quarkus.jib.labels."org.opencontainers.image.documentation"=DOCS
+#quarkus.jib.labels."org.opencontainers.image.source"=SRC
+quarkus.jib.labels."org.opencontainers.image.version"=@project.version@
+quarkus.jib.labels."org.opencontainers.image.revision"=@hg.rev@
+quarkus.jib.labels."org.opencontainers.image.licenses"=GPLv3
+quarkus.jib.labels."org.opencontainers.image.title"=@project.artifactId@
+quarkus.jib.labels."org.opencontainers.image.description"=@project.name@
+
+# OpenAPI3 specifications (https://quarkus.io/blog/openapi-for-everyone)
+mp.openapi.extensions.smallrye.info.title=OpenAPI for @project.artifactId@
+%dev.mp.openapi.extensions.smallrye.info.title=OpenAPI for @project.artifactId@ [development]
+%test.mp.openapi.extensions.smallrye.info.title=OpenAPI for @project.artifactId@ [test]
+mp.openapi.extensions.smallrye.info.version=@project.version@
+mp.openapi.extensions.smallrye.info.description=Last build on @timestamp@
+mp.openapi.extensions.smallrye.info.contact.email=christoph@unexist.dev
+mp.openapi.extensions.smallrye.info.contact.name=@hg.author@
+mp.openapi.extensions.smallrye.info.contact.url=https://unexist.dev
+mp.openapi.extensions.smallrye.info.license.name=GPLv3
+mp.openapi.extensions.smallrye.info.license.url=https://www.gnu.org/licenses/gpl-3.0.html
+
+# Database
+quarkus.datasource.db-kind=h2
+quarkus.datasource.username=username-default
+#quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:default
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/resources/todo.bpmn	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0aui0ws" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1">
+  <bpmn:process id="todo" name="Todo" isExecutable="true" camunda:versionTag="0.1">
+    <bpmn:startEvent id="StartEvent_1" name="Todo Retrieved">
+      <bpmn:outgoing>SequenceFlow_1p2szow</bpmn:outgoing>
+    </bpmn:startEvent>
+    <bpmn:serviceTask id="Task_19pt1nu" name="Tally Todo " camunda:class="dev.unexist.showcase.todo.adapter.tasks.CamundaTodoTallyTask">
+      <bpmn:incoming>SequenceFlow_04u8b2b</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_1axd8hr</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:endEvent id="EndEvent_1oyw02k" name="Todo Done">
+      <bpmn:incoming>SequenceFlow_1axd8hr</bpmn:incoming>
+    </bpmn:endEvent>
+    <bpmn:sequenceFlow id="SequenceFlow_1axd8hr" sourceRef="Task_19pt1nu" targetRef="EndEvent_1oyw02k" />
+    <bpmn:serviceTask id="Task_0q4zvgp" name="Check Todo" camunda:delegateExpression="${camundaTodoCheckTask}">
+      <bpmn:incoming>SequenceFlow_1p2szow</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_04u8b2b</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:sequenceFlow id="SequenceFlow_1p2szow" sourceRef="StartEvent_1" targetRef="Task_0q4zvgp" />
+    <bpmn:sequenceFlow id="SequenceFlow_04u8b2b" sourceRef="Task_0q4zvgp" targetRef="Task_19pt1nu" />
+  </bpmn:process>
+  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
+    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="todo">
+      <bpmndi:BPMNEdge id="SequenceFlow_04u8b2b_di" bpmnElement="SequenceFlow_04u8b2b">
+        <di:waypoint x="410" y="119" />
+        <di:waypoint x="480" y="119" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_1p2szow_di" bpmnElement="SequenceFlow_1p2szow">
+        <di:waypoint x="200" y="119" />
+        <di:waypoint x="310" y="119" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_1axd8hr_di" bpmnElement="SequenceFlow_1axd8hr">
+        <di:waypoint x="580" y="119" />
+        <di:waypoint x="662" y="119" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="345.5" y="98.5" width="90" height="13" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
+        <dc:Bounds x="164" y="101" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="145" y="137" width="74" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ServiceTask_17yjgnl_di" bpmnElement="Task_19pt1nu">
+        <dc:Bounds x="480" y="79" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="EndEvent_1oyw02k_di" bpmnElement="EndEvent_1oyw02k">
+        <dc:Bounds x="662" y="101" width="36" height="36" />
+        <bpmndi:BPMNLabel>
+          <dc:Bounds x="654" y="147" width="54" height="14" />
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="ServiceTask_1m8bv3v_di" bpmnElement="Task_0q4zvgp">
+        <dc:Bounds x="310" y="79" width="100" height="80" />
+      </bpmndi:BPMNShape>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</bpmn:definitions>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/main/resources/todo.drl	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,13 @@
+package dev.unexist.showcase.todo.adapter;
+dialect  "mvel"
+
+import dev.unexist.showcase.todo.domain.todo.TodoBase;
+
+rule "isDone" ruleflow-group "todo"
+    when
+        $todo: TodoBase(2 > 1)
+    then
+        modify($todo) {
+            setDone(true)
+        }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-kogito/src/test/java/dev/unexist/showcase/todo/application/TodoResourceTest.java	Thu Jul 15 13:00:46 2021 +0200
@@ -0,0 +1,29 @@
+/**
+ * @package Quarkus-Workflow-Showcase
+ *
+ * @file Stupid integration test
+ * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev>
+ * @version $Id$
+ *
+ * This program can be distributed under the terms of the GNU GPLv3.
+ * See the file LICENSE for details.
+ **/
+
+package dev.unexist.showcase.todo.application;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.given;
+
+@QuarkusTest
+public class TodoResourceTest {
+
+    @Test
+    public void testTodoEndpoint() {
+        given()
+          .when().get("/todo")
+          .then()
+             .statusCode(204);
+    }
+}
\ No newline at end of file