Changeset 21:f5c622b78543
Moved service
author | unexist |
---|---|
date | Mon, 16 Aug 2021 17:08:42 +0200 |
parents | 23a3e84989d6 |
children | 1fe13cd0cd99 |
files | services/todo-service/pom.xml services/todo-service/src/main/java/dev/unexist/showcase/todo/adapter/TodoResource.java services/todo-service/src/main/java/dev/unexist/showcase/todo/adapter/TodoSink.java services/todo-service/src/main/java/dev/unexist/showcase/todo/application/.gitkeep services/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/DueDate.java services/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/Todo.java services/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoBase.java services/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoRepository.java services/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoService.java services/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/ListTodoRepository.java services/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/serializer/DateSerializer.java services/todo-service/src/main/resources/META-INF/resources/index.html services/todo-service/src/main/resources/application.properties services/todo-service/src/test/java/dev/unexist/showcase/todo/application/TodoResourceTest.java todo-service/pom.xml todo-service/src/main/java/dev/unexist/showcase/todo/adapter/TodoResource.java todo-service/src/main/java/dev/unexist/showcase/todo/adapter/TodoSink.java todo-service/src/main/java/dev/unexist/showcase/todo/application/.gitkeep 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/persistence/ListTodoRepository.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/application/TodoResourceTest.java |
diffstat | 26 files changed, 1130 insertions(+), 1130 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/todo-service/pom.xml Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,51 @@ +<?xml version="1.0"?> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + 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"> + <modelVersion>4.0.0</modelVersion> + <artifactId>todo-service</artifactId> + <version>0.1</version> + + <parent> + <groupId>dev.unexist.showcase</groupId> + <artifactId>showcase-eventbus-quarkus</artifactId> + <version>0.1</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <properties> + <smallrye-reactive.version>3.8.0</smallrye-reactive.version> + <smallrye-reactive-messaging-vertx-eventbus.version>3.1.0</smallrye-reactive-messaging-vertx-eventbus.version> + </properties> + + <dependencies> + <!-- Quarkus --> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-container-image-jib</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-vertx</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-smallrye-reactive-messaging-kafka</artifactId> + </dependency> + + <!-- Smallrye --> + <dependency> + <groupId>io.smallrye.reactive</groupId> + <artifactId>smallrye-reactive-messaging-vertx-eventbus</artifactId> + <version>${smallrye-reactive-messaging-vertx-eventbus.version}</version> + </dependency> + + <!-- Testing --> + <dependency> + <groupId>io.smallrye.reactive</groupId> + <artifactId>smallrye-reactive-messaging-in-memory</artifactId> + <version>${smallrye-reactive.version}</version> + <scope>test</scope> + </dependency> + </dependencies> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/todo-service/src/main/java/dev/unexist/showcase/todo/adapter/TodoResource.java Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,156 @@ +/** + * @package Showcase-Eventbus-Quarkus + * + * @file Todo resource + * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> + * @version $Id$ + * + * This program can be distributed under the terms of the Apache License v2.0. + * 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 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.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import java.net.URI; +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") + @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 uriInfo) { + Response.ResponseBuilder response; + + if (this.todoService.create(base)) { + URI uri = uriInfo.getAbsolutePathBuilder().build(); + + response = Response.created(uri); + } else { + response = Response.status(Response.Status.NOT_ACCEPTABLE); + } + + return response.build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Operation(summary = "Get all todos") + @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") + @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 getAll(@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") + @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") + 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/services/todo-service/src/main/java/dev/unexist/showcase/todo/adapter/TodoSink.java Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,78 @@ +/** + * @package Showcase-Eventbus-Quarkus + * + * @file Todo sink + * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> + * @version $Id$ + * + * This program can be distributed under the terms of the Apache License v2.0. + * See the file LICENSE for details. + **/ + +package dev.unexist.showcase.todo.adapter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.quarkus.vertx.ConsumeEvent; +import io.vertx.mutiny.core.eventbus.EventBus; +import org.apache.commons.lang3.StringUtils; +import org.eclipse.microprofile.reactive.messaging.Channel; +import org.eclipse.microprofile.reactive.messaging.Emitter; +import org.eclipse.microprofile.reactive.messaging.Incoming; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; + +@ApplicationScoped +public class TodoSink { + private static final Logger LOGGER = LoggerFactory.getLogger(TodoSink.class); + + static final ObjectMapper MAPPER = new ObjectMapper(); + + @Inject + EventBus bus; + + @Channel("todo_out") + Emitter<String> emitter; + + @Incoming("todo_in") + public void consumeAll(String message) { + String typeName = StringUtils.EMPTY; + + LOGGER.info("consumeAll: {}", message); + + try { + JsonNode json = MAPPER.readTree(message); + + typeName = json.get("type").asText(); + } catch (JsonProcessingException e) { + LOGGER.error("Error reading JSON", e); + } + + this.bus.send(typeName, message); + } + + @ConsumeEvent("todo_in1") + public void consumeTodoIn1(String message) { + LOGGER.info("consumeTest1: {}", message); + + this.emitter.send(message); + } + + @ConsumeEvent("todo_in2") + public void consumeTodoIn2(String message) { + LOGGER.info("consumeTest2: {}", message); + + this.emitter.send(message); + } + + @Incoming("todo_in3") + public void consumeTodoIn3(String message) { + LOGGER.info("consumeTest3: {}", message); + + this.emitter.send(message); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/DueDate.java Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,65 @@ +/** + * @package Showcase-Eventbus-Quarkus + * + * @file DueDate class + * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> + * @version $Id$ + * + * This program can be distributed under the terms of the Apache License v2.0. + * 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 java.time.LocalDate; + +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/services/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/Todo.java Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,66 @@ +/** + * @package Showcase-Eventbus-Quarkus + * + * @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 Apache License v2.0. + * See the file LICENSE for details. + **/ + +package dev.unexist.showcase.todo.domain.todo; + +public class Todo extends TodoBase { + 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/services/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoBase.java Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,117 @@ +/** + * @package Showcase-Eventbus-Quarkus + * + * @file Todo base class + * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> + * @version $Id$ + * + * This program can be distributed under the terms of the Apache License v2.0. + * See the file LICENSE for details. + **/ + +package dev.unexist.showcase.todo.domain.todo; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.Objects; + +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) { + Objects.requireNonNull(dueDate, "DueDate cannot be null"); + + 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/services/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoRepository.java Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,66 @@ +/** + * @package Showcase-Eventbus-Quarkus + * + * @file Todo repository interface + * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> + * @version $Id$ + * + * This program can be distributed under the terms of the Apache License v2.0. + * 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/services/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/TodoService.java Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,94 @@ +/** + * @package Showcase-Eventbus-Quarkus + * + * @file Todo service and domain service + * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> + * @version $Id$ + * + * This program can be distributed under the terms of the Apache License v2.0. + * 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/services/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/ListTodoRepository.java Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,87 @@ +/** + * @package Showcase-Eventbus-Quarkus + * + * @file Todo repository + * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> + * @version $Id$ + * + * This program can be distributed under the terms of the Apache License v2.0. + * 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("deleteById: 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(); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/serializer/DateSerializer.java Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,39 @@ +/** + * @package Showcase-Eventbus-Quarkus + * + * @file Todo serializer + * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> + * @version $Id$ + * + * This program can be distributed under the terms of the Apache License v2.0. + * 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> { + public static final String PATTERN = "yyyy-MM-dd"; + + /** + * Serialize {@link LocalDate} to format + * + * @param value Value to convert + * @param gen A {@link JsonGenerator} + * @param serializers A {@link SerializerProvider} + * @throws IOException + **/ + + @Override + public void serialize(LocalDate value, JsonGenerator gen, + SerializerProvider serializers) throws IOException { + gen.writeString(value.format(DateTimeFormatter.ofPattern(PATTERN))); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/todo-service/src/main/resources/META-INF/resources/index.html Mon Aug 16 17:08:42 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> + · + <a href="https://github.com/unexist">unexist @ GitHub</a> + · + <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/services/todo-service/src/main/resources/application.properties Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,49 @@ +# 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"=Apache License v2.0 +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=Apache License v2.0 +mp.openapi.extensions.smallrye.info.license.url=https://www.apache.org/licenses/LICENSE-2.0 + +# Messaging +mp.messaging.incoming.todo_in.topic=todo_in +mp.messaging.incoming.todo_in.connector=smallrye-kafka +%test.mp.messaging.incoming.todo_in.connector=smallrye-in-memory +mp.messaging.incoming.todo_in.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer +#mp.messaging.incoming.todo_in.bootstrap.servers=localhost:9092 + +mp.messaging.outgoing.todo_out.topic=todo_out +mp.messaging.outgoing.todo_out.connector=smallrye-kafka +%test.mp.messaging.outgoing.todo_out.connector=smallrye-in-memory +mp.messaging.outgoing.todo_out.value.serializer=org.apache.kafka.common.serialization.StringSerializer +#mp.messaging.outgoing.todo_out.bootstrap.servers=localhost:9092 + +mp.messaging.incoming.todo_in3.connector=smallrye-vertx-eventbus +mp.messaging.incoming.todo_in3.address=todo_in3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/services/todo-service/src/test/java/dev/unexist/showcase/todo/application/TodoResourceTest.java Mon Aug 16 17:08:42 2021 +0200 @@ -0,0 +1,29 @@ +/** + * @package Showcase-Eventbus-Quarkus + * + * @file Stupid integration test + * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> + * @version $Id$ + * + * This program can be distributed under the terms of the Apache License v2.0. + * See the file LICENSE for details. + **/ + +package dev.unexist.showcase.todo.application; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import static io.restassured.RestAssured.given; + +@Disabled +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 Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -<?xml version="1.0"?> -<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - 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"> - <modelVersion>4.0.0</modelVersion> - <artifactId>todo-service</artifactId> - <version>0.1</version> - - <parent> - <groupId>dev.unexist.showcase</groupId> - <artifactId>showcase-eventbus-quarkus</artifactId> - <version>0.1</version> - <relativePath>../pom.xml</relativePath> - </parent> - - <properties> - <smallrye-reactive.version>3.8.0</smallrye-reactive.version> - <smallrye-reactive-messaging-vertx-eventbus.version>3.1.0</smallrye-reactive-messaging-vertx-eventbus.version> - </properties> - - <dependencies> - <!-- Quarkus --> - <dependency> - <groupId>io.quarkus</groupId> - <artifactId>quarkus-container-image-jib</artifactId> - </dependency> - <dependency> - <groupId>io.quarkus</groupId> - <artifactId>quarkus-vertx</artifactId> - </dependency> - <dependency> - <groupId>io.quarkus</groupId> - <artifactId>quarkus-smallrye-reactive-messaging-kafka</artifactId> - </dependency> - - <!-- Smallrye --> - <dependency> - <groupId>io.smallrye.reactive</groupId> - <artifactId>smallrye-reactive-messaging-vertx-eventbus</artifactId> - <version>${smallrye-reactive-messaging-vertx-eventbus.version}</version> - </dependency> - - <!-- Testing --> - <dependency> - <groupId>io.smallrye.reactive</groupId> - <artifactId>smallrye-reactive-messaging-in-memory</artifactId> - <version>${smallrye-reactive.version}</version> - <scope>test</scope> - </dependency> - </dependencies> -</project>
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/adapter/TodoResource.java Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -/** - * @package Showcase-Eventbus-Quarkus - * - * @file Todo resource - * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> - * @version $Id$ - * - * This program can be distributed under the terms of the Apache License v2.0. - * 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 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.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.net.URI; -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") - @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 uriInfo) { - Response.ResponseBuilder response; - - if (this.todoService.create(base)) { - URI uri = uriInfo.getAbsolutePathBuilder().build(); - - response = Response.created(uri); - } else { - response = Response.status(Response.Status.NOT_ACCEPTABLE); - } - - return response.build(); - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - @Operation(summary = "Get all todos") - @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") - @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 getAll(@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") - @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") - 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(); - } -}
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/adapter/TodoSink.java Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/** - * @package Showcase-Eventbus-Quarkus - * - * @file Todo sink - * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> - * @version $Id$ - * - * This program can be distributed under the terms of the Apache License v2.0. - * See the file LICENSE for details. - **/ - -package dev.unexist.showcase.todo.adapter; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.quarkus.vertx.ConsumeEvent; -import io.vertx.mutiny.core.eventbus.EventBus; -import org.apache.commons.lang3.StringUtils; -import org.eclipse.microprofile.reactive.messaging.Channel; -import org.eclipse.microprofile.reactive.messaging.Emitter; -import org.eclipse.microprofile.reactive.messaging.Incoming; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; - -@ApplicationScoped -public class TodoSink { - private static final Logger LOGGER = LoggerFactory.getLogger(TodoSink.class); - - static final ObjectMapper MAPPER = new ObjectMapper(); - - @Inject - EventBus bus; - - @Channel("todo_out") - Emitter<String> emitter; - - @Incoming("todo_in") - public void consumeAll(String message) { - String typeName = StringUtils.EMPTY; - - LOGGER.info("consumeAll: {}", message); - - try { - JsonNode json = MAPPER.readTree(message); - - typeName = json.get("type").asText(); - } catch (JsonProcessingException e) { - LOGGER.error("Error reading JSON", e); - } - - this.bus.send(typeName, message); - } - - @ConsumeEvent("todo_in1") - public void consumeTodoIn1(String message) { - LOGGER.info("consumeTest1: {}", message); - - this.emitter.send(message); - } - - @ConsumeEvent("todo_in2") - public void consumeTodoIn2(String message) { - LOGGER.info("consumeTest2: {}", message); - - this.emitter.send(message); - } - - @Incoming("todo_in3") - public void consumeTodoIn3(String message) { - LOGGER.info("consumeTest3: {}", message); - - this.emitter.send(message); - } -} \ No newline at end of file
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/domain/todo/DueDate.java Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/** - * @package Showcase-Eventbus-Quarkus - * - * @file DueDate class - * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> - * @version $Id$ - * - * This program can be distributed under the terms of the Apache License v2.0. - * 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 java.time.LocalDate; - -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 Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/** - * @package Showcase-Eventbus-Quarkus - * - * @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 Apache License v2.0. - * See the file LICENSE for details. - **/ - -package dev.unexist.showcase.todo.domain.todo; - -public class Todo extends TodoBase { - 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 Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/** - * @package Showcase-Eventbus-Quarkus - * - * @file Todo base class - * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> - * @version $Id$ - * - * This program can be distributed under the terms of the Apache License v2.0. - * See the file LICENSE for details. - **/ - -package dev.unexist.showcase.todo.domain.todo; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.util.Objects; - -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) { - Objects.requireNonNull(dueDate, "DueDate cannot be null"); - - 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 Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/** - * @package Showcase-Eventbus-Quarkus - * - * @file Todo repository interface - * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> - * @version $Id$ - * - * This program can be distributed under the terms of the Apache License v2.0. - * 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 Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/** - * @package Showcase-Eventbus-Quarkus - * - * @file Todo service and domain service - * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> - * @version $Id$ - * - * This program can be distributed under the terms of the Apache License v2.0. - * 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); - } -}
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/persistence/ListTodoRepository.java Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/** - * @package Showcase-Eventbus-Quarkus - * - * @file Todo repository - * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> - * @version $Id$ - * - * This program can be distributed under the terms of the Apache License v2.0. - * 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("deleteById: 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(); - } -} \ No newline at end of file
--- a/todo-service/src/main/java/dev/unexist/showcase/todo/infrastructure/serializer/DateSerializer.java Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/** - * @package Showcase-Eventbus-Quarkus - * - * @file Todo serializer - * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> - * @version $Id$ - * - * This program can be distributed under the terms of the Apache License v2.0. - * 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> { - public static final String PATTERN = "yyyy-MM-dd"; - - /** - * Serialize {@link LocalDate} to format - * - * @param value Value to convert - * @param gen A {@link JsonGenerator} - * @param serializers A {@link SerializerProvider} - * @throws IOException - **/ - - @Override - public void serialize(LocalDate value, JsonGenerator gen, - SerializerProvider serializers) throws IOException { - gen.writeString(value.format(DateTimeFormatter.ofPattern(PATTERN))); - } -}
--- a/todo-service/src/main/resources/META-INF/resources/index.html Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,233 +0,0 @@ -<!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> - · - <a href="https://github.com/unexist">unexist @ GitHub</a> - · - <a href="https://twitter.com/chkappel">unexist @ Twitter</a> - </footer> -</div> -</body> -</html> \ No newline at end of file
--- a/todo-service/src/main/resources/application.properties Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -# 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=Apache License v2.0 -mp.openapi.extensions.smallrye.info.license.url=https://www.apache.org/licenses/LICENSE-2.0 - -# Messaging -mp.messaging.incoming.todo_in.connector=smallrye-kafka -%test.mp.messaging.incoming.todo_in.connector=smallrye-in-memory -mp.messaging.incoming.todo_in.topic=todo_in -mp.messaging.incoming.todo_in.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer -#mp.messaging.incoming.todo_in.bootstrap.servers=localhost:9092 - -mp.messaging.outgoing.todo_out.connector=smallrye-kafka -%test.mp.messaging.outgoing.todo_out.connector=smallrye-in-memory -mp.messaging.outgoing.todo_out.topic=todo_out -mp.messaging.outgoing.todo_out.value.serializer=org.apache.kafka.common.serialization.StringSerializer -#mp.messaging.outgoing.todo_out.bootstrap.servers=localhost:9092 - -mp.messaging.incoming.todo_in3.connector=smallrye-vertx-eventbus -mp.messaging.incoming.todo_in3.address=todo_in3
--- a/todo-service/src/test/java/dev/unexist/showcase/todo/application/TodoResourceTest.java Mon Aug 16 17:05:43 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -/** - * @package Showcase-Eventbus-Quarkus - * - * @file Stupid integration test - * @copyright 2020-2021 Christoph Kappel <christoph@unexist.dev> - * @version $Id$ - * - * This program can be distributed under the terms of the Apache License v2.0. - * See the file LICENSE for details. - **/ - -package dev.unexist.showcase.todo.application; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import static io.restassured.RestAssured.given; - -@Disabled -public class TodoResourceTest { - - @Test - public void testTodoEndpoint() { - given() - .when().get("/todo") - .then() - .statusCode(204); - } -} \ No newline at end of file