Changeset 19:c69cb6b387d1

Restructured and renamed modules
author unexist
date Mon, 24 May 2021 18:50:58 +0200
parents 648ea8bd03cb
children 2539126802a1
files pom.xml todo-service-debezium/src/main/java/dev/unexist/showcase/todo/domain/todo/DueDate.java todo-service-standalone/pom.xml todo-service-standalone/src/main/docker/Dockerfile.fast-jar todo-service-standalone/src/main/docker/Dockerfile.jvm todo-service-standalone/src/main/docker/Dockerfile.native todo-service-standalone/src/main/java/dev/unexist/showcase/todo/adapter/TodoResource.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/application/RestApplication.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/domain/todo/DueDate.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/domain/todo/Todo.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoBase.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoRepository.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoService.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxEntity.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxEvent.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxRepository.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxService.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/OutboxRepositoryImpl.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/TodoRepositoryImpl.java todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/serializer/DateSerializer.java todo-service-standalone/src/main/resources/META-INF/resources/index.html todo-service-standalone/src/main/resources/application.properties todo-service-standalone/src/test/java/dev/unexist/showcase/todo/NativeTodoResourceIT.java todo-service-standalone/src/test/java/dev/unexist/showcase/todo/application/TodoResourceTest.java todo-service/pom.xml todo-service/src/main/docker/Dockerfile.fast-jar todo-service/src/main/docker/Dockerfile.jvm todo-service/src/main/docker/Dockerfile.native todo-service/src/main/java/dev/unexist/showcase/todo/adapter/TodoResource.java todo-service/src/main/java/dev/unexist/showcase/todo/application/RestApplication.java todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/DueDate.java todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/Todo.java todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoBase.java todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoRepository.java todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoService.java todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxEntity.java todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxEvent.java todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxRepository.java todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxService.java todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/OutboxRepositoryImpl.java todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/TodoRepositoryImpl.java todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/serializer/DateSerializer.java todo-service/src/main/resources/META-INF/resources/index.html todo-service/src/main/resources/application.properties todo-service/src/test/java/dev/unexist/showcase/todo/NativeTodoResourceIT.java todo-service/src/test/java/dev/unexist/showcase/todo/application/TodoResourceTest.java
diffstat 46 files changed, 1433 insertions(+), 1360 deletions(-) [+]
line wrap: on
line diff
--- a/pom.xml	Fri May 07 15:11:08 2021 +0200
+++ b/pom.xml	Mon May 24 18:50:58 2021 +0200
@@ -15,6 +15,7 @@
 
     <modules>
         <module>debezium-transformer</module>
-        <module>todo-service</module>
+        <module>todo-service-debezium</module>
+        <module>todo-service-standalone</module>
     </modules>
 </project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-debezium/src/main/java/dev/unexist/showcase/todo/domain/todo/DueDate.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,72 @@
+/**
+ * @package Quarkus-Kubernetes-Showcase
+ *
+ * @file DueDate class
+ * @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.domain.todo;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import dev.unexist.showcase.todo.infrastructure.serializer.DateSerializer;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Embedded;
+import java.time.LocalDate;
+
+@Embeddable
+public class DueDate {
+    @JsonSerialize(using = DateSerializer.class)
+    private LocalDate start;
+
+    @JsonSerialize(using = DateSerializer.class)
+    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-standalone/pom.xml	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>todo-service-standalone</artifactId>
+    <version>0.1</version>
+
+    <parent>
+        <groupId>dev.unexist.showcase</groupId>
+        <artifactId>quarkus-outbox-showcase</artifactId>
+        <version>0.1</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <dependencies>
+        <!-- Database -->
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-hibernate-orm</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-jdbc-postgresql</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-devservices-postgresql</artifactId>
+        </dependency>
+    </dependencies>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/main/docker/Dockerfile.fast-jar	Mon May 24 18:50:58 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-standalone/src/main/docker/Dockerfile.jvm	Mon May 24 18:50:58 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-standalone/src/main/docker/Dockerfile.native	Mon May 24 18:50:58 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-standalone/src/main/java/dev/unexist/showcase/todo/adapter/TodoResource.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,157 @@
+/**
+ * @package Quarkus-Kubernetes-Showcase
+ *
+ * @file Todo resource
+ * @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.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, TodoBase base) {
+        Response.ResponseBuilder response;
+
+        if (this.todoService.delete(id)) {
+            response = Response.noContent();
+        } else {
+            response = Response.status(Response.Status.NOT_FOUND);
+        }
+
+        return response.build();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/main/java/dev/unexist/showcase/todo/application/RestApplication.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,17 @@
+/**
+ * @package Quarkus-Kubernetes-Showcase
+ *
+ * @file Todo application
+ * @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 javax.ws.rs.core.Application;
+
+public class RestApplication extends Application {
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/main/java/dev/unexist/showcase/todo/domain/todo/DueDate.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,72 @@
+/**
+ * @package Quarkus-Kubernetes-Showcase
+ *
+ * @file DueDate class
+ * @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.domain.todo;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import dev.unexist.showcase.todo.infrastructure.serializer.DateSerializer;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Embedded;
+import java.time.LocalDate;
+
+@Embeddable
+public class DueDate {
+    @JsonSerialize(using = DateSerializer.class)
+    private LocalDate start;
+
+    @JsonSerialize(using = DateSerializer.class)
+    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-standalone/src/main/java/dev/unexist/showcase/todo/domain/todo/Todo.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,90 @@
+/**
+ * @package Quarkus-Kubernetes-Showcase
+ *
+ * @file Todo class and aggregate root
+ * @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.domain.todo;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "Todos")
+@NamedQueries({
+        @NamedQuery(name = Todo.FIND_ALL, query = "SELECT t FROM Todo t"),
+        @NamedQuery(name = Todo.FIND_BY_ID, query = "SELECT t FROM Todo t WHERE t.id = :id")
+})
+public class Todo extends TodoBase {
+    public static final String FIND_ALL = "Todo.findAll";
+    public static final String FIND_BY_ID = "Todo.findById";
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.SEQUENCE)
+    private int id;
+
+    /**
+     * Constructor
+     **/
+
+    public Todo() {
+    }
+
+
+    /**
+     * 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-standalone/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoBase.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,127 @@
+/**
+ * @package Quarkus-Kubernetes-Showcase
+ *
+ * @file Todo base class
+ * @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.domain.todo;
+
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.MappedSuperclass;
+import javax.validation.constraints.NotBlank;
+
+@MappedSuperclass
+public class TodoBase {
+
+    @NotBlank
+    @Column
+    private String title;
+
+    @NotBlank
+    @Column
+    private String description;
+
+    @Column
+    private Boolean done;
+
+    @Embedded
+    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-standalone/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoRepository.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,70 @@
+/**
+ * @package Quarkus-Kubernetes-Showcase
+ *
+ * @file Todo repository interface
+ * @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.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-standalone/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoService.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,133 @@
+/**
+ * @package Quarkus-Kubernetes-Showcase
+ *
+ * @file Todo domain service
+ * @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.domain.todo;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import dev.unexist.showcase.todo.infrastructure.outbox.OutboxEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Event;
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+import java.util.List;
+import java.util.Optional;
+
+@ApplicationScoped
+public class TodoService {
+    private static final Logger LOGGER = LoggerFactory.getLogger(TodoService.class);
+
+    @Inject
+    TodoRepository todoRepository;
+
+    @Inject
+    Event<OutboxEvent> eventHandler;
+
+    /**
+     * 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}
+     **/
+
+    @Transactional
+    public boolean create(TodoBase base) {
+        boolean retval = true;
+        Todo todo = new Todo(base);
+
+        this.todoRepository.add(todo);
+
+        OutboxEvent event = new OutboxEvent();
+
+        event.setAggregateId(todo.getId());
+        event.setEventType("todo_created");
+
+        try {
+            ObjectMapper mapper = new ObjectMapper();
+
+            event.setPayload(mapper.writeValueAsString(todo));
+        } catch (JsonProcessingException jpe) {
+            LOGGER.warn("Json error: {}", jpe.getMessage(), jpe);
+
+            retval = false;
+        }
+
+        this.eventHandler.fire(event);
+
+        return retval;
+    }
+
+    /**
+     * 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-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxEntity.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,52 @@
+/**
+ * @package Quarkus-Outbox-Showcase
+ *
+ * @file Outbox entity
+ * @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.infrastructure.outbox;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.Date;
+import java.util.UUID;
+
+import static java.util.Objects.requireNonNull;
+
+@Entity
+@Table(name = "OUTBOX")
+public class OutboxEntity {
+
+    @Id
+    @Column(name = "uuid")
+    private UUID uuid;
+
+    @Column(name = "aggregateId")
+    private Integer aggregateId;
+
+    @Column(name = "eventType")
+    private String eventType;
+
+    @Column(name = "payload")
+    private String payload;
+
+    @Column(name = "createdOn")
+    private Date createdOn;
+
+    protected OutboxEntity() {
+    }
+
+    public OutboxEntity(UUID uuid, Integer aggregateId, String eventType, String payload) {
+        this.uuid = requireNonNull(uuid);
+        this.aggregateId = requireNonNull(aggregateId);
+        this.eventType = requireNonNull(eventType);
+        this.payload = requireNonNull(payload);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxEvent.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,42 @@
+/**
+ * @package Quarkus-Outbox-Showcase
+ *
+ * @file Outbox event
+ * @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.infrastructure.outbox;
+
+public class OutboxEvent {
+    private Integer aggregateId;
+    private String eventType;
+    private String payload;
+
+    public Integer getAggregateId() {
+        return aggregateId;
+    }
+
+    public void setAggregateId(Integer aggregateId) {
+        this.aggregateId = aggregateId;
+    }
+
+    public String getEventType() {
+        return eventType;
+    }
+
+    public void setEventType(String eventType) {
+        this.eventType = eventType;
+    }
+
+    public String getPayload() {
+        return payload;
+    }
+
+    public void setPayload(String payload) {
+        this.payload = payload;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxRepository.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,26 @@
+/**
+ * @package Quarkus-Outbox-Showcase
+ *
+ * @file Outbox repository interface
+ * @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.infrastructure.outbox;
+
+public interface OutboxRepository {
+
+    /**
+     * Add {@link OutboxEntity} entry to list
+     *
+     * @param entity
+     *          {@link OutboxEntity} entry to add
+     * @return
+     *          Either {@code true} on success; otherwise {@code false}
+     **/
+
+    boolean add(OutboxEntity entity);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxService.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,40 @@
+/**
+ * @package Quarkus-Outbox-Showcase
+ *
+ * @file Outbox domain service
+ * @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.infrastructure.outbox;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import javax.enterprise.event.TransactionPhase;
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+import java.util.UUID;
+
+import static javax.transaction.Transactional.TxType.REQUIRES_NEW;
+
+@ApplicationScoped
+public class OutboxService {
+
+    @Inject
+    OutboxRepository outboxRepository;
+
+    @Transactional(REQUIRES_NEW)
+    public void handleOutboxEvent(@Observes(during = TransactionPhase.AFTER_SUCCESS) OutboxEvent event) {
+        UUID uuid = UUID.randomUUID();
+
+        OutboxEntity entity = new OutboxEntity(uuid,
+            event.getAggregateId(),
+            event.getEventType(),
+            event.getPayload());
+
+        outboxRepository.add(entity);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/OutboxRepositoryImpl.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,33 @@
+/**
+ * @package Quarkus-Kubernetes-Showcase
+ *
+ * @file Outbox repository
+ * @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.infrastructure.persistence;
+
+import dev.unexist.showcase.todo.infrastructure.outbox.OutboxEntity;
+import dev.unexist.showcase.todo.infrastructure.outbox.OutboxRepository;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+
+@ApplicationScoped
+public class OutboxRepositoryImpl implements OutboxRepository {
+
+    @Inject
+    EntityManager entityManager;
+
+    @Override
+    public boolean add(OutboxEntity outbox) {
+        this.entityManager.persist(outbox);
+
+        return true;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/TodoRepositoryImpl.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,72 @@
+/**
+ * @package Quarkus-Kubernetes-Showcase
+ *
+ * @file Todo repository
+ * @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.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 javax.inject.Inject;
+import javax.inject.Named;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.transaction.Transactional;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+@ApplicationScoped
+public class TodoRepositoryImpl implements TodoRepository {
+    private static final Logger LOGGER = LoggerFactory.getLogger(TodoRepositoryImpl.class);
+
+    @Inject
+    EntityManager entityManager;
+
+    @Override
+    public boolean add(Todo todo) {
+        this.entityManager.persist(todo);
+
+        return true;
+    }
+
+    @Override
+    public boolean update(Todo todo) {
+        this.entityManager.persist(todo);
+
+        return true;
+    }
+
+    @Override
+    public boolean deleteById(int id) {
+        findById(id).ifPresent(todo -> this.entityManager.remove(todo));
+
+        return true;
+    }
+
+    @Override
+    public List<Todo> getAll() {
+        return this.entityManager.createNamedQuery(Todo.FIND_ALL, Todo.class)
+                .getResultList();
+    }
+
+    @Override
+    public Optional<Todo> findById(int id) {
+        return this.entityManager.createNamedQuery(Todo.FIND_BY_ID, Todo.class)
+                .setParameter("id", id)
+                .getResultList()
+                .stream()
+                .findFirst();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/main/java/dev/unexist/showcase/todo/infrastructure/serializer/DateSerializer.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,29 @@
+/**
+ * @package Quarkus-Kubernetes-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")));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/main/resources/META-INF/resources/index.html	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>quarkus-kubernetes-showcase - 0.1</title>
+    <style>
+        h1, h2, h3, h4, h5, h6 {
+            margin-bottom: 0.5rem;
+            font-weight: 400;
+            line-height: 1.5;
+        }
+
+        h1 {
+            font-size: 2.5rem;
+        }
+
+        h2 {
+            font-size: 2rem
+        }
+
+        h3 {
+            font-size: 1.75rem
+        }
+
+        h4 {
+            font-size: 1.5rem
+        }
+
+        h5 {
+            font-size: 1.25rem
+        }
+
+        h6 {
+            font-size: 1rem
+        }
+
+        .lead {
+            font-weight: 300;
+            font-size: 2rem;
+        }
+
+        .banner {
+            font-size: 2.7rem;
+            margin: 0;
+            padding: 2rem 1rem;
+            background-color: #00A1E2;
+            color: white;
+        }
+
+        body {
+            margin: 0;
+            font-family: -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+        }
+
+        code {
+            font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+            font-size: 87.5%;
+            color: #e83e8c;
+            word-break: break-word;
+        }
+
+        .left-column {
+            padding: .75rem;
+            max-width: 75%;
+            min-width: 55%;
+        }
+
+        .right-column {
+            padding: .75rem;
+            max-width: 25%;
+        }
+
+        .container {
+            display: flex;
+            width: 100%;
+        }
+
+        li {
+            margin: 0.75rem;
+        }
+
+        .right-section {
+            margin-left: 1rem;
+            padding-left: 0.5rem;
+        }
+
+        .right-section h3 {
+            padding-top: 0;
+            font-weight: 200;
+        }
+
+        .right-section ul {
+            border-left: 0.3rem solid #00A1E2;
+            list-style-type: none;
+            padding-left: 0;
+        }
+
+    </style>
+</head>
+<body>
+
+<div class="banner lead">
+    Your new Cloud-Native application is ready!
+</div>
+
+<div class="container">
+    <div class="left-column">
+        <p class="lead"> Congratulations, you have created a new Quarkus application.</p>
+
+        <h2>Why do you see this?</h2>
+
+        <p>This page is served by Quarkus. The source is in
+            <code>src/main/resources/META-INF/resources/index.html</code>.</p>
+
+        <h2>What can I do from here?</h2>
+
+        <p>If not already done, run the application in <em>dev mode</em> using: <code>mvn compile quarkus:dev</code>.
+        </p>
+        <ul>
+            <li>Add REST resources, Servlets, functions and other services in <code>src/main/java</code>.</li>
+            <li>Your static assets are located in <code>src/main/resources/META-INF/resources</code>.</li>
+            <li>Configure your application in <code>src/main/resources/application.properties</code>.
+            </li>
+        </ul>
+
+        <h2>Do you like Quarkus?</h2>
+        <p>Go give it a star on <a href="https://github.com/quarkusio/quarkus">GitHub</a>.</p>
+
+        <h2>How do I get rid of this page?</h2>
+        <p>Just delete the <code>src/main/resources/META-INF/resources/index.html</code> file.</p>
+    </div>
+    <div class="right-column">
+        <div class="right-section">
+            <h3>Application</h3>
+            <ul>
+                <li>GroupId: dev.unexist.showcase</li>
+                <li>ArtifactId: quarkus-kubernetes-showcase</li>
+                <li>Version: 0.1</li>
+                <li>Quarkus Version: 1.13.0.Final</li>
+            </ul>
+        </div>
+        <div class="right-section">
+            <h3>Next steps</h3>
+            <ul>
+                <li><a href="https://quarkus.io/guides/maven-tooling.html" target="_blank">Setup your IDE</a></li>
+                <li><a href="https://quarkus.io/guides/getting-started.html" target="_blank">Getting started</a></li>
+                <li><a href="https://quarkus.io" target="_blank">Quarkus Web Site</a></li>
+            </ul>
+        </div>
+    </div>
+</div>
+
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/main/resources/application.properties	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,36 @@
+# Configuration file
+# key = value
+#quarkus.swagger-ui.always-include=true
+#quarkus.servlet.context-path=/todo
+#quarkus.kubernetes.expose=true
+
+# Disable pass-though of infrastructure health
+#quarkus.datasource.health=false
+#quarkus.reactive-messaging.enabled=false
+#kafka.health.enabled=false
+
+# Kubernetes labels (https://quarkus.io/guides/kubernetes#labels-and-annotations)
+#quarkus.kubernetes.labels.foo=BAR
+
+# 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
+
+# Datasource configuration
+quarkus.datasource.db-kind=postgresql
+quarkus.datasource.username=unexist
+quarkus.datasource.password=password
+quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/showcase
+
+quarkus.datasource.devservices=false
+quarkus.datasource.devservices.image-name=postgres:latest
+
+quarkus.hibernate-orm.database.generation=drop-and-create
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/test/java/dev/unexist/showcase/todo/NativeTodoResourceIT.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,10 @@
+package dev.unexist.showcase.todo;
+
+import dev.unexist.showcase.todo.application.TodoResourceTest;
+import io.quarkus.test.junit.NativeImageTest;
+
+@NativeImageTest
+public class NativeTodoResourceIT extends TodoResourceTest {
+
+    // Execute the same tests but in native mode.
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/todo-service-standalone/src/test/java/dev/unexist/showcase/todo/application/TodoResourceTest.java	Mon May 24 18:50:58 2021 +0200
@@ -0,0 +1,29 @@
+/**
+ * @package Quarkus-Kubernetes-Showcase
+ *
+ * @file Stupid integration test
+ * @copyright 2019 Christoph Kappel <unexist@subforge.org>
+ * @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
--- a/todo-service/pom.xml	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-<?xml version="1.0"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
-         xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>todo-service</artifactId>
-    <version>0.1</version>
-
-    <parent>
-        <groupId>dev.unexist.showcase</groupId>
-        <artifactId>quarkus-outbox-showcase</artifactId>
-        <version>0.1</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <dependencies>
-        <!-- Database -->
-        <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-hibernate-orm</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-jdbc-postgresql</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-devservices-postgresql</artifactId>
-        </dependency>
-    </dependencies>
-</project>
--- a/todo-service/src/main/docker/Dockerfile.fast-jar	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-####
-# 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
--- a/todo-service/src/main/docker/Dockerfile.jvm	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-####
-# 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
--- a/todo-service/src/main/docker/Dockerfile.native	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-####
-# 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
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/adapter/TodoResource.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-/**
- * @package Quarkus-Kubernetes-Showcase
- *
- * @file Todo resource
- * @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.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, TodoBase base) {
-        Response.ResponseBuilder response;
-
-        if (this.todoService.delete(id)) {
-            response = Response.noContent();
-        } else {
-            response = Response.status(Response.Status.NOT_FOUND);
-        }
-
-        return response.build();
-    }
-}
\ No newline at end of file
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/application/RestApplication.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-/**
- * @package Quarkus-Kubernetes-Showcase
- *
- * @file Todo application
- * @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 javax.ws.rs.core.Application;
-
-public class RestApplication extends Application {
-}
\ No newline at end of file
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/DueDate.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/**
- * @package Quarkus-Kubernetes-Showcase
- *
- * @file DueDate class
- * @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.domain.todo;
-
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import dev.unexist.showcase.todo.infrastructure.serializer.DateSerializer;
-
-import javax.persistence.Embeddable;
-import javax.persistence.Embedded;
-import java.time.LocalDate;
-
-@Embeddable
-public class DueDate {
-    @JsonSerialize(using = DateSerializer.class)
-    private LocalDate start;
-
-    @JsonSerialize(using = DateSerializer.class)
-    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;
-    }
-}
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/Todo.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/**
- * @package Quarkus-Kubernetes-Showcase
- *
- * @file Todo class and aggregate root
- * @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.domain.todo;
-
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-
-@Entity
-@Table(name = "Todos")
-@NamedQueries({
-        @NamedQuery(name = Todo.FIND_ALL, query = "SELECT t FROM Todo t"),
-        @NamedQuery(name = Todo.FIND_BY_ID, query = "SELECT t FROM Todo t WHERE t.id = :id")
-})
-public class Todo extends TodoBase {
-    public static final String FIND_ALL = "Todo.findAll";
-    public static final String FIND_BY_ID = "Todo.findById";
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.SEQUENCE)
-    private int id;
-
-    /**
-     * Constructor
-     **/
-
-    public Todo() {
-    }
-
-
-    /**
-     * 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;
-    }
-}
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoBase.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/**
- * @package Quarkus-Kubernetes-Showcase
- *
- * @file Todo base class
- * @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.domain.todo;
-
-import javax.persistence.Column;
-import javax.persistence.Embedded;
-import javax.persistence.MappedSuperclass;
-import javax.validation.constraints.NotBlank;
-
-@MappedSuperclass
-public class TodoBase {
-
-    @NotBlank
-    @Column
-    private String title;
-
-    @NotBlank
-    @Column
-    private String description;
-
-    @Column
-    private Boolean done;
-
-    @Embedded
-    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());
-        }
-    }
-}
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoRepository.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/**
- * @package Quarkus-Kubernetes-Showcase
- *
- * @file Todo repository interface
- * @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.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);
-}
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoService.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/**
- * @package Quarkus-Kubernetes-Showcase
- *
- * @file Todo domain service
- * @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.domain.todo;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import dev.unexist.showcase.todo.infrastructure.outbox.OutboxEvent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.event.Event;
-import javax.inject.Inject;
-import javax.transaction.Transactional;
-import java.util.List;
-import java.util.Optional;
-
-@ApplicationScoped
-public class TodoService {
-    private static final Logger LOGGER = LoggerFactory.getLogger(TodoService.class);
-
-    @Inject
-    TodoRepository todoRepository;
-
-    @Inject
-    Event<OutboxEvent> eventHandler;
-
-    /**
-     * 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}
-     **/
-
-    @Transactional
-    public boolean create(TodoBase base) {
-        boolean retval = true;
-        Todo todo = new Todo(base);
-
-        this.todoRepository.add(todo);
-
-        OutboxEvent event = new OutboxEvent();
-
-        event.setAggregateId(todo.getId());
-        event.setEventType("todo_created");
-
-        try {
-            ObjectMapper mapper = new ObjectMapper();
-
-            event.setPayload(mapper.writeValueAsString(todo));
-        } catch (JsonProcessingException jpe) {
-            LOGGER.warn("Json error: {}", jpe.getMessage(), jpe);
-
-            retval = false;
-        }
-
-        this.eventHandler.fire(event);
-
-        return retval;
-    }
-
-    /**
-     * 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);
-    }
-}
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxEntity.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/**
- * @package Quarkus-Outbox-Showcase
- *
- * @file Outbox entity
- * @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.infrastructure.outbox;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import java.util.Date;
-import java.util.UUID;
-
-import static java.util.Objects.requireNonNull;
-
-@Entity
-@Table(name = "OUTBOX")
-public class OutboxEntity {
-
-    @Id
-    @Column(name = "uuid")
-    private UUID uuid;
-
-    @Column(name = "aggregateId")
-    private Integer aggregateId;
-
-    @Column(name = "eventType")
-    private String eventType;
-
-    @Column(name = "payload")
-    private String payload;
-
-    @Column(name = "createdOn")
-    private Date createdOn;
-
-    protected OutboxEntity() {
-    }
-
-    public OutboxEntity(UUID uuid, Integer aggregateId, String eventType, String payload) {
-        this.uuid = requireNonNull(uuid);
-        this.aggregateId = requireNonNull(aggregateId);
-        this.eventType = requireNonNull(eventType);
-        this.payload = requireNonNull(payload);
-    }
-}
\ No newline at end of file
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxEvent.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/**
- * @package Quarkus-Outbox-Showcase
- *
- * @file Outbox event
- * @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.infrastructure.outbox;
-
-public class OutboxEvent {
-    private Integer aggregateId;
-    private String eventType;
-    private String payload;
-
-    public Integer getAggregateId() {
-        return aggregateId;
-    }
-
-    public void setAggregateId(Integer aggregateId) {
-        this.aggregateId = aggregateId;
-    }
-
-    public String getEventType() {
-        return eventType;
-    }
-
-    public void setEventType(String eventType) {
-        this.eventType = eventType;
-    }
-
-    public String getPayload() {
-        return payload;
-    }
-
-    public void setPayload(String payload) {
-        this.payload = payload;
-    }
-}
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxRepository.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/**
- * @package Quarkus-Outbox-Showcase
- *
- * @file Outbox repository interface
- * @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.infrastructure.outbox;
-
-public interface OutboxRepository {
-
-    /**
-     * Add {@link OutboxEntity} entry to list
-     *
-     * @param entity
-     *          {@link OutboxEntity} entry to add
-     * @return
-     *          Either {@code true} on success; otherwise {@code false}
-     **/
-
-    boolean add(OutboxEntity entity);
-}
\ No newline at end of file
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/outbox/OutboxService.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/**
- * @package Quarkus-Outbox-Showcase
- *
- * @file Outbox domain service
- * @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.infrastructure.outbox;
-
-import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.event.Observes;
-import javax.enterprise.event.TransactionPhase;
-import javax.inject.Inject;
-import javax.transaction.Transactional;
-import java.util.UUID;
-
-import static javax.transaction.Transactional.TxType.REQUIRES_NEW;
-
-@ApplicationScoped
-public class OutboxService {
-
-    @Inject
-    OutboxRepository outboxRepository;
-
-    @Transactional(REQUIRES_NEW)
-    public void handleOutboxEvent(@Observes(during = TransactionPhase.AFTER_SUCCESS) OutboxEvent event) {
-        UUID uuid = UUID.randomUUID();
-
-        OutboxEntity entity = new OutboxEntity(uuid,
-            event.getAggregateId(),
-            event.getEventType(),
-            event.getPayload());
-
-        outboxRepository.add(entity);
-    }
-}
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/OutboxRepositoryImpl.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/**
- * @package Quarkus-Kubernetes-Showcase
- *
- * @file Outbox repository
- * @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.infrastructure.persistence;
-
-import dev.unexist.showcase.todo.infrastructure.outbox.OutboxEntity;
-import dev.unexist.showcase.todo.infrastructure.outbox.OutboxRepository;
-
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Inject;
-import javax.persistence.EntityManager;
-
-@ApplicationScoped
-public class OutboxRepositoryImpl implements OutboxRepository {
-
-    @Inject
-    EntityManager entityManager;
-
-    @Override
-    public boolean add(OutboxEntity outbox) {
-        this.entityManager.persist(outbox);
-
-        return true;
-    }
-}
\ No newline at end of file
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/TodoRepositoryImpl.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/**
- * @package Quarkus-Kubernetes-Showcase
- *
- * @file Todo repository
- * @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.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 javax.inject.Inject;
-import javax.inject.Named;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.transaction.Transactional;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-@ApplicationScoped
-public class TodoRepositoryImpl implements TodoRepository {
-    private static final Logger LOGGER = LoggerFactory.getLogger(TodoRepositoryImpl.class);
-
-    @Inject
-    EntityManager entityManager;
-
-    @Override
-    public boolean add(Todo todo) {
-        this.entityManager.persist(todo);
-
-        return true;
-    }
-
-    @Override
-    public boolean update(Todo todo) {
-        this.entityManager.persist(todo);
-
-        return true;
-    }
-
-    @Override
-    public boolean deleteById(int id) {
-        findById(id).ifPresent(todo -> this.entityManager.remove(todo));
-
-        return true;
-    }
-
-    @Override
-    public List<Todo> getAll() {
-        return this.entityManager.createNamedQuery(Todo.FIND_ALL, Todo.class)
-                .getResultList();
-    }
-
-    @Override
-    public Optional<Todo> findById(int id) {
-        return this.entityManager.createNamedQuery(Todo.FIND_BY_ID, Todo.class)
-                .setParameter("id", id)
-                .getResultList()
-                .stream()
-                .findFirst();
-    }
-}
\ No newline at end of file
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/serializer/DateSerializer.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/**
- * @package Quarkus-Kubernetes-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")));
-    }
-}
\ No newline at end of file
--- a/todo-service/src/main/resources/META-INF/resources/index.html	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <title>quarkus-kubernetes-showcase - 0.1</title>
-    <style>
-        h1, h2, h3, h4, h5, h6 {
-            margin-bottom: 0.5rem;
-            font-weight: 400;
-            line-height: 1.5;
-        }
-
-        h1 {
-            font-size: 2.5rem;
-        }
-
-        h2 {
-            font-size: 2rem
-        }
-
-        h3 {
-            font-size: 1.75rem
-        }
-
-        h4 {
-            font-size: 1.5rem
-        }
-
-        h5 {
-            font-size: 1.25rem
-        }
-
-        h6 {
-            font-size: 1rem
-        }
-
-        .lead {
-            font-weight: 300;
-            font-size: 2rem;
-        }
-
-        .banner {
-            font-size: 2.7rem;
-            margin: 0;
-            padding: 2rem 1rem;
-            background-color: #00A1E2;
-            color: white;
-        }
-
-        body {
-            margin: 0;
-            font-family: -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
-        }
-
-        code {
-            font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
-            font-size: 87.5%;
-            color: #e83e8c;
-            word-break: break-word;
-        }
-
-        .left-column {
-            padding: .75rem;
-            max-width: 75%;
-            min-width: 55%;
-        }
-
-        .right-column {
-            padding: .75rem;
-            max-width: 25%;
-        }
-
-        .container {
-            display: flex;
-            width: 100%;
-        }
-
-        li {
-            margin: 0.75rem;
-        }
-
-        .right-section {
-            margin-left: 1rem;
-            padding-left: 0.5rem;
-        }
-
-        .right-section h3 {
-            padding-top: 0;
-            font-weight: 200;
-        }
-
-        .right-section ul {
-            border-left: 0.3rem solid #00A1E2;
-            list-style-type: none;
-            padding-left: 0;
-        }
-
-    </style>
-</head>
-<body>
-
-<div class="banner lead">
-    Your new Cloud-Native application is ready!
-</div>
-
-<div class="container">
-    <div class="left-column">
-        <p class="lead"> Congratulations, you have created a new Quarkus application.</p>
-
-        <h2>Why do you see this?</h2>
-
-        <p>This page is served by Quarkus. The source is in
-            <code>src/main/resources/META-INF/resources/index.html</code>.</p>
-
-        <h2>What can I do from here?</h2>
-
-        <p>If not already done, run the application in <em>dev mode</em> using: <code>mvn compile quarkus:dev</code>.
-        </p>
-        <ul>
-            <li>Add REST resources, Servlets, functions and other services in <code>src/main/java</code>.</li>
-            <li>Your static assets are located in <code>src/main/resources/META-INF/resources</code>.</li>
-            <li>Configure your application in <code>src/main/resources/application.properties</code>.
-            </li>
-        </ul>
-
-        <h2>Do you like Quarkus?</h2>
-        <p>Go give it a star on <a href="https://github.com/quarkusio/quarkus">GitHub</a>.</p>
-
-        <h2>How do I get rid of this page?</h2>
-        <p>Just delete the <code>src/main/resources/META-INF/resources/index.html</code> file.</p>
-    </div>
-    <div class="right-column">
-        <div class="right-section">
-            <h3>Application</h3>
-            <ul>
-                <li>GroupId: dev.unexist.showcase</li>
-                <li>ArtifactId: quarkus-kubernetes-showcase</li>
-                <li>Version: 0.1</li>
-                <li>Quarkus Version: 1.13.0.Final</li>
-            </ul>
-        </div>
-        <div class="right-section">
-            <h3>Next steps</h3>
-            <ul>
-                <li><a href="https://quarkus.io/guides/maven-tooling.html" target="_blank">Setup your IDE</a></li>
-                <li><a href="https://quarkus.io/guides/getting-started.html" target="_blank">Getting started</a></li>
-                <li><a href="https://quarkus.io" target="_blank">Quarkus Web Site</a></li>
-            </ul>
-        </div>
-    </div>
-</div>
-
-
-</body>
-</html>
\ No newline at end of file
--- a/todo-service/src/main/resources/application.properties	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-# Configuration file
-# key = value
-#quarkus.swagger-ui.always-include=true
-#quarkus.servlet.context-path=/todo
-#quarkus.kubernetes.expose=true
-
-# Disable pass-though of infrastructure health
-#quarkus.datasource.health=false
-#quarkus.reactive-messaging.enabled=false
-#kafka.health.enabled=false
-
-# Kubernetes labels (https://quarkus.io/guides/kubernetes#labels-and-annotations)
-#quarkus.kubernetes.labels.foo=BAR
-
-# 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
-
-# Datasource configuration
-quarkus.datasource.db-kind=postgresql
-quarkus.datasource.username=unexist
-quarkus.datasource.password=password
-quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/showcase
-
-quarkus.datasource.devservices=false
-quarkus.datasource.devservices.image-name=postgres:latest
-
-quarkus.hibernate-orm.database.generation=drop-and-create
\ No newline at end of file
--- a/todo-service/src/test/java/dev/unexist/showcase/todo/NativeTodoResourceIT.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-package dev.unexist.showcase.todo;
-
-import dev.unexist.showcase.todo.application.TodoResourceTest;
-import io.quarkus.test.junit.NativeImageTest;
-
-@NativeImageTest
-public class NativeTodoResourceIT extends TodoResourceTest {
-
-    // Execute the same tests but in native mode.
-}
\ No newline at end of file
--- a/todo-service/src/test/java/dev/unexist/showcase/todo/application/TodoResourceTest.java	Fri May 07 15:11:08 2021 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/**
- * @package Quarkus-Kubernetes-Showcase
- *
- * @file Stupid integration test
- * @copyright 2019 Christoph Kappel <unexist@subforge.org>
- * @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