├── .gitignore
├── blade
├── src
│ └── main
│ │ ├── resources
│ │ └── application.properties
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── microframeworks
│ │ └── blade
│ │ ├── JacksonJsonSupport.java
│ │ ├── BladeApplication.java
│ │ └── TodoRestController.java
├── Dockerfile
└── pom.xml
├── quarkus
├── src
│ └── main
│ │ ├── resources
│ │ └── application.properties
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── microframeworks
│ │ └── quarkus
│ │ ├── QuarkusApplication.java
│ │ ├── HelloWorldController.java
│ │ └── TodoController.java
├── Dockerfile
└── pom.xml
├── helidon-se
├── src
│ └── main
│ │ ├── resources
│ │ └── application.yaml
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── demo
│ │ └── microframeworks
│ │ └── helidon
│ │ └── se
│ │ ├── HelloWorldRestController.java
│ │ ├── HelidonApplication.java
│ │ └── TodoRestController.java
├── Dockerfile
└── pom.xml
├── helidon-mp
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ ├── microprofile-config.properties
│ │ │ └── beans.xml
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── microframeworks
│ │ └── helidon
│ │ └── mp
│ │ ├── HelidonMpApplication.java
│ │ ├── HelloWorldApplication.java
│ │ ├── HelloWorldController.java
│ │ ├── CorsFilter.java
│ │ ├── TodoApplication.java
│ │ └── TodoController.java
├── Dockerfile
└── pom.xml
├── micronaut
├── src
│ └── main
│ │ ├── resources
│ │ └── application.yaml
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── demo
│ │ └── microframeworks
│ │ └── micronaut
│ │ ├── MicronautApplication.java
│ │ ├── TodoFactory.java
│ │ ├── HelloWorldController.java
│ │ └── TodoController.java
├── Dockerfile
└── pom.xml
├── README.md
├── ktor
├── src
│ └── main
│ │ ├── resources
│ │ └── application.conf
│ │ └── kotlin
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── demo
│ │ └── microframeworks
│ │ └── ktor
│ │ ├── KtorApplication.kt
│ │ └── TodoBackend.kt
├── Dockerfile
└── pom.xml
├── kumuluzee
├── Dockerfile
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── beans.xml
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── demo
│ │ └── microframeworks
│ │ └── kumuluzee
│ │ ├── KumuluzEEApplication.java
│ │ ├── TodoBackendFactory.java
│ │ ├── HelloWorldController.java
│ │ └── TodoController.java
└── pom.xml
├── spark
├── Dockerfile
├── src
│ └── main
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── microframeworks
│ │ └── spark
│ │ ├── JacksonResponseTransformer.java
│ │ ├── SparkApplication.java
│ │ └── TodoRestController.java
└── pom.xml
├── armeria
├── Dockerfile
├── src
│ └── main
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── microframeworks
│ │ └── armeria
│ │ ├── ArmeriaApplication.java
│ │ └── TodoRestController.java
└── pom.xml
├── javalin
├── Dockerfile
├── src
│ └── main
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── microframeworks
│ │ └── javalin
│ │ ├── JavalinApplication.java
│ │ └── TodoRestController.java
└── pom.xml
├── jooby
├── Dockerfile
├── src
│ └── main
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── demo
│ │ └── microframeworks
│ │ └── jooby
│ │ ├── JoobyApplication.java
│ │ └── TodoRestController.java
└── pom.xml
├── http4k
├── Dockerfile
├── src
│ └── main
│ │ └── kotlin
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── demo
│ │ └── microframeworks
│ │ └── http4k
│ │ ├── Http4kApplication.kt
│ │ └── TodoRestController.kt
└── pom.xml
├── minijax
├── Dockerfile
├── src
│ └── main
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── microframeworks
│ │ └── minijax
│ │ ├── HelloWorldController.java
│ │ ├── MinijaxApplication.java
│ │ └── TodoController.java
└── pom.xml
├── pippo
├── Dockerfile
├── src
│ └── main
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── demo
│ │ └── microframeworks
│ │ └── pippo
│ │ ├── PippoApplication.java
│ │ └── TodoRestController.java
└── pom.xml
├── ratpack
├── Dockerfile
├── pom.xml
└── src
│ └── main
│ └── java
│ └── nl
│ └── jaapcoomans
│ └── demo
│ └── microframeworks
│ └── ratpack
│ ├── RatpackApplication.java
│ └── TodoRestController.java
├── dropwizard
├── Dockerfile
├── src
│ └── main
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── microframeworks
│ │ └── dropwizard
│ │ ├── HelloWorldController.java
│ │ ├── DropWizardApplication.java
│ │ └── TodoRestController.java
└── pom.xml
├── todo-backend
├── src
│ └── main
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── demo
│ │ └── microframeworks
│ │ └── todo
│ │ ├── domain
│ │ ├── TodoRepository.java
│ │ ├── PartialTodo.java
│ │ ├── TodoService.java
│ │ └── Todo.java
│ │ ├── api
│ │ ├── CreateTodoCommand.java
│ │ └── TodoDTO.java
│ │ └── peristsence
│ │ └── InMemoryTodoRepository.java
└── pom.xml
├── todo-backend-test
├── src
│ └── test
│ │ └── java
│ │ └── nl
│ │ └── jaapcoomans
│ │ └── demo
│ │ └── microframeworks
│ │ └── todo
│ │ └── test
│ │ ├── JavalinTodoTest.java
│ │ ├── Http4kTodoBackendTest.java
│ │ ├── KtorTodoBackendTest.java
│ │ ├── BladeTodoBackendTest.java
│ │ ├── JoobyTodoBackendTest.java
│ │ ├── PippoTodoBackendTest.java
│ │ ├── SparkTodoBackendTest.java
│ │ ├── ArmeriaTodoBackendTest.java
│ │ ├── MinijaxTodoBackendTest.java
│ │ ├── RatpackTodoBackendTest.java
│ │ ├── HelidonMpTodoBackendTest.java
│ │ ├── HelidonSeTodoBackendTest.java
│ │ ├── KumuluzEeTodoBackendTest.java
│ │ ├── QuarkusTodoBackendTest.java
│ │ ├── DropWizardTodoBackendTest.java
│ │ ├── MicronautTodoBackendTest.java
│ │ └── BaseTodoBackendTest.java
└── pom.xml
├── LICENSE
├── docker-compose.yaml
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | *.iml
3 | target
4 |
--------------------------------------------------------------------------------
/blade/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.port=8080
2 |
--------------------------------------------------------------------------------
/quarkus/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | quarkus.http.cors=true
--------------------------------------------------------------------------------
/helidon-se/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 | host: 0.0.0.0
4 |
--------------------------------------------------------------------------------
/helidon-mp/src/main/resources/META-INF/microprofile-config.properties:
--------------------------------------------------------------------------------
1 | server.port=8080
2 | server.host=0.0.0.0
3 |
--------------------------------------------------------------------------------
/micronaut/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | micronaut:
4 | server:
5 | cors:
6 | enabled: true
7 |
8 | todos:
9 | baseUrl: http://localhost:8080/todos
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 15 Microframeworks for the JVM
2 | This repo contains 15 different implementations, using 15 different microframeworks, of TODO backend and a simple
3 | Hello World endpoint.
4 |
5 |
--------------------------------------------------------------------------------
/ktor/src/main/resources/application.conf:
--------------------------------------------------------------------------------
1 | ktor {
2 | deployment {
3 | port = 8080
4 | }
5 |
6 | application {
7 | modules = [ nl.jaapcoomans.demo.microframeworks.ktor.KtorApplicationKt.module ]
8 | }
9 | }
--------------------------------------------------------------------------------
/blade/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.microframeworks.blade.BladeApplication
--------------------------------------------------------------------------------
/kumuluzee/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk15:jre-15.0.2_7-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java --illegal-access=warn -cp "/opt/application/application.jar:/opt/application/libs/*" com.kumuluz.ee.EeApplication
--------------------------------------------------------------------------------
/spark/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.microframeworks.spark.SparkApplication
--------------------------------------------------------------------------------
/armeria/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.microframeworks.armeria.ArmeriaApplication
--------------------------------------------------------------------------------
/javalin/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.microframeworks.javalin.JavalinApplication
--------------------------------------------------------------------------------
/jooby/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.demo.microframeworks.jooby.JoobyApplication
--------------------------------------------------------------------------------
/ktor/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.demo.microframeworks.ktor.KtorApplicationKt
--------------------------------------------------------------------------------
/http4k/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.demo.microframeworks.http4k.Http4kApplicationKt
--------------------------------------------------------------------------------
/minijax/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.microframeworks.minijax.MinijaxApplication
9 |
--------------------------------------------------------------------------------
/pippo/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.demo.microframeworks.pippo.PippoApplication
9 |
--------------------------------------------------------------------------------
/ratpack/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.demo.microframeworks.ratpack.RatpackApplication
--------------------------------------------------------------------------------
/helidon-mp/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.microframeworks.helidon.mp.HelidonMpApplication
--------------------------------------------------------------------------------
/helidon-se/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.demo.microframeworks.helidon.se.HelidonApplication
--------------------------------------------------------------------------------
/dropwizard/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.microframeworks.dropwizard.DropWizardApplication server
--------------------------------------------------------------------------------
/micronaut/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
2 |
3 | WORKDIR /opt/application
4 |
5 | COPY target/libs/* ./libs/
6 | COPY target/application.jar ./application.jar
7 |
8 | ENTRYPOINT java -cp "/opt/application/application.jar:/opt/application/libs/*" nl.jaapcoomans.demo.microframeworks.micronaut.MicronautApplication server
--------------------------------------------------------------------------------
/kumuluzee/src/main/resources/META-INF/beans.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/micronaut/src/main/java/nl/jaapcoomans/demo/microframeworks/micronaut/MicronautApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.micronaut;
2 |
3 | import io.micronaut.runtime.Micronaut;
4 |
5 | public class MicronautApplication {
6 | public static void main(String[] args) {
7 | Micronaut.run(MicronautApplication.class);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/todo-backend/src/main/java/nl/jaapcoomans/demo/microframeworks/todo/domain/TodoRepository.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.domain;
2 |
3 | import java.util.List;
4 | import java.util.Optional;
5 | import java.util.UUID;
6 |
7 | public interface TodoRepository {
8 | Todo persist(Todo todo);
9 |
10 | List findAll();
11 |
12 | void deleteAll();
13 |
14 | Optional findById(UUID id);
15 |
16 | void delete(UUID id);
17 | }
18 |
--------------------------------------------------------------------------------
/helidon-mp/src/main/java/nl/jaapcoomans/microframeworks/helidon/mp/HelidonMpApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.helidon.mp;
2 |
3 | import io.helidon.microprofile.server.Server;
4 |
5 | public class HelidonMpApplication {
6 | public static void main(String[] args) {
7 | Server.builder()
8 | .addApplication(new HelloWorldApplication())
9 | .addApplication(new TodoApplication())
10 | .build()
11 | .start();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/helidon-mp/src/main/java/nl/jaapcoomans/microframeworks/helidon/mp/HelloWorldApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.helidon.mp;
2 |
3 | import javax.enterprise.context.ApplicationScoped;
4 | import javax.ws.rs.ApplicationPath;
5 | import javax.ws.rs.core.Application;
6 | import java.util.Set;
7 |
8 | @ApplicationScoped
9 | @ApplicationPath("/")
10 | public class HelloWorldApplication extends Application {
11 | @Override
12 | public Set> getClasses() {
13 | return Set.of(HelloWorldController.class);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/todo-backend/src/main/java/nl/jaapcoomans/demo/microframeworks/todo/api/CreateTodoCommand.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.api;
2 |
3 | public class CreateTodoCommand {
4 | private String title;
5 | private int order;
6 |
7 | public String getTitle() {
8 | return title;
9 | }
10 |
11 | public void setTitle(String title) {
12 | this.title = title;
13 | }
14 |
15 | public int getOrder() {
16 | return order;
17 | }
18 |
19 | public void setOrder(int order) {
20 | this.order = order;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/micronaut/src/main/java/nl/jaapcoomans/demo/microframeworks/micronaut/TodoFactory.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.micronaut;
2 |
3 | import io.micronaut.context.annotation.Bean;
4 | import io.micronaut.context.annotation.Factory;
5 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
6 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
7 |
8 | @Factory
9 | public class TodoFactory {
10 | @Bean()
11 | public TodoService todoService() {
12 | return new TodoService(new InMemoryTodoRepository());
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/kumuluzee/src/main/java/nl/jaapcoomans/demo/microframeworks/kumuluzee/KumuluzEEApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.kumuluzee;
2 |
3 | import javax.ws.rs.ApplicationPath;
4 | import javax.ws.rs.core.Application;
5 | import java.util.HashSet;
6 | import java.util.Set;
7 |
8 | @ApplicationPath("")
9 | public class KumuluzEEApplication extends Application {
10 | @Override
11 | public Set> getClasses() {
12 | Set> classes = new HashSet<>();
13 | classes.add(HelloWorldController.class);
14 | classes.add(TodoController.class);
15 | return classes;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/todo-backend/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | todo-backend
8 |
9 |
10 | parent
11 | nl.jaapcoomans.demo.microframeworks
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 1.8
17 |
18 |
--------------------------------------------------------------------------------
/kumuluzee/src/main/java/nl/jaapcoomans/demo/microframeworks/kumuluzee/TodoBackendFactory.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.kumuluzee;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoRepository;
4 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
5 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
6 |
7 | import javax.enterprise.context.ApplicationScoped;
8 | import javax.enterprise.inject.Produces;
9 |
10 | @ApplicationScoped
11 | public class TodoBackendFactory {
12 | @Produces
13 | public TodoRepository todoRepository() {
14 | return new InMemoryTodoRepository();
15 | }
16 |
17 | @Produces
18 | public TodoService todoService() {
19 | return new TodoService(todoRepository());
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/JavalinTodoTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class JavalinTodoTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile javalinImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../javalin"));
13 |
14 | @Container
15 | private static final GenericContainer> javalinContainer = new GenericContainer<>(javalinImage).withExposedPorts(7000);
16 |
17 | final GenericContainer>getContainer() {
18 | return javalinContainer;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/Http4kTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class Http4kTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile http4kImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../http4k"));
13 |
14 | @Container
15 | private static final GenericContainer> http4kContainer = new GenericContainer<>(http4kImage).withExposedPorts(8080);
16 |
17 | final GenericContainer> getContainer() {
18 | return http4kContainer;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/KtorTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class KtorTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile ktorImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../ktor"));
13 |
14 | @Container
15 | private static final GenericContainer> ktorContainer = new GenericContainer<>(ktorImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return ktorContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/BladeTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class BladeTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile bladeImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../blade"));
13 |
14 | @Container
15 | private static final GenericContainer> bladeContainer = new GenericContainer<>(bladeImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return bladeContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/JoobyTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class JoobyTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile joobyImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../jooby"));
13 |
14 | @Container
15 | private static final GenericContainer> joobyContainer = new GenericContainer<>(joobyImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return joobyContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/PippoTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class PippoTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile pippoImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../pippo"));
13 |
14 | @Container
15 | private static final GenericContainer> pippoContainer = new GenericContainer<>(pippoImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return pippoContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/SparkTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class SparkTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile sparkImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../spark"));
13 |
14 | @Container
15 | private static final GenericContainer> sparkContainer = new GenericContainer<>(sparkImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return sparkContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/ArmeriaTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class ArmeriaTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile armeriaImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../armeria"));
13 |
14 | @Container
15 | private static final GenericContainer> armeriaContainer = new GenericContainer<>(armeriaImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return armeriaContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/MinijaxTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class MinijaxTodoBackendTest extends BaseTodoBackendTest{
12 | private static final ImageFromDockerfile minijaxImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../minijax"));
13 |
14 | @Container
15 | private static final GenericContainer> minijaxContainer = new GenericContainer<>(minijaxImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return minijaxContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/RatpackTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class RatpackTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile ratpackImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../ratpack"));
13 |
14 | @Container
15 | private static final GenericContainer> ratpackContainer = new GenericContainer<>(ratpackImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return ratpackContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend/src/main/java/nl/jaapcoomans/demo/microframeworks/todo/domain/PartialTodo.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.domain;
2 |
3 | import java.util.Optional;
4 |
5 | public class PartialTodo {
6 | private String title;
7 | private Boolean completed;
8 | private Integer order;
9 |
10 | public void setTitle(String title) {
11 | this.title = title;
12 | }
13 |
14 | public void setCompleted(Boolean completed) {
15 | this.completed = completed;
16 | }
17 |
18 | public void setOrder(Integer order) {
19 | this.order = order;
20 | }
21 |
22 | Optional title() {
23 | return Optional.ofNullable(this.title);
24 | }
25 |
26 | Optional completed() {
27 | return Optional.ofNullable(this.completed);
28 | }
29 |
30 | Optional order() {
31 | return Optional.ofNullable(this.order);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/HelidonMpTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class HelidonMpTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile helidonImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../helidon-mp"));
13 |
14 | @Container
15 | private static final GenericContainer> helidonContainer = new GenericContainer<>(helidonImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return helidonContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/HelidonSeTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class HelidonSeTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile helidonImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../helidon-se"));
13 |
14 | @Container
15 | private static final GenericContainer> helidonContainer = new GenericContainer<>(helidonImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return helidonContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/KumuluzEeTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class KumuluzEeTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile kumuluzEeImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../kumuluzee"));
13 |
14 | @Container
15 | private static final GenericContainer> kumuluzEeContainer = new GenericContainer<>(kumuluzEeImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return kumuluzEeContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/QuarkusTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | public class QuarkusTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile quarkusImage = new ImageFromDockerfile()
13 | .withFileFromPath(".", Paths.get("../quarkus"));
14 |
15 | @Container
16 | private static final GenericContainer> quarkusContainer = new GenericContainer<>(quarkusImage).withExposedPorts(8080);
17 |
18 | @Override
19 | GenericContainer> getContainer() {
20 | return quarkusContainer;
21 | }
22 | }
--------------------------------------------------------------------------------
/quarkus/src/main/java/nl/jaapcoomans/microframeworks/quarkus/QuarkusApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.quarkus;
2 |
3 | import io.quarkus.runtime.Quarkus;
4 | import io.quarkus.runtime.annotations.QuarkusMain;
5 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoRepository;
6 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
7 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
8 |
9 | import javax.enterprise.inject.Produces;
10 |
11 | @QuarkusMain
12 | public class QuarkusApplication {
13 | public static void main(String... args) {
14 | Quarkus.run(args);
15 | }
16 |
17 | @Produces
18 | public TodoService todoService(TodoRepository todoRepository) {
19 | return new TodoService(todoRepository);
20 | }
21 |
22 | @Produces
23 | public TodoRepository todoRepository() {
24 | return new InMemoryTodoRepository();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/DropWizardTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | class DropWizardTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile dropWizardImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../dropwizard"));
13 |
14 | @Container
15 | private static final GenericContainer> dropWizardContainer = new GenericContainer<>(dropWizardImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return dropWizardContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/MicronautTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import org.testcontainers.containers.GenericContainer;
4 | import org.testcontainers.images.builder.ImageFromDockerfile;
5 | import org.testcontainers.junit.jupiter.Container;
6 | import org.testcontainers.junit.jupiter.Testcontainers;
7 |
8 | import java.nio.file.Paths;
9 |
10 | @Testcontainers
11 | public class MicronautTodoBackendTest extends BaseTodoBackendTest {
12 | private static final ImageFromDockerfile micronautImage = new ImageFromDockerfile().withFileFromPath(".", Paths.get("../micronaut"));
13 |
14 | @Container
15 | private static final GenericContainer> micronautContainer = new GenericContainer<>(micronautImage).withExposedPorts(8080);
16 |
17 | @Override
18 | GenericContainer> getContainer() {
19 | return micronautContainer;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/dropwizard/src/main/java/nl/jaapcoomans/microframeworks/dropwizard/HelloWorldController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.dropwizard;
2 |
3 | import javax.ws.rs.GET;
4 | import javax.ws.rs.Path;
5 | import javax.ws.rs.PathParam;
6 | import javax.ws.rs.Produces;
7 | import javax.ws.rs.core.MediaType;
8 |
9 | @Path("/hello")
10 | @Produces(MediaType.TEXT_PLAIN)
11 | public class HelloWorldController {
12 | @GET
13 | public String helloWorld() {
14 | return "Hello World!";
15 | }
16 |
17 | @GET
18 | @Path("/{name}")
19 | public String hello(@PathParam("name") String name) {
20 | return String.format("Hello, %s!", capitalize(name));
21 | }
22 |
23 | private static String capitalize(String name) {
24 | if (name.length() < 2) {
25 | return name.toUpperCase();
26 | } else {
27 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/minijax/src/main/java/nl/jaapcoomans/microframeworks/minijax/HelloWorldController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.minijax;
2 |
3 | import jakarta.ws.rs.GET;
4 | import jakarta.ws.rs.Path;
5 | import jakarta.ws.rs.PathParam;
6 | import jakarta.ws.rs.Produces;
7 | import jakarta.ws.rs.core.MediaType;
8 |
9 | public class HelloWorldController {
10 | @GET
11 | @Path("/hello")
12 | public String helloworld() {
13 | return "Hello World!";
14 | }
15 |
16 | @GET
17 | @Path("/hello/{name}")
18 | @Produces(MediaType.TEXT_PLAIN)
19 | public String hello(@PathParam("name") String name) {
20 | return String.format("Hello, %s!", capitalize(name));
21 | }
22 |
23 | private static String capitalize(String name) {
24 | if (name.length() < 2) {
25 | return name.toUpperCase();
26 | } else {
27 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/quarkus/src/main/java/nl/jaapcoomans/microframeworks/quarkus/HelloWorldController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.quarkus;
2 |
3 | import javax.ws.rs.GET;
4 | import javax.ws.rs.Path;
5 | import javax.ws.rs.PathParam;
6 | import javax.ws.rs.Produces;
7 | import javax.ws.rs.core.MediaType;
8 |
9 | @Path("/hello")
10 | public class HelloWorldController {
11 | @GET
12 | @Produces(MediaType.TEXT_PLAIN)
13 | public String helloWorld() {
14 | return "Hello World!";
15 | }
16 |
17 | @GET
18 | @Path("/{name}")
19 | @Produces(MediaType.TEXT_PLAIN)
20 | public String hello(@PathParam("name") String name) {
21 | return String.format("Hello, %s!", capitalize(name));
22 | }
23 |
24 | private static String capitalize(String name) {
25 | if (name.length() < 2) {
26 | return name.toUpperCase();
27 | } else {
28 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/kumuluzee/src/main/java/nl/jaapcoomans/demo/microframeworks/kumuluzee/HelloWorldController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.kumuluzee;
2 |
3 | import javax.ws.rs.GET;
4 | import javax.ws.rs.Path;
5 | import javax.ws.rs.PathParam;
6 | import javax.ws.rs.Produces;
7 | import javax.ws.rs.core.MediaType;
8 |
9 | @Path("/hello")
10 | public class HelloWorldController {
11 |
12 | @GET
13 | @Produces(MediaType.TEXT_PLAIN)
14 | public String helloWorld() {
15 | return "Hello World!";
16 | }
17 |
18 | @GET
19 | @Path("/{name}")
20 | @Produces(MediaType.TEXT_PLAIN)
21 | public String helloWorld(@PathParam("name") String name) {
22 | return String.format("Hello, %s!", capitalize(name));
23 | }
24 |
25 | private String capitalize(String name) {
26 | if (name.length() < 2) {
27 | return name.toUpperCase();
28 | } else {
29 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/helidon-mp/src/main/java/nl/jaapcoomans/microframeworks/helidon/mp/HelloWorldController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.helidon.mp;
2 |
3 | import javax.enterprise.context.RequestScoped;
4 | import javax.ws.rs.GET;
5 | import javax.ws.rs.Path;
6 | import javax.ws.rs.PathParam;
7 | import javax.ws.rs.Produces;
8 | import javax.ws.rs.core.MediaType;
9 |
10 | @RequestScoped
11 | @Path("/hello")
12 | public class HelloWorldController {
13 | @GET
14 | @Produces(MediaType.TEXT_PLAIN)
15 | public String helloWorld() {
16 | return "Hello World!";
17 | }
18 |
19 | @GET
20 | @Path("/{name}")
21 | @Produces(MediaType.TEXT_PLAIN)
22 | public String hello(@PathParam("name") String name) {
23 | return String.format("Hello, %s!", capitalize(name));
24 | }
25 |
26 | private static String capitalize(String name) {
27 | if (name.length() < 2) {
28 | return name.toUpperCase();
29 | } else {
30 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/helidon-mp/src/main/java/nl/jaapcoomans/microframeworks/helidon/mp/CorsFilter.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.helidon.mp;
2 |
3 | import javax.ws.rs.HttpMethod;
4 | import javax.ws.rs.container.ContainerRequestContext;
5 | import javax.ws.rs.container.ContainerResponseContext;
6 | import javax.ws.rs.container.ContainerResponseFilter;
7 | import javax.ws.rs.ext.Provider;
8 |
9 | @Provider
10 | public class CorsFilter implements ContainerResponseFilter {
11 |
12 | @Override
13 | public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
14 | if (!HttpMethod.OPTIONS.equals(requestContext.getMethod())) {
15 | responseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
16 | responseContext.getHeaders().add("Access-Control-Allow-Credentials", "true");
17 | responseContext.getHeaders().add("Access-Control-Allow-Headers", "content-type");
18 | responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/micronaut/src/main/java/nl/jaapcoomans/demo/microframeworks/micronaut/HelloWorldController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.micronaut;
2 |
3 | import io.micronaut.http.MediaType;
4 | import io.micronaut.http.annotation.Controller;
5 | import io.micronaut.http.annotation.Get;
6 | import io.micronaut.http.annotation.PathVariable;
7 | import io.reactivex.Single;
8 |
9 | @Controller("/hello")
10 | public class HelloWorldController {
11 | @Get(produces = MediaType.TEXT_PLAIN)
12 | public Single helloWorld() {
13 | return Single.just("Hello World!");
14 | }
15 |
16 | @Get(uri = "/{name}", produces = MediaType.TEXT_PLAIN)
17 | public Single helloWorld(@PathVariable String name) {
18 | return Single.just(String.format("Hello, %s!", capitalize(name)));
19 | }
20 |
21 | private String capitalize(String name) {
22 | if (name.length() < 2) {
23 | return name.toUpperCase();
24 | } else {
25 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/spark/src/main/java/nl/jaapcoomans/microframeworks/spark/JacksonResponseTransformer.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.spark;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import spark.ResponseTransformer;
6 |
7 | import java.util.Optional;
8 |
9 | public class JacksonResponseTransformer implements ResponseTransformer {
10 | private ObjectMapper objectMapper = new ObjectMapper();
11 |
12 | @Override
13 | public String render(Object model) {
14 | if (model instanceof Optional) {
15 | Optional> optional = (Optional>) model;
16 | return optional
17 | .map(this::serialize)
18 | .orElse("");
19 | }
20 |
21 | return this.serialize(model);
22 | }
23 |
24 | private String serialize(Object model) {
25 | try {
26 | return objectMapper.writeValueAsString(model);
27 | } catch (JsonProcessingException e) {
28 | throw new RuntimeException("Failed to serialize to JSON.", e);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/helidon-mp/src/main/java/nl/jaapcoomans/microframeworks/helidon/mp/TodoApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.helidon.mp;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoRepository;
4 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
5 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
6 |
7 | import javax.enterprise.context.ApplicationScoped;
8 | import javax.enterprise.inject.Produces;
9 | import javax.ws.rs.ApplicationPath;
10 | import javax.ws.rs.core.Application;
11 | import java.util.Set;
12 |
13 | @ApplicationScoped
14 | @ApplicationPath("/todos")
15 | public class TodoApplication extends Application {
16 | @Produces
17 | public TodoRepository todoRepository() {
18 | return new InMemoryTodoRepository();
19 | }
20 |
21 | @Produces
22 | public TodoService todoService(TodoRepository todoRepository) {
23 | return new TodoService(todoRepository);
24 | }
25 |
26 | @Override
27 | public Set> getClasses() {
28 | return Set.of(TodoController.class, CorsFilter.class);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Jaap Coomans
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/helidon-mp/src/main/resources/META-INF/beans.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
26 |
27 |
--------------------------------------------------------------------------------
/minijax/src/main/java/nl/jaapcoomans/microframeworks/minijax/MinijaxApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.minijax;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
4 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
5 | import org.minijax.Minijax;
6 | import org.minijax.json.JsonFeature;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | public class MinijaxApplication {
11 | private static final Logger LOGGER = LoggerFactory.getLogger(MinijaxApplication.class);
12 |
13 | public static void main(String[] args) {
14 | long startTime = System.currentTimeMillis();
15 |
16 | var todoRepository = new InMemoryTodoRepository();
17 |
18 | new Minijax()
19 | .port(8080)
20 | .register(JsonFeature.class)
21 | .register(HelloWorldController.class)
22 | .register(new TodoService(todoRepository))
23 | .register(TodoController.class)
24 | .allowCors("/")
25 | .start();
26 |
27 | LOGGER.info("Started in {} ms", System.currentTimeMillis() - startTime);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/helidon-se/src/main/java/nl/jaapcoomans/demo/microframeworks/helidon/se/HelloWorldRestController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.helidon.se;
2 |
3 | import io.helidon.webserver.Routing;
4 | import io.helidon.webserver.ServerRequest;
5 | import io.helidon.webserver.ServerResponse;
6 | import io.helidon.webserver.Service;
7 |
8 | public class HelloWorldRestController implements Service {
9 | @Override
10 | public void update(Routing.Rules rules) {
11 | rules
12 | .get("/", this::helloWorld)
13 | .get("/{name}", this::hello);
14 | }
15 |
16 | private void helloWorld(ServerRequest request, ServerResponse response) {
17 | response.send("Hello World!");
18 | }
19 |
20 | private void hello(ServerRequest request, ServerResponse response) {
21 | response.send(String.format("Hello, %s!", capitalize(request.path().param("name"))));
22 | }
23 |
24 | private static String capitalize(String name) {
25 | if (name.length() < 2) {
26 | return name.toUpperCase();
27 | } else {
28 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/todo-backend/src/main/java/nl/jaapcoomans/demo/microframeworks/todo/peristsence/InMemoryTodoRepository.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.peristsence;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
4 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoRepository;
5 |
6 | import java.util.ArrayList;
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.util.Optional;
11 | import java.util.UUID;
12 |
13 | public class InMemoryTodoRepository implements TodoRepository {
14 | private static final Map TODOS = new HashMap<>();
15 |
16 | @Override
17 | public List findAll() {
18 | return new ArrayList<>(TODOS.values());
19 | }
20 |
21 | @Override
22 | public Optional findById(UUID id) {
23 | return Optional.ofNullable(TODOS.get(id));
24 | }
25 |
26 | @Override
27 | public void delete(UUID id) {
28 | TODOS.remove(id);
29 | }
30 |
31 | @Override
32 | public Todo persist(Todo todo) {
33 | TODOS.put(todo.getId(), todo);
34 | return todo;
35 | }
36 |
37 | @Override
38 | public void deleteAll() {
39 | TODOS.clear();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/todo-backend/src/main/java/nl/jaapcoomans/demo/microframeworks/todo/domain/TodoService.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.domain;
2 |
3 | import java.util.List;
4 | import java.util.Optional;
5 | import java.util.UUID;
6 |
7 | public class TodoService {
8 | private TodoRepository repository;
9 |
10 | public TodoService(TodoRepository repository) {
11 | this.repository = repository;
12 | }
13 |
14 | public List findAll() {
15 | return this.repository.findAll();
16 | }
17 |
18 | public Optional findById(UUID id) {
19 | return repository.findById(id);
20 | }
21 |
22 | public Todo createNewTodo(String title, int order) {
23 | Todo todo = Todo.create(title, order);
24 |
25 | return this.repository.persist(todo);
26 | }
27 |
28 | public void deleteAll() {
29 | this.repository.deleteAll();
30 | }
31 |
32 | public void delete(UUID id) {
33 | this.repository.delete(id);
34 | }
35 |
36 | public Optional updateTodo(UUID id, PartialTodo command) {
37 | return this.repository.findById(id)
38 | .map(todo -> todo.update(command))
39 | .map(repository::persist);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/quarkus/Dockerfile:
--------------------------------------------------------------------------------
1 | #FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3
2 | FROM adoptopenjdk/openjdk16:jre-16.0.1_9-alpine
3 |
4 | ARG RUN_JAVA_VERSION=1.3.8
5 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
6 | # Install the run-java script
7 | ADD https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh /deployments/run-java.sh
8 |
9 | # Also set up permissions for user `1001`
10 | RUN chown 1001 /deployments \
11 | && chmod "g+rwX" /deployments \
12 | && chown 1001:root /deployments \
13 | && chown 1001 /deployments/run-java.sh \
14 | && chmod 540 /deployments/run-java.sh
15 |
16 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
17 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
18 | # We make four distinct layers so if there are application changes the library layers can be re-used
19 | COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/
20 | COPY --chown=1001 target/quarkus-app/*.jar /deployments/
21 | COPY --chown=1001 target/quarkus-app/app/ /deployments/app/
22 | COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/
23 |
24 | EXPOSE 8080
25 | USER 1001
26 |
27 | ENTRYPOINT [ "/deployments/run-java.sh" ]
28 |
--------------------------------------------------------------------------------
/blade/src/main/java/nl/jaapcoomans/microframeworks/blade/JacksonJsonSupport.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.blade;
2 |
3 | import com.blade.kit.ReflectKit;
4 | import com.blade.kit.json.JsonSupport;
5 | import com.fasterxml.jackson.core.JsonProcessingException;
6 | import com.fasterxml.jackson.databind.ObjectMapper;
7 |
8 | import java.io.IOException;
9 | import java.lang.reflect.Type;
10 |
11 | public class JacksonJsonSupport implements JsonSupport {
12 | private ObjectMapper objectMapper = new ObjectMapper();
13 |
14 | @Override
15 | public String toString(Object data) {
16 | try {
17 | return this.objectMapper.writeValueAsString(data);
18 | } catch (JsonProcessingException e) {
19 | throw new RuntimeException("Error while serializing to JSON: " + e.getMessage(), e);
20 | }
21 | }
22 |
23 | @Override
24 | public T formJson(String json, Type type) {
25 | try {
26 | @SuppressWarnings("unchecked")
27 | Class clazz = (Class) ReflectKit.typeToClass(type);
28 | return this.objectMapper.readValue(json, clazz);
29 | } catch (IOException e) {
30 | throw new RuntimeException("Error while parsing JSON: " + e.getMessage(), e);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: "3"
2 |
3 | services:
4 | armeria:
5 | build: armeria
6 | ports:
7 | - "7001:8080"
8 | blade:
9 | build: blade
10 | ports:
11 | - "7002:8080"
12 | dropwizard:
13 | build: dropwizard
14 | ports:
15 | - "7003:8080"
16 | helidon-mp:
17 | build: helidon-mp
18 | ports:
19 | - "7004:8080"
20 | helidon-se:
21 | build: helidon-se
22 | ports:
23 | - "7005:8080"
24 | http4k:
25 | build: http4k
26 | ports:
27 | - "7006:8080"
28 | javalin:
29 | build: javalin
30 | ports:
31 | - "7007:7000"
32 | jooby:
33 | build: jooby
34 | ports:
35 | - "7008:8080"
36 | ktor:
37 | build: ktor
38 | ports:
39 | - "7009:8080"
40 | kumuluzee:
41 | build: kumuluzee
42 | ports:
43 | - "7010:8080"
44 | micronaut:
45 | build: micronaut
46 | ports:
47 | - "7011:8080"
48 | minijax:
49 | build: minijax
50 | ports:
51 | - "7012:8080"
52 | pippo:
53 | build: pippo
54 | ports:
55 | - "7013:8080"
56 | ratpack:
57 | build: ratpack
58 | ports:
59 | - "7014:8080"
60 | spark:
61 | build: spark
62 | ports:
63 | - "7015:8080"
64 | quarkus:
65 | build: quarkus
66 | ports:
67 | - "7016:8080"
--------------------------------------------------------------------------------
/todo-backend/src/main/java/nl/jaapcoomans/demo/microframeworks/todo/api/TodoDTO.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.api;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
4 |
5 | import java.util.UUID;
6 |
7 | public class TodoDTO {
8 | private UUID id;
9 | private String title;
10 | private String url;
11 | private boolean completed;
12 | private int order;
13 |
14 | private TodoDTO(UUID id, String title, String url, boolean completed, int order) {
15 | this.id = id;
16 | this.title = title;
17 | this.url = url;
18 | this.completed = completed;
19 | this.order = order;
20 | }
21 |
22 | public static TodoDTO from(Todo todo, String url) {
23 | return new TodoDTO(
24 | todo.getId(),
25 | todo.getTitle(),
26 | url,
27 | todo.isCompleted(),
28 | todo.getOrder()
29 | );
30 | }
31 |
32 | public UUID getId() {
33 | return id;
34 | }
35 |
36 | public String getTitle() {
37 | return title;
38 | }
39 |
40 | public String getUrl() {
41 | return url;
42 | }
43 |
44 | public boolean isCompleted() {
45 | return completed;
46 | }
47 |
48 | public int getOrder() {
49 | return order;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/todo-backend/src/main/java/nl/jaapcoomans/demo/microframeworks/todo/domain/Todo.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.domain;
2 |
3 | import java.util.UUID;
4 |
5 | public class Todo {
6 | private UUID id;
7 | private String title;
8 | private boolean completed;
9 | private int order;
10 |
11 | private Todo(UUID id, String title, boolean completed, int order) {
12 | this.id = id;
13 | this.title = title;
14 | this.completed = completed;
15 | this.order = order;
16 | }
17 |
18 | static Todo create(String title, int order) {
19 | return new Todo(UUID.randomUUID(), title, false, order);
20 | }
21 |
22 | Todo changeTitle(String title) {
23 | return new Todo(this.id, title, this.completed, this.order);
24 | }
25 |
26 | Todo complete() {
27 | return new Todo(this.id, this.title, true, this.order);
28 | }
29 |
30 | Todo restore() {
31 | return new Todo(this.id, this.title, false, this.order);
32 | }
33 |
34 | Todo reorder(int order) {
35 | return new Todo(this.id, this.title, this.completed, order);
36 | }
37 |
38 | public UUID getId() {
39 | return id;
40 | }
41 |
42 | public String getTitle() {
43 | return title;
44 | }
45 |
46 | public boolean isCompleted() {
47 | return completed;
48 | }
49 |
50 | public int getOrder() {
51 | return order;
52 | }
53 |
54 | Todo update(PartialTodo todo) {
55 | return new Todo(
56 | this.id,
57 | todo.title().orElse(this.title),
58 | todo.completed().orElse(this.completed),
59 | todo.order().orElse(this.order)
60 | );
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/ktor/src/main/kotlin/nl/jaapcoomans/demo/microframeworks/ktor/KtorApplication.kt:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.ktor
2 |
3 | import io.ktor.application.Application
4 | import io.ktor.application.ApplicationStarted
5 | import io.ktor.application.call
6 | import io.ktor.application.install
7 | import io.ktor.application.log
8 | import io.ktor.features.CORS
9 | import io.ktor.features.ContentNegotiation
10 | import io.ktor.http.ContentType
11 | import io.ktor.http.HttpMethod
12 | import io.ktor.jackson.jackson
13 | import io.ktor.response.respondText
14 | import io.ktor.routing.get
15 | import io.ktor.routing.routing
16 | import java.util.Locale
17 |
18 | fun main(args: Array): Unit = io.ktor.server.netty.EngineMain.main(args)
19 |
20 | fun Application.module() {
21 | val startTime = System.currentTimeMillis()
22 |
23 | install(ContentNegotiation) {
24 | jackson {}
25 | }
26 | install(CORS) {
27 | method(HttpMethod.Get)
28 | method(HttpMethod.Post)
29 | method(HttpMethod.Delete)
30 | method(HttpMethod.Patch)
31 | method(HttpMethod.Options)
32 | anyHost()
33 | allowNonSimpleContentTypes = true
34 | allowSameOrigin = false
35 | }
36 |
37 | routing {
38 | get("/hello") {
39 | call.respondText("Hello World!", ContentType.Text.Plain)
40 | }
41 | get("/hello/{name}") {
42 | call.respondText("Hello, ${call.parameters["name"]?.capitalize()}!", ContentType.Text.Plain)
43 | }
44 |
45 | todoRoutes()
46 | }
47 |
48 | environment.monitor.subscribe(ApplicationStarted) {
49 | val bootTime = System.currentTimeMillis() - startTime
50 | log.info("Started in ${bootTime} ms.");
51 | }
52 | }
53 |
54 | fun String.capitalize(): String {
55 | return this.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
56 | }
--------------------------------------------------------------------------------
/minijax/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | minijax
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 0.5.10
17 |
18 |
19 |
20 |
21 | org.minijax
22 | minijax-undertow
23 | ${minijax.version}
24 |
25 |
26 | org.minijax
27 | minijax-json
28 | ${minijax.version}
29 |
30 |
31 |
32 |
33 | nl.jaapcoomans.demo.microframeworks
34 | todo-backend
35 | 0.0.1-SNAPSHOT
36 |
37 |
38 |
39 |
40 | org.slf4j
41 | slf4j-simple
42 |
43 |
44 |
45 |
46 |
47 |
48 | org.apache.maven.plugins
49 | maven-jar-plugin
50 |
51 |
52 | org.apache.maven.plugins
53 | maven-dependency-plugin
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/spark/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | spark
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 2.9.3
17 | 2.13.4.2
18 |
19 |
20 |
21 |
22 | com.sparkjava
23 | spark-core
24 | ${spark.version}
25 |
26 |
27 |
28 |
29 | nl.jaapcoomans.demo.microframeworks
30 | todo-backend
31 | 0.0.1-SNAPSHOT
32 |
33 |
34 |
35 |
36 | org.slf4j
37 | slf4j-simple
38 |
39 |
40 |
41 |
42 | com.fasterxml.jackson.core
43 | jackson-databind
44 | ${jackson.version}
45 |
46 |
47 |
48 |
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-jar-plugin
53 |
54 |
55 | org.apache.maven.plugins
56 | maven-dependency-plugin
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/dropwizard/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | dropwizard
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 2.0.21
17 | 2.12.3
18 |
19 |
20 |
21 |
22 |
23 | io.dropwizard
24 | dropwizard-dependencies
25 | ${dropwizard.version}
26 | pom
27 | import
28 |
29 |
30 |
31 |
32 |
33 |
34 | io.dropwizard
35 | dropwizard-core
36 | ${dropwizard.version}
37 |
38 |
39 |
40 |
41 | nl.jaapcoomans.demo.microframeworks
42 | todo-backend
43 | 0.0.1-SNAPSHOT
44 |
45 |
46 |
47 |
48 |
49 |
50 | org.apache.maven.plugins
51 | maven-jar-plugin
52 |
53 |
54 | org.apache.maven.plugins
55 | maven-dependency-plugin
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/javalin/src/main/java/nl/jaapcoomans/microframeworks/javalin/JavalinApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.javalin;
2 |
3 | import io.javalin.Javalin;
4 | import io.javalin.apibuilder.EndpointGroup;
5 | import io.javalin.core.JavalinConfig;
6 | import io.javalin.http.Context;
7 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
8 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
9 |
10 | import static io.javalin.apibuilder.ApiBuilder.get;
11 | import static io.javalin.apibuilder.ApiBuilder.path;
12 |
13 | public class JavalinApplication {
14 | private static final int PORT = 7000;
15 |
16 | public static void main(String[] args) {
17 | Javalin.create(JavalinApplication::configure)
18 | .routes(() -> {
19 | path("/hello", helloWorldApi());
20 | path("/todos", todoApi());
21 | })
22 | .start(PORT);
23 | }
24 |
25 | private static void configure(JavalinConfig config) {
26 | config.enableCorsForAllOrigins();
27 | }
28 |
29 | private static EndpointGroup helloWorldApi() {
30 | return () -> {
31 | get(JavalinApplication::helloWorld);
32 | get("/:name", JavalinApplication::hello);
33 | };
34 | }
35 |
36 | private static EndpointGroup todoApi() {
37 | var todoRepository = new InMemoryTodoRepository();
38 | var todoService = new TodoService(todoRepository);
39 | var todoController = new TodoRestController(todoService, "http://localhost:7000/todos");
40 |
41 | return todoController.defineEndpoints();
42 | }
43 |
44 | private static void hello(Context context) {
45 | context.result(String.format("Hello, %s!", capitalize(context.pathParam("name"))));
46 | }
47 |
48 | private static void helloWorld(Context context) {
49 | context.result("Hello World!");
50 | }
51 |
52 | private static String capitalize(String name) {
53 | if (name.length() < 2) {
54 | return name.toUpperCase();
55 | } else {
56 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/dropwizard/src/main/java/nl/jaapcoomans/microframeworks/dropwizard/DropWizardApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.dropwizard;
2 |
3 | import io.dropwizard.Application;
4 | import io.dropwizard.Configuration;
5 | import io.dropwizard.setup.Environment;
6 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
7 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
8 | import org.eclipse.jetty.servlets.CrossOriginFilter;
9 |
10 | import javax.servlet.DispatcherType;
11 | import javax.servlet.FilterRegistration;
12 | import java.util.EnumSet;
13 |
14 | public class DropWizardApplication extends Application {
15 | public static void main(String[] args) throws Exception {
16 | var application = new DropWizardApplication();
17 | application.run(args);
18 | }
19 |
20 | @Override
21 | public void run(Configuration configuration, Environment environment) {
22 | this.enableCors(environment);
23 |
24 | var helloWorldController = new HelloWorldController();
25 | environment.jersey().register(helloWorldController);
26 |
27 | var todoRestController = createTodoBackend();
28 | environment.jersey().register(todoRestController);
29 | }
30 |
31 | private void enableCors(Environment environment) {
32 | final FilterRegistration.Dynamic cors = environment.servlets().addFilter("CORS", CrossOriginFilter.class);
33 |
34 | cors.setInitParameter("allowedOrigins", "*");
35 | cors.setInitParameter("allowedHeaders", "Content-Type");
36 | cors.setInitParameter("allowedMethods", "OPTIONS,GET,PUT,POST,DELETE,HEAD");
37 |
38 | // Add URL mapping
39 | cors.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
40 |
41 | // Do not pass preflight requests on to application.
42 | cors.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, "false");
43 | }
44 |
45 | private TodoRestController createTodoBackend() {
46 | var repository = new InMemoryTodoRepository();
47 | var todoService = new TodoService(repository);
48 |
49 | return new TodoRestController(todoService, "http://localhost:8080/todos");
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/http4k/src/main/kotlin/nl/jaapcoomans/demo/microframeworks/http4k/Http4kApplication.kt:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.http4k
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService
4 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository
5 | import org.http4k.core.Method.DELETE
6 | import org.http4k.core.Method.GET
7 | import org.http4k.core.Method.PATCH
8 | import org.http4k.core.Method.POST
9 | import org.http4k.core.Request
10 | import org.http4k.core.Response
11 | import org.http4k.core.Status.Companion.OK
12 | import org.http4k.filter.AllowAllOriginPolicy
13 | import org.http4k.filter.CorsPolicy
14 | import org.http4k.filter.ServerFilters
15 | import org.http4k.routing.bind
16 | import org.http4k.routing.path
17 | import org.http4k.routing.routes
18 | import org.http4k.server.Jetty
19 | import org.http4k.server.asServer
20 | import java.util.Locale
21 |
22 | fun main() {
23 | val todoRepository = InMemoryTodoRepository()
24 | val todoService = TodoService(todoRepository)
25 | val todoRestController = TodoRestController(todoService)
26 |
27 | val app = routes(
28 | "/hello" bind GET to { Response(OK).body("Hello World!") },
29 | "/hello/{name}" bind GET to helloController,
30 | "/todos" bind GET to todoRestController::getAll,
31 | "/todos" bind POST to todoRestController::createTodo,
32 | "/todos" bind DELETE to todoRestController::deleteAll,
33 | "/todos/{id}" bind GET to todoRestController::getTodo,
34 | "/todos/{id}" bind PATCH to todoRestController::patchTodo,
35 | "/todos/{id}" bind DELETE to todoRestController::deleteTodo
36 | ).withFilter(ServerFilters.Cors(CorsPolicy(
37 | originPolicy = AllowAllOriginPolicy,
38 | headers = listOf("Content-Type"),
39 | methods = listOf(GET, POST, DELETE, PATCH)
40 | )))
41 |
42 | val server = app.asServer(Jetty(8080))
43 |
44 | server.start()
45 | }
46 |
47 | val helloController = fun(req: Request): Response {
48 | return Response(OK).body("Hello, ${req.path("name")?.capitalize()}!")
49 | }
50 |
51 | fun String.capitalize(): String {
52 | return this.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/kumuluzee/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | kumuluzee
8 |
9 |
10 | parent
11 | nl.jaapcoomans.demo.microframeworks
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 11
17 | 3.12.1
18 |
19 |
20 |
21 |
22 |
23 | com.kumuluz.ee
24 | kumuluzee-bom
25 | ${kumuluzee.version}
26 | pom
27 | import
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | com.kumuluz.ee
36 | kumuluzee-microProfile-3.3
37 |
38 |
39 | com.kumuluz.ee.cors
40 | kumuluzee-cors
41 | 1.0.6
42 |
43 |
44 |
45 |
46 | nl.jaapcoomans.demo.microframeworks
47 | todo-backend
48 | 0.0.1-SNAPSHOT
49 |
50 |
51 |
52 |
53 |
54 |
55 | org.apache.maven.plugins
56 | maven-jar-plugin
57 |
58 |
59 | org.apache.maven.plugins
60 | maven-dependency-plugin
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/jooby/src/main/java/nl/jaapcoomans/demo/microframeworks/jooby/JoobyApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.jooby;
2 |
3 | import io.jooby.Context;
4 | import io.jooby.CorsHandler;
5 | import io.jooby.MediaType;
6 | import io.jooby.ServerOptions;
7 | import io.jooby.json.JacksonModule;
8 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
9 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
10 |
11 | import javax.annotation.Nonnull;
12 |
13 | import static io.jooby.Jooby.runApp;
14 |
15 | public class JoobyApplication {
16 | private static final int PORT = 8080;
17 |
18 | public static void main(String[] args) {
19 | long startTime = System.currentTimeMillis();
20 |
21 | var jacksonModule = new JacksonModule();
22 |
23 | var todoRepository = new InMemoryTodoRepository();
24 | var todoService = new TodoService(todoRepository);
25 | var todoController = new TodoRestController(todoService, "http://localhost:8080/todos");
26 |
27 | runApp(args, app -> {
28 | app.setServerOptions(new ServerOptions().setPort(PORT));
29 | app.encoder(MediaType.json, jacksonModule);
30 | app.decoder(MediaType.json, jacksonModule);
31 | app.decorator(new CorsHandler());
32 |
33 | app.get("/hello", JoobyApplication::helloWorld);
34 | app.get("/hello/{name}", JoobyApplication::hello);
35 |
36 | todoController.initializeRoutes(app);
37 |
38 | app.onStarted(() -> {
39 | long bootTime = System.currentTimeMillis() - startTime;
40 | System.out.println("Started in " + bootTime + "ms.");
41 | });
42 | });
43 | }
44 |
45 | private static String helloWorld(Context context) {
46 | return "Hello World!";
47 | }
48 |
49 | @Nonnull
50 | private static String hello(Context context) {
51 | var name = context.path("name").value();
52 | return String.format("Hello, %s!", capitalize(name));
53 | }
54 |
55 | private static String capitalize(String name) {
56 | if (name.length() < 2) {
57 | return name.toUpperCase();
58 | } else {
59 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/blade/src/main/java/nl/jaapcoomans/microframeworks/blade/BladeApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.blade;
2 |
3 | import com.blade.Blade;
4 | import com.blade.kit.JsonKit;
5 | import com.blade.mvc.RouteContext;
6 | import com.blade.security.web.cors.CorsConfiger;
7 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
8 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
9 |
10 | import java.util.List;
11 |
12 | public class BladeApplication {
13 | public static void main(String[] args) {
14 | /*
15 | * The default JsonKit is not configurable and fails to correctly serialize UUID. Luckily the actual
16 | * serialization is pluggable. Therefore created a custom implementation based on Jackson.
17 | */
18 | JsonKit.jsonSupprt(new JacksonJsonSupport());
19 |
20 | Blade application = Blade.of()
21 | .enableCors(true, corsConfiger())
22 | .get("/hello", BladeApplication::helloWorld)
23 | .get("/hello/:name", BladeApplication::hello);
24 |
25 | createTodoBackend(application);
26 |
27 | application.start(BladeApplication.class, args);
28 | }
29 |
30 | private static CorsConfiger corsConfiger() {
31 | return CorsConfiger.builder()
32 | .allowedHeaders(List.of("Content-Type"))
33 | .build();
34 | }
35 |
36 | private static void createTodoBackend(Blade application) {
37 | var todoRepository = new InMemoryTodoRepository();
38 | var todoService = new TodoService(todoRepository);
39 | var todoApi = new TodoRestController(todoService, "http://localhost:7000/todos");
40 |
41 | todoApi.initializeRoutes(application);
42 | }
43 |
44 | private static void helloWorld(RouteContext context) {
45 | context.text("Hello World!");
46 | }
47 |
48 | private static void hello(RouteContext context) {
49 | String name = context.pathString("name");
50 | context.text(String.format("Hello, %s!", capitalize(name)));
51 | }
52 |
53 | private static String capitalize(String name) {
54 | if (name.length() < 2) {
55 | return name.toUpperCase();
56 | } else {
57 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/armeria/src/main/java/nl/jaapcoomans/microframeworks/armeria/ArmeriaApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.armeria;
2 |
3 | import com.linecorp.armeria.common.HttpRequest;
4 | import com.linecorp.armeria.common.HttpResponse;
5 | import com.linecorp.armeria.server.Server;
6 | import com.linecorp.armeria.server.ServerBuilder;
7 | import com.linecorp.armeria.server.ServiceRequestContext;
8 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
9 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
10 | import org.slf4j.Logger;
11 | import org.slf4j.LoggerFactory;
12 |
13 | import java.util.concurrent.CompletableFuture;
14 |
15 | public class ArmeriaApplication {
16 | private static final int PORT = 8080;
17 | private static final Logger LOGGER = LoggerFactory.getLogger(ArmeriaApplication.class);
18 |
19 | public static void main(String[] args) {
20 | final long startTime = System.currentTimeMillis();
21 |
22 | ServerBuilder sb = Server.builder();
23 | sb.http(PORT);
24 |
25 | sb.service("/hello", ArmeriaApplication::helloWorld);
26 | sb.service("/hello/{name}", ArmeriaApplication::hello);
27 |
28 | TodoRestController todoBackendApi = createTodoBackend();
29 | sb.annotatedService(todoBackendApi);
30 |
31 | Server server = sb.build();
32 | CompletableFuture future = server.start();
33 | future.join();
34 |
35 | LOGGER.info("Started in {} ms", System.currentTimeMillis() - startTime);
36 | }
37 |
38 | private static TodoRestController createTodoBackend() {
39 | var todoRepository = new InMemoryTodoRepository();
40 | var todoService = new TodoService(todoRepository);
41 | return new TodoRestController(todoService, "http://localhost:8080/todos");
42 | }
43 |
44 | private static HttpResponse helloWorld(ServiceRequestContext context, HttpRequest request) {
45 | return HttpResponse.of("Hello World!");
46 | }
47 |
48 | private static HttpResponse hello(ServiceRequestContext context, HttpRequest request) {
49 | String name = context.pathParam("name");
50 | return HttpResponse.of("Hello, %s!", capitalize(name));
51 | }
52 |
53 | private static String capitalize(String name) {
54 | if (name.length() < 2) {
55 | return name.toUpperCase();
56 | } else {
57 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/ratpack/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | ratpack
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 1.8.2
17 |
18 |
19 |
20 |
21 | io.ratpack
22 | ratpack-core
23 | ${ratpack.version}
24 |
25 |
26 |
27 |
28 | nl.jaapcoomans.demo.microframeworks
29 | todo-backend
30 | 0.0.1-SNAPSHOT
31 |
32 |
33 |
34 |
35 | org.slf4j
36 | slf4j-simple
37 |
38 |
39 |
40 |
41 | org.junit.jupiter
42 | junit-jupiter-api
43 |
44 |
45 | org.junit.jupiter
46 | junit-jupiter-engine
47 |
48 |
49 | org.mockito
50 | mockito-junit-jupiter
51 |
52 |
53 | org.assertj
54 | assertj-core
55 |
56 |
57 |
58 |
59 |
60 |
61 | org.apache.maven.plugins
62 | maven-jar-plugin
63 |
64 |
65 | org.apache.maven.plugins
66 | maven-dependency-plugin
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/armeria/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | armeria
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 1.24.3
17 |
18 |
19 |
20 |
21 | com.linecorp.armeria
22 | armeria
23 | ${armeria.version}
24 |
25 |
26 |
27 |
28 | nl.jaapcoomans.demo.microframeworks
29 | todo-backend
30 | 0.0.1-SNAPSHOT
31 |
32 |
33 |
34 |
35 | org.slf4j
36 | slf4j-simple
37 |
38 |
39 |
40 |
41 | org.junit.jupiter
42 | junit-jupiter-api
43 |
44 |
45 | org.junit.jupiter
46 | junit-jupiter-engine
47 |
48 |
49 | org.mockito
50 | mockito-junit-jupiter
51 |
52 |
53 | org.assertj
54 | assertj-core
55 |
56 |
57 |
58 |
59 |
60 |
61 | org.apache.maven.plugins
62 | maven-jar-plugin
63 |
64 |
65 | org.apache.maven.plugins
66 | maven-dependency-plugin
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/pippo/src/main/java/nl/jaapcoomans/demo/microframeworks/pippo/PippoApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.pippo;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
4 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
5 | import ro.pippo.core.HttpConstants;
6 | import ro.pippo.core.Pippo;
7 | import ro.pippo.core.route.CorsHandler;
8 | import ro.pippo.core.route.RouteContext;
9 |
10 | public class PippoApplication {
11 | private static final int PORT = 8080;
12 |
13 | public static void main(String[] args) {
14 | Pippo pippo = new Pippo();
15 | pippo.getServer().getSettings().host("0.0.0.0");
16 | pippo.getServer().setPort(PORT);
17 |
18 | pippo.ANY("/.*", createCorsHandler());
19 | pippo.GET("/hello", PippoApplication::helloWorld);
20 | pippo.GET("/hello/{name}", PippoApplication::hello);
21 |
22 | var todoRestController = createTodoBackend();
23 | todoRestController.initializeRoutes(pippo);
24 |
25 | pippo.start();
26 | }
27 |
28 | private static CorsHandler createCorsHandler() {
29 | var corsHandler = new CorsHandler("*");
30 | corsHandler.allowHeaders(HttpConstants.Header.CONTENT_TYPE);
31 | corsHandler.allowMethods("GET,POST,PATCH,DELETE");
32 |
33 | return corsHandler;
34 | }
35 |
36 | private static void initializeCors(Pippo pippo) {
37 | var corsHandler = new CorsHandler("*");
38 | corsHandler.allowHeaders(HttpConstants.Header.CONTENT_TYPE);
39 | corsHandler.allowMethods("GET,POST,PATCH,DELETE");
40 |
41 | pippo.ANY("/.*", corsHandler);
42 | }
43 |
44 | private static TodoRestController createTodoBackend() {
45 | var todoRepository = new InMemoryTodoRepository();
46 | var todoService = new TodoService(todoRepository);
47 |
48 | return new TodoRestController(todoService, "http://localhost:8080/todos");
49 | }
50 |
51 | private static void helloWorld(RouteContext context) {
52 | context.text().send("Hello World!");
53 | }
54 |
55 | private static void hello(RouteContext context) {
56 | var name = context.getParameter("name").toString();
57 | context.text().send(String.format("Hello, %s!", capitalize(name)));
58 | }
59 |
60 | private static String capitalize(String name) {
61 | if (name.length() < 2) {
62 | return name.toUpperCase();
63 | } else {
64 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/todo-backend-test/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | todo-backend-test
8 |
9 |
10 | parent
11 | nl.jaapcoomans.demo.microframeworks
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 1.15.3
17 |
18 |
19 |
20 |
21 | org.slf4j
22 | slf4j-simple
23 | test
24 |
25 |
26 |
27 | org.junit.jupiter
28 | junit-jupiter-api
29 | ${junit.version}
30 | test
31 |
32 |
33 | org.junit.jupiter
34 | junit-jupiter-engine
35 | ${junit.version}
36 | test
37 |
38 |
39 | io.rest-assured
40 | rest-assured
41 | 4.3.3
42 | test
43 |
44 |
45 | org.assertj
46 | assertj-core
47 | ${assertj.version}
48 | test
49 |
50 |
51 | org.testcontainers
52 | testcontainers
53 | ${testcontainers.version}
54 | test
55 |
56 |
57 | org.hamcrest
58 | hamcrest-core
59 |
60 |
61 |
62 |
63 | org.testcontainers
64 | junit-jupiter
65 | ${testcontainers.version}
66 | test
67 |
68 |
69 |
--------------------------------------------------------------------------------
/helidon-se/src/main/java/nl/jaapcoomans/demo/microframeworks/helidon/se/HelidonApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.helidon.se;
2 |
3 | import io.helidon.media.jackson.JacksonSupport;
4 | import io.helidon.webserver.Routing;
5 | import io.helidon.webserver.WebServer;
6 | import io.helidon.webserver.cors.CorsSupport;
7 | import io.helidon.webserver.cors.CrossOriginConfig;
8 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
9 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
10 |
11 | public class HelidonApplication {
12 | public static void main(final String[] args) {
13 | long startTime = System.currentTimeMillis();
14 | var server = WebServer.builder(HelidonApplication::createRouting)
15 | .addMediaSupport(JacksonSupport.create())
16 | .port(8080).build();
17 |
18 | server.start()
19 | .thenAccept(ws -> {
20 | long bootTime = System.currentTimeMillis() - startTime;
21 | System.out.println(
22 | "WEB server is up! http://localhost:" + ws.port() + "/ in " + bootTime + "ms");
23 | ws.whenShutdown().thenRun(()
24 | -> System.out.println("WEB server is DOWN. Good bye!"));
25 | })
26 | .exceptionally(t -> {
27 | System.err.println("Startup failed: " + t.getMessage());
28 | t.printStackTrace(System.err);
29 | return null;
30 | });
31 | }
32 |
33 | private static Routing createRouting() {
34 | HelloWorldRestController helloWorldRestController = new HelloWorldRestController();
35 |
36 | TodoRestController todoRestController = createTodoBackend();
37 |
38 | return Routing.builder()
39 | .register("/hello", helloWorldRestController)
40 | .register("/todos", createCorsSupport(), todoRestController)
41 | .build();
42 | }
43 |
44 | private static CorsSupport createCorsSupport() {
45 | return CorsSupport.builder()
46 | .addCrossOrigin(CrossOriginConfig.builder()
47 | .allowOrigins("*")
48 | .allowMethods("GET", "POST", "PUT", "DELETE")
49 | .build())
50 | .addCrossOrigin(CrossOriginConfig.create())
51 | .build();
52 | }
53 |
54 | private static TodoRestController createTodoBackend() {
55 | var repository = new InMemoryTodoRepository();
56 | var todoService = new TodoService(repository);
57 |
58 | return new TodoRestController(todoService, "http://localhost:8080/todos");
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/ktor/src/main/kotlin/nl/jaapcoomans/demo/microframeworks/ktor/TodoBackend.kt:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.ktor
2 |
3 | import io.ktor.application.call
4 | import io.ktor.http.HttpStatusCode
5 | import io.ktor.request.receive
6 | import io.ktor.response.respond
7 | import io.ktor.routing.Route
8 | import io.ktor.routing.delete
9 | import io.ktor.routing.get
10 | import io.ktor.routing.patch
11 | import io.ktor.routing.post
12 | import io.ktor.routing.route
13 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand
14 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO
15 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo
16 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo
17 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService
18 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository
19 | import java.util.UUID
20 |
21 | val todoRepository = InMemoryTodoRepository()
22 | val todoService = TodoService(todoRepository)
23 |
24 | fun Route.todoRoutes() {
25 | route("/todos") {
26 | get {
27 | call.respond(todoService.findAll().map { it.wrap() })
28 | }
29 | get("/{id}") {
30 | val id = call.parameters["id"]
31 | val todo = todoService.findById(UUID.fromString(id))
32 | .map { it.wrap() }
33 | .orElse(null)
34 |
35 | when(todo) {
36 | null -> call.respond(HttpStatusCode.NotFound)
37 | else -> call.respond(todo)
38 | }
39 | }
40 | post {
41 | val command = call.receive()
42 | val todo = todoService.createNewTodo(command.title, command.order)
43 | call.respond(todo.wrap())
44 | }
45 | delete {
46 | todoService.deleteAll()
47 | call.respond(HttpStatusCode.NoContent)
48 | }
49 | patch("/{id}") {
50 | val id = call.parameters["id"]
51 | val command = call.receive()
52 |
53 | val todo = todoService.updateTodo(UUID.fromString(id), command).map { it.wrap() }
54 | if (todo.isPresent) {
55 | call.respond(todo.get())
56 | } else {
57 | call.respond(HttpStatusCode.NotFound)
58 | }
59 | }
60 | delete("/{id}") {
61 | val id = call.parameters["id"]
62 | todoService.delete(UUID.fromString(id))
63 | call.respond(HttpStatusCode.NoContent)
64 | }
65 | }
66 | }
67 |
68 | fun Todo.wrap(): TodoDTO {
69 | return TodoDTO.from(this, createUrl())
70 | }
71 |
72 | fun Todo.createUrl(): String {
73 | return "http://localhost:8080/todos/$id"
74 | }
--------------------------------------------------------------------------------
/blade/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | blade
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 2.0.15.RELEASE
17 | 2.13.4.2
18 |
19 |
20 |
21 |
22 | com.bladejava
23 | blade-mvc
24 | ${blade.version}
25 |
26 |
27 |
28 |
29 | nl.jaapcoomans.demo.microframeworks
30 | todo-backend
31 | 0.0.1-SNAPSHOT
32 |
33 |
34 |
35 |
36 | com.fasterxml.jackson.core
37 | jackson-databind
38 | ${jackson.version}
39 |
40 |
41 |
42 |
43 | org.slf4j
44 | slf4j-simple
45 |
46 |
47 |
48 |
49 | org.junit.jupiter
50 | junit-jupiter-api
51 |
52 |
53 | org.junit.jupiter
54 | junit-jupiter-engine
55 |
56 |
57 | org.mockito
58 | mockito-junit-jupiter
59 |
60 |
61 | org.assertj
62 | assertj-core
63 |
64 |
65 |
66 |
67 |
68 |
69 | org.apache.maven.plugins
70 | maven-jar-plugin
71 |
72 |
73 | org.apache.maven.plugins
74 | maven-dependency-plugin
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/pippo/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | pippo
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 1.13.1
17 |
18 |
19 |
20 |
21 | ro.pippo
22 | pippo-core
23 | ${pippo.version}
24 |
25 |
26 | ro.pippo
27 | pippo-jetty
28 | ${pippo.version}
29 |
30 |
31 | ro.pippo
32 | pippo-jackson
33 | ${pippo.version}
34 |
35 |
36 |
37 |
38 | nl.jaapcoomans.demo.microframeworks
39 | todo-backend
40 | 0.0.1-SNAPSHOT
41 |
42 |
43 |
44 |
45 | org.slf4j
46 | slf4j-simple
47 |
48 |
49 |
50 |
51 | org.junit.jupiter
52 | junit-jupiter-api
53 |
54 |
55 | org.junit.jupiter
56 | junit-jupiter-engine
57 |
58 |
59 | org.mockito
60 | mockito-junit-jupiter
61 |
62 |
63 | org.assertj
64 | assertj-core
65 |
66 |
67 |
68 |
69 |
70 |
71 | org.apache.maven.plugins
72 | maven-jar-plugin
73 |
74 |
75 | org.apache.maven.plugins
76 | maven-dependency-plugin
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/jooby/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | jooby
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 2.9.6
17 |
18 |
19 |
20 |
21 |
22 | io.jooby
23 | jooby-bom
24 | ${jooby.version}
25 | pom
26 | import
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | io.jooby
35 | jooby-netty
36 |
37 |
38 | io.jooby
39 | jooby-jackson
40 |
41 |
42 |
43 |
44 | nl.jaapcoomans.demo.microframeworks
45 | todo-backend
46 | 0.0.1-SNAPSHOT
47 |
48 |
49 |
50 |
51 | org.slf4j
52 | slf4j-simple
53 |
54 |
55 |
56 |
57 | org.junit.jupiter
58 | junit-jupiter-api
59 |
60 |
61 | org.junit.jupiter
62 | junit-jupiter-engine
63 |
64 |
65 | org.mockito
66 | mockito-junit-jupiter
67 |
68 |
69 | org.assertj
70 | assertj-core
71 |
72 |
73 |
74 |
75 |
76 |
77 | org.apache.maven.plugins
78 | maven-jar-plugin
79 |
80 |
81 | org.apache.maven.plugins
82 | maven-dependency-plugin
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/http4k/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | http4k
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 4.9.1.0
17 |
18 |
19 |
20 |
21 |
22 | org.http4k
23 | http4k-core
24 | ${http4k.version}
25 |
26 |
27 | org.http4k
28 | http4k-server-jetty
29 | ${http4k.version}
30 |
31 |
32 | org.http4k
33 | http4k-format-jackson
34 | ${http4k.version}
35 |
36 |
37 |
38 |
39 | nl.jaapcoomans.demo.microframeworks
40 | todo-backend
41 | 0.0.1-SNAPSHOT
42 |
43 |
44 |
45 |
46 | org.jetbrains.kotlin
47 | kotlin-stdlib
48 |
49 |
50 |
51 |
52 | org.slf4j
53 | slf4j-simple
54 |
55 |
56 |
57 |
58 | org.junit.jupiter
59 | junit-jupiter-api
60 |
61 |
62 | org.junit.jupiter
63 | junit-jupiter-engine
64 |
65 |
66 |
67 |
68 | src/main/kotlin
69 |
70 |
71 |
72 | org.jetbrains.kotlin
73 | kotlin-maven-plugin
74 |
75 |
76 | org.apache.maven.plugins
77 | maven-jar-plugin
78 |
79 |
80 | org.apache.maven.plugins
81 | maven-dependency-plugin
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/dropwizard/src/main/java/nl/jaapcoomans/microframeworks/dropwizard/TodoRestController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.dropwizard;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
4 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
5 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
6 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
7 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
8 |
9 | import javax.ws.rs.Consumes;
10 | import javax.ws.rs.DELETE;
11 | import javax.ws.rs.GET;
12 | import javax.ws.rs.PATCH;
13 | import javax.ws.rs.POST;
14 | import javax.ws.rs.Path;
15 | import javax.ws.rs.PathParam;
16 | import javax.ws.rs.Produces;
17 | import javax.ws.rs.core.MediaType;
18 | import javax.ws.rs.core.Response;
19 | import java.util.List;
20 | import java.util.UUID;
21 | import java.util.stream.Collectors;
22 |
23 | @Path("/todos")
24 | public class TodoRestController {
25 | private TodoService todoService;
26 | private String baseUrl;
27 |
28 | TodoRestController(TodoService todoService, String baseUrl) {
29 | this.todoService = todoService;
30 | this.baseUrl = baseUrl;
31 | }
32 |
33 | @GET
34 | @Produces(MediaType.APPLICATION_JSON)
35 | public List getAll() {
36 | return this.todoService.findAll().stream()
37 | .map(this::wrap)
38 | .collect(Collectors.toList());
39 | }
40 |
41 | @GET
42 | @Path("/{id}")
43 | @Produces(MediaType.APPLICATION_JSON)
44 | public Response getTodo(@PathParam("id") String id) {
45 | return this.todoService.findById(UUID.fromString(id))
46 | .map(this::wrap)
47 | .map(body -> Response.ok(body).build())
48 | .orElse(Response.status(Response.Status.NOT_FOUND).build());
49 | }
50 |
51 | @POST
52 | @Produces(MediaType.APPLICATION_JSON)
53 | @Consumes(MediaType.APPLICATION_JSON)
54 | public TodoDTO createTodo(CreateTodoCommand command) {
55 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
56 | return this.wrap(result);
57 | }
58 |
59 | @DELETE
60 | public Response deleteAll() {
61 | this.todoService.deleteAll();
62 | return Response.noContent().build();
63 | }
64 |
65 | @PATCH
66 | @Path("/{id}")
67 | @Produces(MediaType.APPLICATION_JSON)
68 | @Consumes(MediaType.APPLICATION_JSON)
69 | public TodoDTO patchTodo(@PathParam("id") String id, PartialTodo command) {
70 | return this.todoService.updateTodo(UUID.fromString(id), command)
71 | .map(this::wrap)
72 | .orElse(null);
73 | }
74 |
75 | @DELETE
76 | @Path("/{id}")
77 | public Response deleteTodo(@PathParam("id") UUID id) {
78 | this.todoService.delete(id);
79 | return Response.noContent().build();
80 | }
81 |
82 | private TodoDTO wrap(Todo todo) {
83 | return TodoDTO.from(todo, createUrl(todo));
84 | }
85 |
86 | private String createUrl(Todo todo) {
87 | return this.baseUrl + "/" + todo.getId().toString();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/ratpack/src/main/java/nl/jaapcoomans/demo/microframeworks/ratpack/RatpackApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.ratpack;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
4 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import ratpack.handling.Context;
8 | import ratpack.http.HttpMethod;
9 | import ratpack.http.Status;
10 | import ratpack.server.RatpackServer;
11 | import ratpack.server.RatpackServerSpec;
12 | import ratpack.server.ServerConfig;
13 |
14 | public class RatpackApplication {
15 | private static final Logger LOGGER = LoggerFactory.getLogger(RatpackApplication.class);
16 | private static final int PORT = 8080;
17 |
18 | public static void main(String[] args) throws Exception {
19 | long startTime = System.currentTimeMillis();
20 |
21 | RatpackServer.start(RatpackApplication::init);
22 |
23 | LOGGER.info("Started in {} ms", System.currentTimeMillis() - startTime);
24 | }
25 |
26 | private static void init(RatpackServerSpec server) {
27 | var todoRestController = createTodoBackend();
28 |
29 | server.serverConfig(ServerConfig.embedded().port(PORT))
30 | .handlers(chain -> {
31 | chain.all(RatpackApplication::cors)
32 | .get("hello", RatpackApplication::helloWorld)
33 | .get("hello/:name", RatpackApplication::hello);
34 | todoRestController.initializeEndpoints(chain);
35 | });
36 | }
37 |
38 | private static TodoRestController createTodoBackend() {
39 | var todoRepository = new InMemoryTodoRepository();
40 | var todoService = new TodoService(todoRepository);
41 | return new TodoRestController(todoService, "http://localhost:8080/todos");
42 | }
43 |
44 | private static void cors(Context context) {
45 | context.header("Access-Control-Allow-Origin", "*");
46 | if (context.getRequest().getMethod() == HttpMethod.OPTIONS) {
47 | context.header("Access-Control-Allow-Methods", "GET,POST,PATCH,DELETE");
48 | context.header("Access-Control-Allow-Headers", "content-type");
49 | context.getResponse().status(Status.OK).send();
50 | } else {
51 | context.next();
52 | }
53 | }
54 |
55 | private static void helloWorld(Context context) {
56 | context.getResponse()
57 | .contentType("text/plain")
58 | .send("Hello World");
59 | }
60 |
61 | private static void hello(Context context) {
62 | var name = context.getPathTokens().get("name");
63 | context.getResponse()
64 | .contentType("text/plain")
65 | .send(String.format("Hello, %s!", capitalize(name)));
66 | }
67 |
68 | private static String capitalize(String name) {
69 | if (name.length() < 2) {
70 | return name.toUpperCase();
71 | } else {
72 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/http4k/src/main/kotlin/nl/jaapcoomans/demo/microframeworks/http4k/TodoRestController.kt:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.http4k
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand
4 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO
5 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo
6 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo
7 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService
8 | import org.http4k.core.ContentType
9 | import org.http4k.core.Request
10 | import org.http4k.core.Response
11 | import org.http4k.core.Status
12 | import org.http4k.format.Jackson
13 | import org.http4k.format.Jackson.asJsonObject
14 | import org.http4k.routing.path
15 | import java.util.UUID
16 |
17 | class TodoRestController(val todoService: TodoService) {
18 | private val json = Jackson
19 |
20 | fun getAll(req: Request): Response {
21 | val todos = todoService.findAll().map { it.wrap() }
22 | return Response(Status.OK)
23 | .header("Content-Type", ContentType.APPLICATION_JSON.value)
24 | .body(todos.asJsonObject().toPrettyString())
25 | }
26 |
27 | fun createTodo(req: Request): Response {
28 | val command = json.asA(req.bodyString(), CreateTodoCommand::class)
29 |
30 | val todo = todoService.createNewTodo(command.title, command.order)
31 |
32 | return Response(Status.OK)
33 | .header("Content-Type", ContentType.APPLICATION_JSON.value)
34 | .body(todo.wrap().asJsonObject().toPrettyString())
35 | }
36 |
37 | fun getTodo(req: Request): Response {
38 | val id = req.path("id")
39 | val todo = todoService.findById(UUID.fromString(id))
40 | return if (todo.isPresent) {
41 | Response(Status.OK)
42 | .header("Content-Type", ContentType.APPLICATION_JSON.value)
43 | .body(todo.get().wrap().asJsonObject().toPrettyString())
44 | } else {
45 | Response(Status.NOT_FOUND)
46 | }
47 | }
48 |
49 | fun patchTodo(req: Request): Response {
50 | val id = req.path("id")
51 | val command = json.asA(req.bodyString(), PartialTodo::class)
52 |
53 | val todo = todoService.updateTodo(UUID.fromString(id), command)
54 | return if (todo.isPresent) {
55 | Response(Status.OK)
56 | .header("Content-Type", ContentType.APPLICATION_JSON.value)
57 | .body(todo.get().wrap().asJsonObject().toPrettyString())
58 | } else {
59 | Response(Status.NOT_FOUND)
60 | }
61 | }
62 |
63 | fun deleteTodo(req: Request): Response {
64 | val id = req.path("id")
65 | todoService.delete(UUID.fromString(id))
66 | return Response(Status.NO_CONTENT)
67 | }
68 |
69 | fun deleteAll(req: Request): Response {
70 | todoService.deleteAll()
71 | return Response(Status.NO_CONTENT)
72 | }
73 |
74 | private fun Todo.wrap(): TodoDTO {
75 | return TodoDTO.from(this, createUrl())
76 | }
77 |
78 | private fun Todo.createUrl(): String {
79 | return "http://localhost:8080/todos/$id"
80 | }
81 | }
--------------------------------------------------------------------------------
/spark/src/main/java/nl/jaapcoomans/microframeworks/spark/SparkApplication.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.spark;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
4 | import nl.jaapcoomans.demo.microframeworks.todo.peristsence.InMemoryTodoRepository;
5 | import spark.Request;
6 | import spark.Response;
7 |
8 | import static spark.Spark.before;
9 | import static spark.Spark.delete;
10 | import static spark.Spark.get;
11 | import static spark.Spark.options;
12 | import static spark.Spark.patch;
13 | import static spark.Spark.path;
14 | import static spark.Spark.port;
15 | import static spark.Spark.post;
16 |
17 | public class SparkApplication {
18 | private static final int PORT = 8080;
19 |
20 | public static void main(String[] args) {
21 | port(PORT);
22 | addCORS();
23 |
24 | get("/hello", SparkApplication::helloWorld);
25 | get("/hello/:name", SparkApplication::hello);
26 |
27 | setupTodoBackend();
28 | }
29 |
30 | private static void setupTodoBackend() {
31 | var todoRepository = new InMemoryTodoRepository();
32 | var todoService = new TodoService(todoRepository);
33 | var todoRestController = new TodoRestController(todoService, "http://localhost:8080/todos");
34 |
35 | var jsonTransformer = new JacksonResponseTransformer();
36 |
37 | path("/todos", () -> {
38 | get("", todoRestController::getAll, jsonTransformer);
39 | post("", todoRestController::createTodo, jsonTransformer);
40 | delete("", todoRestController::deleteAll);
41 | path("/:id", () -> {
42 | get("", todoRestController::getTodo, jsonTransformer);
43 | delete("", todoRestController::deleteTodo);
44 | patch("", todoRestController::patchTodo, jsonTransformer);
45 | });
46 | });
47 | }
48 |
49 | private static String helloWorld(Request request, Response response) {
50 | return "Hello World!";
51 | }
52 |
53 | private static String hello(Request request, Response response) {
54 | return String.format("Hello, %s!", capitalize(request.params("name")));
55 | }
56 |
57 | private static String capitalize(String name) {
58 | if (name.length() < 2) {
59 | return name.toUpperCase();
60 | } else {
61 | return name.substring(0, 1).toUpperCase() + name.substring(1).toLowerCase();
62 | }
63 | }
64 |
65 | private static void addCORS() {
66 | before((request, response) -> {
67 | response.header("Access-Control-Allow-Origin", "*");
68 | });
69 |
70 | options("/*", (request, response) -> {
71 | String accessControlRequestHeaders = request.headers("Access-Control-Request-Headers");
72 | if (accessControlRequestHeaders != null) {
73 | response.header("Access-Control-Allow-Headers", accessControlRequestHeaders);
74 | }
75 |
76 | String accessControlRequestMethod = request.headers("Access-Control-Request-Method");
77 | if (accessControlRequestMethod != null) {
78 | response.header("Access-Control-Allow-Methods", accessControlRequestMethod);
79 | }
80 |
81 | return "OK";
82 | });
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/blade/src/main/java/nl/jaapcoomans/microframeworks/blade/TodoRestController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.blade;
2 |
3 | import com.blade.Blade;
4 | import com.blade.mvc.RouteContext;
5 | import com.blade.mvc.http.HttpMethod;
6 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
7 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
8 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
9 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
10 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
11 |
12 | import java.util.List;
13 | import java.util.UUID;
14 | import java.util.stream.Collectors;
15 |
16 | class TodoRestController {
17 | private static final String ID_PATH_PARAM = "id";
18 |
19 | private TodoService todoService;
20 | private String baseUrl;
21 |
22 | TodoRestController(TodoService todoService, String baseUrl) {
23 | this.todoService = todoService;
24 | this.baseUrl = baseUrl;
25 | }
26 |
27 | void initializeRoutes(Blade application) {
28 | application.contextPath("/todos")
29 | .get("/", this::getAll)
30 | .post("/", this::createTodo)
31 | .delete("/", this::deleteAll)
32 | .get("/:id", this::getTodo)
33 | .delete("/:id", this::deleteTodo)
34 | .routeMatcher().addRoute("/:id", this::patchTodo, HttpMethod.PATCH);
35 | }
36 |
37 | private void getAll(RouteContext context) {
38 | List todos = this.todoService.findAll().stream()
39 | .map(this::wrap)
40 | .collect(Collectors.toList());
41 |
42 | context.json(todos);
43 | }
44 |
45 | private void getTodo(RouteContext context) {
46 | UUID id = UUID.fromString(context.pathString(ID_PATH_PARAM));
47 |
48 | this.todoService.findById(id)
49 | .map(this::wrap)
50 | .ifPresentOrElse(context::json, () -> context.status(404));
51 | }
52 |
53 | private void createTodo(RouteContext context) {
54 | var command = context.request().bindWithBody(CreateTodoCommand.class);
55 |
56 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
57 | context.json(this.wrap(result));
58 | }
59 |
60 | private void deleteAll(RouteContext context) {
61 | this.todoService.deleteAll();
62 | context.status(204);
63 | }
64 |
65 | private void patchTodo(RouteContext context) {
66 | UUID id = UUID.fromString(context.pathString(ID_PATH_PARAM));
67 |
68 | var command = context.request().bindWithBody(PartialTodo.class);
69 |
70 | this.todoService.updateTodo(id, command)
71 | .map(this::wrap)
72 | .ifPresentOrElse(context::json, () -> context.status(404));
73 | }
74 |
75 | private void deleteTodo(RouteContext context) {
76 | UUID id = UUID.fromString(context.pathString(ID_PATH_PARAM));
77 | this.todoService.delete(id);
78 | context.status(204);
79 | }
80 |
81 | private TodoDTO wrap(Todo todo) {
82 | return TodoDTO.from(todo, createUrl(todo));
83 | }
84 |
85 | private String createUrl(Todo todo) {
86 | return this.baseUrl + "/" + todo.getId().toString();
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/kumuluzee/src/main/java/nl/jaapcoomans/demo/microframeworks/kumuluzee/TodoController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.kumuluzee;
2 |
3 | import com.kumuluz.ee.cors.annotations.CrossOrigin;
4 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
5 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
6 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
7 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
8 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
9 |
10 | import javax.inject.Inject;
11 | import javax.ws.rs.Consumes;
12 | import javax.ws.rs.DELETE;
13 | import javax.ws.rs.GET;
14 | import javax.ws.rs.PATCH;
15 | import javax.ws.rs.POST;
16 | import javax.ws.rs.Path;
17 | import javax.ws.rs.PathParam;
18 | import javax.ws.rs.Produces;
19 | import javax.ws.rs.core.MediaType;
20 | import javax.ws.rs.core.Response;
21 | import java.util.List;
22 | import java.util.UUID;
23 | import java.util.stream.Collectors;
24 |
25 | @Path("/todos")
26 | @CrossOrigin(allowOrigin = "*", allowGenericHttpRequests = true)
27 | public class TodoController {
28 | private TodoService todoService;
29 |
30 | private String baseUrl = "http://localhost:8080/todos";
31 |
32 | @Inject
33 | public TodoController(TodoService todoService) {
34 | this.todoService = todoService;
35 | }
36 |
37 | @GET
38 | @Produces(MediaType.APPLICATION_JSON)
39 | public List getAll() {
40 | return this.todoService.findAll().stream()
41 | .map(this::wrap)
42 | .collect(Collectors.toList());
43 | }
44 |
45 | @GET
46 | @Path("/{id}")
47 | @Produces(MediaType.APPLICATION_JSON)
48 | public Response getTodo(@PathParam("id") String id) {
49 | return this.todoService.findById(UUID.fromString(id))
50 | .map(this::wrap)
51 | .map(body -> Response.ok(body).build())
52 | .orElse(Response.status(Response.Status.NOT_FOUND).build());
53 | }
54 |
55 | @POST
56 | @Produces(MediaType.APPLICATION_JSON)
57 | @Consumes(MediaType.APPLICATION_JSON)
58 | public TodoDTO createTodo(CreateTodoCommand command) {
59 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
60 | return this.wrap(result);
61 | }
62 |
63 | @DELETE
64 | public Response deleteAll() {
65 | this.todoService.deleteAll();
66 | return Response.noContent().build();
67 | }
68 |
69 | @PATCH
70 | @Path("/{id}")
71 | @Produces(MediaType.APPLICATION_JSON)
72 | @Consumes(MediaType.APPLICATION_JSON)
73 | public TodoDTO patchTodo(@PathParam("id") String id, PartialTodo command) {
74 | return this.todoService.updateTodo(UUID.fromString(id), command)
75 | .map(this::wrap)
76 | .orElse(null);
77 | }
78 |
79 | @DELETE
80 | @Path("/{id}")
81 | public Response deleteTodo(@PathParam("id") UUID id) {
82 | this.todoService.delete(id);
83 | return Response.noContent().build();
84 | }
85 |
86 | private TodoDTO wrap(Todo todo) {
87 | return TodoDTO.from(todo, createUrl(todo));
88 | }
89 |
90 | private String createUrl(Todo todo) {
91 | return this.baseUrl + "/" + todo.getId().toString();
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/ktor/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | ktor
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 1.5.4
17 |
18 |
19 |
20 |
21 | jcenter
22 | https://jcenter.bintray.com
23 |
24 |
25 |
26 |
27 |
28 |
29 | io.ktor
30 | ktor-server-core
31 | ${ktor.version}
32 |
33 |
34 | io.ktor
35 | ktor-server-netty
36 | ${ktor.version}
37 |
38 |
39 | io.ktor
40 | ktor-jackson
41 | ${ktor.version}
42 |
43 |
44 |
45 |
46 | nl.jaapcoomans.demo.microframeworks
47 | todo-backend
48 | 0.0.1-SNAPSHOT
49 |
50 |
51 |
52 |
53 | org.jetbrains.kotlin
54 | kotlin-stdlib
55 |
56 |
57 |
58 |
59 | org.slf4j
60 | slf4j-simple
61 |
62 |
63 |
64 |
65 | org.junit.jupiter
66 | junit-jupiter-api
67 |
68 |
69 | org.junit.jupiter
70 | junit-jupiter-engine
71 |
72 |
73 |
74 |
75 | src/main/kotlin
76 | src/test/kotlin
77 |
78 |
79 |
80 | org.jetbrains.kotlin
81 | kotlin-maven-plugin
82 |
83 |
84 | org.apache.maven.plugins
85 | maven-jar-plugin
86 |
87 |
88 | org.apache.maven.plugins
89 | maven-dependency-plugin
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/pippo/src/main/java/nl/jaapcoomans/demo/microframeworks/pippo/TodoRestController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.pippo;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
4 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
5 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
6 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
7 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
8 | import ro.pippo.core.Pippo;
9 | import ro.pippo.core.route.RouteContext;
10 |
11 | import java.util.List;
12 | import java.util.UUID;
13 | import java.util.stream.Collectors;
14 |
15 | public class TodoRestController {
16 | private static final String ID_PATH_PARAM = "id";
17 |
18 | private TodoService todoService;
19 | private String baseUrl;
20 |
21 | TodoRestController(TodoService todoService, String baseUrl) {
22 | this.todoService = todoService;
23 | this.baseUrl = baseUrl;
24 | }
25 |
26 | void initializeRoutes(Pippo pippo) {
27 | pippo.GET("/todos", this::getAll);
28 | pippo.POST("/todos", this::createTodo);
29 | pippo.DELETE("/todos", this::deleteAll);
30 | pippo.GET("/todos/{id}", this::getTodo);
31 | pippo.PATCH("/todos/{id}", this::patchTodo);
32 | pippo.DELETE("/todos/{id}", this::deleteTodo);
33 | }
34 |
35 | private void getAll(RouteContext context) {
36 | List todos = this.todoService.findAll().stream()
37 | .map(this::wrap)
38 | .collect(Collectors.toList());
39 |
40 | context.json().send(todos);
41 | }
42 |
43 | private void getTodo(RouteContext context) {
44 | UUID id = UUID.fromString(context.getParameter(ID_PATH_PARAM).toString());
45 |
46 | this.todoService.findById(id)
47 | .map(this::wrap)
48 | .ifPresentOrElse(context.json()::send, () -> context.status(404));
49 | }
50 |
51 | private void createTodo(RouteContext context) {
52 | var command = context.createEntityFromBody(CreateTodoCommand.class);
53 |
54 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
55 | context.json().send(this.wrap(result));
56 | }
57 |
58 | private void deleteAll(RouteContext context) {
59 | this.todoService.deleteAll();
60 | context.status(204);
61 | }
62 |
63 | private void patchTodo(RouteContext context) {
64 | var id = UUID.fromString(context.getParameter(ID_PATH_PARAM)
65 | .toString());
66 |
67 | var command = context.createEntityFromBody(PartialTodo.class);
68 |
69 | this.todoService.updateTodo(id, command)
70 | .map(this::wrap)
71 | .ifPresentOrElse(context.json()::send,
72 | () -> context.status(404));
73 | }
74 |
75 | private void deleteTodo(RouteContext context) {
76 | UUID id = UUID.fromString(context.getParameter(ID_PATH_PARAM).toString());
77 | this.todoService.delete(id);
78 | context.status(204);
79 | }
80 |
81 | private TodoDTO wrap(Todo todo) {
82 | return TodoDTO.from(todo, createUrl(todo));
83 | }
84 |
85 | private String createUrl(Todo todo) {
86 | return this.baseUrl + "/" + todo.getId().toString();
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/javalin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | javalin
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 3.13.7
17 | 2.13.4.2
18 |
19 |
20 |
21 |
22 |
23 | io.javalin
24 | javalin
25 | ${javalin.version}
26 |
27 |
28 |
29 |
30 | nl.jaapcoomans.demo.microframeworks
31 | todo-backend
32 | 0.0.1-SNAPSHOT
33 |
34 |
35 |
36 |
37 | org.slf4j
38 | slf4j-simple
39 |
40 |
41 |
42 |
43 | com.fasterxml.jackson.core
44 | jackson-databind
45 | ${jackson.version}
46 |
47 |
48 | com.fasterxml.jackson.datatype
49 | jackson-datatype-jsr310
50 | ${jackson.version}
51 |
52 |
53 | com.fasterxml.jackson.module
54 | jackson-module-parameter-names
55 | ${jackson.version}
56 |
57 |
58 |
59 |
60 | org.junit.jupiter
61 | junit-jupiter-api
62 |
63 |
64 | org.junit.jupiter
65 | junit-jupiter-engine
66 |
67 |
68 | org.mockito
69 | mockito-junit-jupiter
70 |
71 |
72 | org.assertj
73 | assertj-core
74 |
75 |
76 |
77 |
78 |
79 |
80 | org.apache.maven.plugins
81 | maven-jar-plugin
82 |
83 |
84 | org.apache.maven.plugins
85 | maven-dependency-plugin
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/jooby/src/main/java/nl/jaapcoomans/demo/microframeworks/jooby/TodoRestController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.jooby;
2 |
3 | import io.jooby.Context;
4 | import io.jooby.Jooby;
5 | import io.jooby.StatusCode;
6 | import io.jooby.exception.StatusCodeException;
7 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
8 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
9 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
10 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
11 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
12 |
13 | import javax.annotation.Nonnull;
14 | import java.util.List;
15 | import java.util.UUID;
16 | import java.util.stream.Collectors;
17 |
18 | public class TodoRestController {
19 | private static final String ID_PATH_PARAM = "id";
20 |
21 | private TodoService todoService;
22 | private String baseUrl;
23 |
24 | TodoRestController(TodoService todoService, String baseUrl) {
25 | this.todoService = todoService;
26 | this.baseUrl = baseUrl;
27 | }
28 |
29 | void initializeRoutes(Jooby app) {
30 | app.get("/todos", this::getAll);
31 | app.post("/todos", this::createTodo);
32 | app.delete("/todos", this::deleteAll);
33 | app.get("/todos/{id}", this::getTodo);
34 | app.patch("/todos/{id}", this::patchTodo);
35 | app.delete("/todos/{id}", this::deleteTodo);
36 | }
37 |
38 | @Nonnull
39 | private List getAll(Context context) {
40 | return this.todoService.findAll().stream()
41 | .map(this::wrap)
42 | .collect(Collectors.toList());
43 | }
44 |
45 | @Nonnull
46 | private TodoDTO getTodo(Context context) {
47 | UUID id = UUID.fromString(context.path(ID_PATH_PARAM).value());
48 |
49 | return this.todoService.findById(id)
50 | .map(this::wrap)
51 | .orElseThrow(() -> new StatusCodeException(StatusCode.NOT_FOUND));
52 | }
53 |
54 | private TodoDTO createTodo(Context context) {
55 | var command = context.body(CreateTodoCommand.class);
56 |
57 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
58 | return this.wrap(result);
59 | }
60 |
61 | private Context deleteAll(Context context) {
62 | this.todoService.deleteAll();
63 | context.send(StatusCode.NO_CONTENT);
64 | return context;
65 | }
66 |
67 | @Nonnull
68 | private TodoDTO patchTodo(Context context) {
69 | UUID id = UUID.fromString(context.path(ID_PATH_PARAM).value());
70 |
71 | var command = context.body(PartialTodo.class);
72 |
73 | return this.todoService.updateTodo(id, command)
74 | .map(this::wrap)
75 | .orElseThrow(() -> new StatusCodeException(StatusCode.NOT_FOUND));
76 | }
77 |
78 | private Context deleteTodo(Context context) {
79 | UUID id = UUID.fromString(context.path(ID_PATH_PARAM).value());
80 | this.todoService.delete(id);
81 | context.send(StatusCode.NO_CONTENT);
82 | return context;
83 | }
84 |
85 | private TodoDTO wrap(Todo todo) {
86 | return TodoDTO.from(todo, createUrl(todo));
87 | }
88 |
89 | private String createUrl(Todo todo) {
90 | return this.baseUrl + "/" + todo.getId().toString();
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/javalin/src/main/java/nl/jaapcoomans/microframeworks/javalin/TodoRestController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.javalin;
2 |
3 | import io.javalin.apibuilder.EndpointGroup;
4 | import io.javalin.http.Context;
5 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
6 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
7 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
8 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
9 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
10 |
11 | import java.util.List;
12 | import java.util.UUID;
13 | import java.util.stream.Collectors;
14 |
15 | import static io.javalin.apibuilder.ApiBuilder.delete;
16 | import static io.javalin.apibuilder.ApiBuilder.get;
17 | import static io.javalin.apibuilder.ApiBuilder.patch;
18 | import static io.javalin.apibuilder.ApiBuilder.post;
19 |
20 | class TodoRestController {
21 | private static final String ID_PATH_PARAM = "id";
22 | private static final String ID_PATH = "/:" + ID_PATH_PARAM;
23 |
24 | private TodoService todoService;
25 | private String baseUrl;
26 |
27 | TodoRestController(TodoService todoService, String baseUrl) {
28 | this.todoService = todoService;
29 | this.baseUrl = baseUrl;
30 | }
31 |
32 | EndpointGroup defineEndpoints() {
33 | return () -> {
34 | get(this::getAll);
35 | post(this::createTodo);
36 | delete(this::deleteAll);
37 | get(ID_PATH, this::getTodo);
38 | patch(ID_PATH, this::patchTodo);
39 | delete(ID_PATH, this::deleteTodo);
40 | };
41 | }
42 |
43 | void getAll(Context context) {
44 | List todos = this.todoService.findAll().stream()
45 | .map(this::wrap)
46 | .collect(Collectors.toList());
47 |
48 | context.json(todos);
49 | }
50 |
51 | void getTodo(Context context) {
52 | UUID id = UUID.fromString(context.pathParam(ID_PATH_PARAM));
53 |
54 | this.todoService.findById(id)
55 | .map(this::wrap)
56 | .ifPresentOrElse(context::json, () -> context.status(404));
57 | }
58 |
59 | void createTodo(Context context) {
60 | var command = context.bodyAsClass(CreateTodoCommand.class);
61 |
62 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
63 | context.json(this.wrap(result));
64 | }
65 |
66 | void deleteAll(Context context) {
67 | this.todoService.deleteAll();
68 | context.status(204);
69 | }
70 |
71 | void patchTodo(Context context) {
72 | UUID id = UUID.fromString(context.pathParam(ID_PATH_PARAM));
73 |
74 | var command = context.bodyAsClass(PartialTodo.class);
75 |
76 | this.todoService.updateTodo(id, command)
77 | .map(this::wrap)
78 | .ifPresentOrElse(context::json, () -> context.status(404));
79 | }
80 |
81 | void deleteTodo(Context context) {
82 | UUID id = UUID.fromString(context.pathParam(ID_PATH_PARAM));
83 | this.todoService.delete(id);
84 | context.status(204);
85 | }
86 |
87 | private TodoDTO wrap(Todo todo) {
88 | return TodoDTO.from(todo, createUrl(todo));
89 | }
90 |
91 | private String createUrl(Todo todo) {
92 | return this.baseUrl + "/" + todo.getId().toString();
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/micronaut/src/main/java/nl/jaapcoomans/demo/microframeworks/micronaut/TodoController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.micronaut;
2 |
3 | import io.micronaut.context.annotation.Value;
4 | import io.micronaut.http.HttpResponse;
5 | import io.micronaut.http.HttpResponseFactory;
6 | import io.micronaut.http.HttpStatus;
7 | import io.micronaut.http.MediaType;
8 | import io.micronaut.http.annotation.Controller;
9 | import io.micronaut.http.annotation.Delete;
10 | import io.micronaut.http.annotation.Get;
11 | import io.micronaut.http.annotation.Patch;
12 | import io.micronaut.http.annotation.PathVariable;
13 | import io.micronaut.http.annotation.Post;
14 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
15 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
16 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
17 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
18 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
19 |
20 | import javax.inject.Inject;
21 | import java.util.List;
22 | import java.util.Optional;
23 | import java.util.UUID;
24 | import java.util.stream.Collectors;
25 |
26 | @Controller("/todos")
27 | public class TodoController {
28 | private TodoService todoService;
29 | private String baseUrl;
30 |
31 | @Inject
32 | public TodoController(TodoService todoService, @Value("${todos.baseUrl}") String baseUrl) {
33 | this.todoService = todoService;
34 | this.baseUrl = baseUrl;
35 | }
36 |
37 | @Get(produces = MediaType.APPLICATION_JSON)
38 | public List getAll() {
39 | return this.todoService.findAll().stream()
40 | .map(this::wrap)
41 | .collect(Collectors.toList());
42 | }
43 |
44 | @Get(uri = "/{id}", produces = MediaType.APPLICATION_JSON)
45 | public HttpResponse getTodo(@PathVariable String id) {
46 | return this.todoService.findById(UUID.fromString(id))
47 | .map(this::wrap)
48 | .map(HttpResponseFactory.INSTANCE::ok)
49 | .orElse(HttpResponseFactory.INSTANCE.status(HttpStatus.NOT_FOUND));
50 | }
51 |
52 | @Post(produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
53 | public TodoDTO createTodo(CreateTodoCommand command) {
54 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
55 | return this.wrap(result);
56 | }
57 |
58 | @Delete
59 | public HttpResponse deleteAll() {
60 | this.todoService.deleteAll();
61 | return HttpResponseFactory.INSTANCE.status(HttpStatus.NO_CONTENT);
62 | }
63 |
64 | @Patch(uri = "/{id}",
65 | produces = MediaType.APPLICATION_JSON,
66 | consumes = MediaType.APPLICATION_JSON)
67 | public Optional patchTodo(@PathVariable String id,
68 | PartialTodo command) {
69 |
70 | return this.todoService.updateTodo(UUID.fromString(id), command)
71 | .map(this::wrap);
72 | }
73 |
74 | @Delete(uri = "/{id}")
75 | public HttpResponse deleteTodo(@PathVariable UUID id) {
76 | this.todoService.delete(id);
77 | return HttpResponseFactory.INSTANCE.status(HttpStatus.NO_CONTENT);
78 | }
79 |
80 | private TodoDTO wrap(Todo todo) {
81 | return TodoDTO.from(todo, createUrl(todo));
82 | }
83 |
84 | private String createUrl(Todo todo) {
85 | return this.baseUrl + "/" + todo.getId().toString();
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/quarkus/src/main/java/nl/jaapcoomans/microframeworks/quarkus/TodoController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.quarkus;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
4 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
5 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
6 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
7 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
8 |
9 | import javax.enterprise.context.RequestScoped;
10 | import javax.inject.Inject;
11 | import javax.ws.rs.Consumes;
12 | import javax.ws.rs.DELETE;
13 | import javax.ws.rs.GET;
14 | import javax.ws.rs.OPTIONS;
15 | import javax.ws.rs.PATCH;
16 | import javax.ws.rs.POST;
17 | import javax.ws.rs.Path;
18 | import javax.ws.rs.PathParam;
19 | import javax.ws.rs.Produces;
20 | import javax.ws.rs.core.Context;
21 | import javax.ws.rs.core.MediaType;
22 | import javax.ws.rs.core.Response;
23 | import javax.ws.rs.core.UriBuilder;
24 | import javax.ws.rs.core.UriInfo;
25 | import java.util.List;
26 | import java.util.UUID;
27 | import java.util.stream.Collectors;
28 |
29 | @Path("/todos")
30 | public class TodoController {
31 | private final TodoService todoService;
32 |
33 | @Context
34 | private UriInfo uriInfo;
35 |
36 | @Inject
37 | public TodoController(TodoService todoService) {
38 | this.todoService = todoService;
39 | }
40 |
41 | @GET
42 | @Produces(MediaType.APPLICATION_JSON)
43 | public List getAll() {
44 | return this.todoService.findAll().stream()
45 | .map(this::wrap)
46 | .collect(Collectors.toList());
47 | }
48 |
49 | @GET
50 | @Path("/{id}")
51 | @Produces(MediaType.APPLICATION_JSON)
52 | public Response getTodo(@PathParam("id") String id) {
53 | return this.todoService.findById(UUID.fromString(id))
54 | .map(this::wrap)
55 | .map(body -> Response.ok(body).build())
56 | .orElse(Response.status(Response.Status.NOT_FOUND).build());
57 | }
58 |
59 | @POST
60 | @Produces(MediaType.APPLICATION_JSON)
61 | @Consumes(MediaType.APPLICATION_JSON)
62 | public TodoDTO createTodo(CreateTodoCommand command) {
63 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
64 | return this.wrap(result);
65 | }
66 |
67 | @DELETE
68 | public Response deleteAll() {
69 | this.todoService.deleteAll();
70 | return Response.noContent().build();
71 | }
72 |
73 | @PATCH
74 | @Path("/{id}")
75 | @Produces(MediaType.APPLICATION_JSON)
76 | @Consumes(MediaType.APPLICATION_JSON)
77 | public TodoDTO patchTodo(@PathParam("id") String id, PartialTodo command) {
78 | return this.todoService.updateTodo(UUID.fromString(id), command)
79 | .map(this::wrap)
80 | .orElse(null);
81 | }
82 |
83 | @DELETE
84 | @Path("/{id}")
85 | public Response deleteTodo(@PathParam("id") UUID id) {
86 | this.todoService.delete(id);
87 | return Response.noContent().build();
88 | }
89 |
90 | private TodoDTO wrap(Todo todo) {
91 | return TodoDTO.from(todo, createUrl(todo));
92 | }
93 |
94 | private String createUrl(Todo todo) {
95 | return this.uriInfo.getBaseUriBuilder()
96 | .path("todos")
97 | .path(todo.getId().toString())
98 | .build()
99 | .toString();
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/spark/src/main/java/nl/jaapcoomans/microframeworks/spark/TodoRestController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.spark;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
5 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
6 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
7 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
8 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
9 | import org.eclipse.jetty.http.HttpStatus;
10 | import spark.Request;
11 | import spark.Response;
12 |
13 | import java.io.IOException;
14 | import java.util.List;
15 | import java.util.Optional;
16 | import java.util.UUID;
17 | import java.util.stream.Collectors;
18 |
19 | class TodoRestController {
20 | private static final String ID_PATH_PARAM = "id";
21 |
22 | private TodoService todoService;
23 | private String baseUrl;
24 |
25 | private ObjectMapper objectMapper = new ObjectMapper();
26 |
27 | TodoRestController(TodoService todoService, String baseUrl) {
28 | this.todoService = todoService;
29 | this.baseUrl = baseUrl;
30 | }
31 |
32 | List getAll(Request request, Response response) {
33 | response.header("Content-Type", "application/json");
34 |
35 | return this.todoService.findAll().stream()
36 | .map(this::wrap)
37 | .collect(Collectors.toList());
38 | }
39 |
40 |
41 | Optional getTodo(Request request, Response response) {
42 | UUID id = UUID.fromString(request.params(ID_PATH_PARAM));
43 |
44 | response.header("Content-Type", "application/json");
45 |
46 | var result = this.todoService.findById(id)
47 | .map(this::wrap);
48 |
49 | if (result.isEmpty()) {
50 | response.status(404);
51 | }
52 |
53 | return result;
54 | }
55 |
56 |
57 | TodoDTO createTodo(Request request, Response response) throws Exception {
58 | var command = deserialize(request.body(), CreateTodoCommand.class);
59 |
60 | response.header("Content-Type", "application/json");
61 |
62 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
63 | return this.wrap(result);
64 | }
65 |
66 | String deleteAll(Request request, Response response) {
67 | this.todoService.deleteAll();
68 | response.status(HttpStatus.NO_CONTENT_204);
69 | return "";
70 | }
71 |
72 |
73 | Optional patchTodo(Request request, Response response) {
74 | var id = UUID.fromString(request.params(ID_PATH_PARAM));
75 | var command = deserialize(request.body(), PartialTodo.class);
76 |
77 | response.header("Content-Type", "application/json");
78 |
79 | return this.todoService.updateTodo(id, command)
80 | .map(this::wrap);
81 | }
82 |
83 | String deleteTodo(Request request, Response response) {
84 | UUID id = UUID.fromString(request.params(ID_PATH_PARAM));
85 | this.todoService.delete(id);
86 |
87 | response.status(204);
88 | return "";
89 | }
90 |
91 | private T deserialize(String json, Class clazz) {
92 | try {
93 | return objectMapper.readValue(json, clazz);
94 | } catch (IOException e) {
95 | throw new RuntimeException("Failed to serialize to JSON");
96 | }
97 | }
98 |
99 | private TodoDTO wrap(Todo todo) {
100 | return TodoDTO.from(todo, createUrl(todo));
101 | }
102 |
103 | private String createUrl(Todo todo) {
104 | return this.baseUrl + "/" + todo.getId().toString();
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/helidon-se/src/main/java/nl/jaapcoomans/demo/microframeworks/helidon/se/TodoRestController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.helidon.se;
2 |
3 | import io.helidon.common.http.Http;
4 | import io.helidon.webserver.Handler;
5 | import io.helidon.webserver.Routing;
6 | import io.helidon.webserver.ServerRequest;
7 | import io.helidon.webserver.ServerResponse;
8 | import io.helidon.webserver.Service;
9 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
10 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
11 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
12 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
13 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
14 |
15 | import java.util.List;
16 | import java.util.UUID;
17 | import java.util.stream.Collectors;
18 |
19 | import static io.helidon.common.http.Http.Status.NOT_FOUND_404;
20 | import static io.helidon.common.http.Http.Status.NO_CONTENT_204;
21 |
22 | public class TodoRestController implements Service {
23 | private static final String ID_PATH_PARAM = "id";
24 |
25 | private static final Http.RequestMethod PATCH = Http.RequestMethod.create("PATCH");
26 |
27 | private final TodoService todoService;
28 | private final String baseUrl;
29 |
30 | TodoRestController(TodoService todoService, String baseUrl) {
31 | this.todoService = todoService;
32 | this.baseUrl = baseUrl;
33 | }
34 |
35 | @Override
36 | public void update(Routing.Rules rules) {
37 | rules.get("/", this::getAll)
38 | .post("/", Handler.create(CreateTodoCommand.class, this::createTodo))
39 | .delete("/", this::deleteAll)
40 | .get("/{id}", this::getTodo)
41 | .delete("/{id}", this::deleteTodo)
42 | .anyOf(List.of(PATCH), "/{id}", Handler.create(PartialTodo.class, this::patchTodo));
43 | }
44 |
45 | private void getAll(ServerRequest request, ServerResponse response) {
46 | List todos = this.todoService.findAll().stream()
47 | .map(this::wrap)
48 | .collect(Collectors.toList());
49 |
50 | response.send(todos);
51 | }
52 |
53 | private void getTodo(ServerRequest request, ServerResponse response) {
54 | UUID id = UUID.fromString(request.path().param(ID_PATH_PARAM));
55 |
56 | this.todoService.findById(id)
57 | .map(this::wrap)
58 | .ifPresentOrElse(response::send,
59 | () -> response.status(NOT_FOUND_404).send());
60 | }
61 |
62 | private void createTodo(ServerRequest request, ServerResponse response, CreateTodoCommand command) {
63 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
64 | response.send(this.wrap(result));
65 | }
66 |
67 | private void deleteAll(ServerRequest request, ServerResponse response) {
68 | this.todoService.deleteAll();
69 | response.status(NO_CONTENT_204).send();
70 | }
71 |
72 | private void patchTodo(ServerRequest request, ServerResponse response, PartialTodo command) {
73 | UUID id = UUID.fromString(request.path().param(ID_PATH_PARAM));
74 |
75 | this.todoService.updateTodo(id, command)
76 | .map(this::wrap)
77 | .ifPresentOrElse(response::send, () -> response.status(NOT_FOUND_404).send());
78 | }
79 |
80 | private void deleteTodo(ServerRequest request, ServerResponse response) {
81 | UUID id = UUID.fromString(request.path().param(ID_PATH_PARAM));
82 | this.todoService.delete(id);
83 | response.status(NO_CONTENT_204).send();
84 | }
85 |
86 | private TodoDTO wrap(Todo todo) {
87 | return TodoDTO.from(todo, createUrl(todo));
88 | }
89 |
90 | private String createUrl(Todo todo) {
91 | return this.baseUrl + "/" + todo.getId().toString();
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/minijax/src/main/java/nl/jaapcoomans/microframeworks/minijax/TodoController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.minijax;
2 |
3 | import jakarta.inject.Inject;
4 | import jakarta.ws.rs.Consumes;
5 | import jakarta.ws.rs.DELETE;
6 | import jakarta.ws.rs.GET;
7 | import jakarta.ws.rs.OPTIONS;
8 | import jakarta.ws.rs.PATCH;
9 | import jakarta.ws.rs.POST;
10 | import jakarta.ws.rs.Path;
11 | import jakarta.ws.rs.PathParam;
12 | import jakarta.ws.rs.Produces;
13 | import jakarta.ws.rs.core.MediaType;
14 | import jakarta.ws.rs.core.Response;
15 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
16 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
17 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
18 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
19 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
20 |
21 | import java.util.List;
22 | import java.util.Optional;
23 | import java.util.UUID;
24 | import java.util.stream.Collectors;
25 |
26 | @Path("/todos")
27 | public class TodoController {
28 | private TodoService todoService;
29 |
30 | private String baseUrl = "http://localhost:8080/todos";
31 |
32 | @Inject
33 | public TodoController(TodoService todoService) {
34 | this.todoService = todoService;
35 | }
36 |
37 | @OPTIONS
38 | public Response options() {
39 | return corsResponse();
40 | }
41 |
42 | @OPTIONS
43 | @Path("{id:.*}")
44 | public Response options2() {
45 | return corsResponse();
46 | }
47 |
48 | private static Response corsResponse() {
49 | return Response.ok()
50 | .header("Access-Control-Allow-Origin", "*")
51 | .header("Access-Control-Allow-Headers", "content-type")
52 | .header("Access-Control-Allow-Credentials", "true")
53 | .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
54 | .build();
55 | }
56 |
57 | @GET
58 | @Produces(MediaType.APPLICATION_JSON)
59 | public List getAll() {
60 | return this.todoService.findAll().stream()
61 | .map(this::wrap)
62 | .collect(Collectors.toList());
63 | }
64 |
65 | @GET
66 | @Path("/{id}")
67 | @Produces(MediaType.APPLICATION_JSON)
68 | public TodoDTO getTodo(@PathParam("id") String id) {
69 | return this.todoService.findById(UUID.fromString(id))
70 | .map(this::wrap)
71 | .orElse(null);
72 | }
73 |
74 | @POST
75 | @Produces(MediaType.APPLICATION_JSON)
76 | @Consumes(MediaType.APPLICATION_JSON)
77 | public TodoDTO createTodo(CreateTodoCommand command) {
78 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
79 | return this.wrap(result);
80 | }
81 |
82 | @DELETE
83 | public Response deleteAll() {
84 | this.todoService.deleteAll();
85 | return Response.noContent().build();
86 | }
87 |
88 | @PATCH
89 | @Path("/{id}")
90 | @Produces(MediaType.APPLICATION_JSON)
91 | @Consumes(MediaType.APPLICATION_JSON)
92 | public TodoDTO patchTodo(@PathParam("id") String id, PartialTodo command) {
93 | return this.todoService.updateTodo(UUID.fromString(id), command)
94 | .map(this::wrap)
95 | .orElse(null);
96 | }
97 |
98 | @DELETE
99 | @Path("/{id}")
100 | public Response deleteTodo(@PathParam("id") UUID id) {
101 | this.todoService.delete(id);
102 | return Response.noContent().build();
103 | }
104 |
105 | private TodoDTO wrap(Todo todo) {
106 | return TodoDTO.from(todo, createUrl(todo));
107 | }
108 |
109 | private String createUrl(Todo todo) {
110 | return this.baseUrl + "/" + todo.getId().toString();
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/helidon-se/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | nl.jaapcoomans.demo.microframeworks
7 | helidon-se
8 | jar
9 | 0.0.1-SNAPSHOT
10 |
11 |
12 | io.helidon.applications
13 | helidon-se
14 | 2.3.0
15 |
16 |
17 |
18 |
19 | 16
20 | ${java.version}
21 | ${java.version}
22 |
23 |
24 |
25 |
26 | io.helidon.bundles
27 | helidon-bundles-webserver
28 |
29 |
30 | io.helidon.media
31 | helidon-media-jackson
32 |
33 |
34 | io.helidon.webserver
35 | helidon-webserver-cors
36 |
37 |
38 |
39 |
40 | nl.jaapcoomans.demo.microframeworks
41 | todo-backend
42 | 0.0.1-SNAPSHOT
43 |
44 |
45 |
46 |
47 | org.slf4j
48 | slf4j-simple
49 |
50 |
51 |
52 |
53 | org.junit.jupiter
54 | junit-jupiter-api
55 |
56 |
57 | org.junit.jupiter
58 | junit-jupiter-engine
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | org.apache.maven.plugins
67 | maven-jar-plugin
68 |
69 | application
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | org.apache.maven.plugins
78 | maven-dependency-plugin
79 | 3.1.1
80 |
81 |
82 | dependencies
83 | package
84 |
85 | copy-dependencies
86 |
87 |
88 | target/libs
89 |
90 |
91 |
92 |
93 | false
94 | false
95 | true
96 | runtime
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/helidon-mp/src/main/java/nl/jaapcoomans/microframeworks/helidon/mp/TodoController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.helidon.mp;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
4 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
5 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
6 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
7 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
8 |
9 | import javax.enterprise.context.RequestScoped;
10 | import javax.inject.Inject;
11 | import javax.ws.rs.Consumes;
12 | import javax.ws.rs.DELETE;
13 | import javax.ws.rs.GET;
14 | import javax.ws.rs.OPTIONS;
15 | import javax.ws.rs.PATCH;
16 | import javax.ws.rs.POST;
17 | import javax.ws.rs.Path;
18 | import javax.ws.rs.PathParam;
19 | import javax.ws.rs.Produces;
20 | import javax.ws.rs.core.MediaType;
21 | import javax.ws.rs.core.Response;
22 | import java.util.List;
23 | import java.util.UUID;
24 | import java.util.stream.Collectors;
25 |
26 | @RequestScoped
27 | @Path("/")
28 | public class TodoController {
29 | private TodoService todoService;
30 |
31 | private String baseUrl = "http://localhost:8080/todos";
32 |
33 | @Inject
34 | public TodoController(TodoService todoService) {
35 | this.todoService = todoService;
36 | }
37 |
38 | @OPTIONS
39 | public Response options() {
40 | return corsResponse();
41 | }
42 |
43 | @OPTIONS
44 | @Path("{id:.*}")
45 | public Response options2() {
46 | return corsResponse();
47 | }
48 |
49 | private static Response corsResponse() {
50 | return Response.ok()
51 | .header("Access-Control-Allow-Origin", "*")
52 | .header("Access-Control-Allow-Headers", "content-type")
53 | .header("Access-Control-Allow-Credentials", "true")
54 | .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
55 | .build();
56 | }
57 |
58 |
59 | @GET
60 | @Produces(MediaType.APPLICATION_JSON)
61 | public List getAll() {
62 | return this.todoService.findAll().stream()
63 | .map(this::wrap)
64 | .collect(Collectors.toList());
65 | }
66 |
67 | @GET
68 | @Path("/{id}")
69 | @Produces(MediaType.APPLICATION_JSON)
70 | public Response getTodo(@PathParam("id") String id) {
71 | return this.todoService.findById(UUID.fromString(id))
72 | .map(this::wrap)
73 | .map(body -> Response.ok(body).build())
74 | .orElse(Response.status(Response.Status.NOT_FOUND).build());
75 | }
76 |
77 | @POST
78 | @Produces(MediaType.APPLICATION_JSON)
79 | @Consumes(MediaType.APPLICATION_JSON)
80 | public TodoDTO createTodo(CreateTodoCommand command) {
81 | Todo result = this.todoService.createNewTodo(command.getTitle(), command.getOrder());
82 | return this.wrap(result);
83 | }
84 |
85 | @DELETE
86 | public Response deleteAll() {
87 | this.todoService.deleteAll();
88 | return Response.noContent().build();
89 | }
90 |
91 | @PATCH
92 | @Path("/{id}")
93 | @Produces(MediaType.APPLICATION_JSON)
94 | @Consumes(MediaType.APPLICATION_JSON)
95 | public TodoDTO patchTodo(@PathParam("id") String id, PartialTodo command) {
96 | return this.todoService.updateTodo(UUID.fromString(id), command)
97 | .map(this::wrap)
98 | .orElse(null);
99 | }
100 |
101 | @DELETE
102 | @Path("/{id}")
103 | public Response deleteTodo(@PathParam("id") UUID id) {
104 | this.todoService.delete(id);
105 | return Response.noContent().build();
106 | }
107 |
108 | private TodoDTO wrap(Todo todo) {
109 | return TodoDTO.from(todo, createUrl(todo));
110 | }
111 |
112 | private String createUrl(Todo todo) {
113 | return this.baseUrl + "/" + todo.getId().toString();
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/armeria/src/main/java/nl/jaapcoomans/microframeworks/armeria/TodoRestController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.microframeworks.armeria;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import com.linecorp.armeria.common.HttpMethod;
6 | import com.linecorp.armeria.common.HttpResponse;
7 | import com.linecorp.armeria.common.HttpStatus;
8 | import com.linecorp.armeria.common.MediaType;
9 | import com.linecorp.armeria.server.ServiceRequestContext;
10 | import com.linecorp.armeria.server.annotation.ConsumesJson;
11 | import com.linecorp.armeria.server.annotation.Delete;
12 | import com.linecorp.armeria.server.annotation.Get;
13 | import com.linecorp.armeria.server.annotation.Param;
14 | import com.linecorp.armeria.server.annotation.Patch;
15 | import com.linecorp.armeria.server.annotation.Post;
16 | import com.linecorp.armeria.server.annotation.ProducesJson;
17 | import com.linecorp.armeria.server.annotation.StatusCode;
18 | import com.linecorp.armeria.server.annotation.decorator.CorsDecorator;
19 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
20 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
21 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
22 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
23 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
24 |
25 | import java.util.List;
26 | import java.util.UUID;
27 | import java.util.stream.Collectors;
28 |
29 | @CorsDecorator(origins = "*", allowedRequestMethods = HttpMethod.GET, allowedRequestHeaders = "Content-Type")
30 | class TodoRestController {
31 | private ObjectMapper objectMapper = new ObjectMapper();
32 |
33 | private TodoService todoService;
34 | private String baseUrl;
35 |
36 | TodoRestController(TodoService todoService, String baseUrl) {
37 | this.todoService = todoService;
38 | this.baseUrl = baseUrl;
39 | }
40 |
41 | @Get("/todos")
42 | @ProducesJson
43 | public List getAll() {
44 | return this.todoService.findAll().stream()
45 | .map(this::wrap)
46 | .collect(Collectors.toList());
47 | }
48 |
49 | @Get("/todos/{id}")
50 | @ProducesJson
51 | public HttpResponse getTodo(@Param("id") String id) throws JsonProcessingException {
52 | return this.todoService.findById(UUID.fromString(id))
53 | .map(this::wrap)
54 | .map(todo -> HttpResponse.of(HttpStatus.OK, MediaType.JSON,
55 | this.convertToJson(todo)))
56 | .orElse(HttpResponse.of(404));
57 | }
58 |
59 | private String convertToJson(TodoDTO todo) {
60 | try {
61 | return objectMapper.writeValueAsString(todo);
62 | } catch (JsonProcessingException e) {
63 | throw new RuntimeException(e);
64 | }
65 | }
66 |
67 | @Post("/todos")
68 | @ProducesJson
69 | @ConsumesJson
70 | public TodoDTO createTodo(CreateTodoCommand command) {
71 | Todo todo = this.todoService.createNewTodo(command.getTitle(),
72 | command.getOrder());
73 | return this.wrap(todo);
74 | }
75 |
76 | @Delete("/todos")
77 | @StatusCode(204)
78 | public void deleteAll() {
79 | this.todoService.deleteAll();
80 | }
81 |
82 | @Patch("/todos/{id}")
83 | @ConsumesJson
84 | @ProducesJson
85 | public TodoDTO patchTodo(@Param("id") String id, PartialTodo command) {
86 | return this.todoService.updateTodo(UUID.fromString(id), command)
87 | .map(this::wrap)
88 | .orElse(null);
89 | }
90 |
91 | @Delete("/todos/{id}")
92 | @StatusCode(204)
93 | public void deleteTodo(@Param("id") String id) {
94 | this.todoService.delete(UUID.fromString(id));
95 | }
96 |
97 | private TodoDTO wrap(Todo todo) {
98 | return TodoDTO.from(todo, createUrl(todo));
99 | }
100 |
101 | private String createUrl(Todo todo) {
102 | return this.baseUrl + "/" + todo.getId().toString();
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/ratpack/src/main/java/nl/jaapcoomans/demo/microframeworks/ratpack/TodoRestController.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.ratpack;
2 |
3 | import nl.jaapcoomans.demo.microframeworks.todo.api.CreateTodoCommand;
4 | import nl.jaapcoomans.demo.microframeworks.todo.api.TodoDTO;
5 | import nl.jaapcoomans.demo.microframeworks.todo.domain.PartialTodo;
6 | import nl.jaapcoomans.demo.microframeworks.todo.domain.Todo;
7 | import nl.jaapcoomans.demo.microframeworks.todo.domain.TodoService;
8 | import ratpack.handling.Chain;
9 | import ratpack.handling.Context;
10 | import ratpack.http.Status;
11 | import ratpack.jackson.Jackson;
12 |
13 | import java.util.List;
14 | import java.util.UUID;
15 | import java.util.stream.Collectors;
16 |
17 | import static ratpack.handling.Handlers.byMethod;
18 | import static ratpack.jackson.Jackson.fromJson;
19 | import static ratpack.jackson.Jackson.json;
20 |
21 | public class TodoRestController {
22 | private static final String ID_PATH_PARAM = "id";
23 |
24 | private TodoService todoService;
25 | private String baseUrl;
26 |
27 | TodoRestController(TodoService todoService, String baseUrl) {
28 | this.todoService = todoService;
29 | this.baseUrl = baseUrl;
30 | }
31 |
32 | void initializeEndpoints(Chain chain) throws Exception {
33 | chain
34 | .path("todos", byMethod(chain.getRegistry(), spec ->
35 | spec.get(this::getAll)
36 | .post(this::createTodo)
37 | .delete(this::deleteAll)
38 | )
39 | )
40 | .path("todos/:id", byMethod(chain.getRegistry(), spec ->
41 | spec.get(this::getTodo)
42 | .delete(this::deleteTodo)
43 | .patch(this::patchTodo)
44 | )
45 | );
46 | }
47 |
48 | void getAll(Context context) {
49 | List todos = this.todoService.findAll().stream()
50 | .map(this::wrap)
51 | .collect(Collectors.toList());
52 |
53 | context.render(json(todos));
54 | }
55 |
56 | void getTodo(Context context) {
57 | UUID id = UUID.fromString(context.getPathTokens().get(ID_PATH_PARAM));
58 |
59 | this.todoService.findById(id)
60 | .map(this::wrap)
61 | .map(Jackson::json)
62 | .ifPresentOrElse(context::render, () -> context.getResponse().status(Status.NOT_FOUND).send());
63 | }
64 |
65 | void createTodo(Context context) {
66 | context.parse(fromJson(CreateTodoCommand.class))
67 | .map(command -> this.todoService.createNewTodo(command.getTitle(), command.getOrder()))
68 | .map(this::wrap)
69 | .map(Jackson::json)
70 | .then(context::render);
71 | }
72 |
73 | void deleteAll(Context context) {
74 | this.todoService.deleteAll();
75 | context.getResponse().status(Status.NO_CONTENT).send();
76 | }
77 |
78 | void patchTodo(Context context) {
79 | UUID id = UUID.fromString(context.getPathTokens().get(ID_PATH_PARAM));
80 |
81 | context.parse(fromJson(PartialTodo.class))
82 | .map(command -> this.todoService.updateTodo(id, command))
83 | .then(todo -> todo.map(this::wrap)
84 | .map(Jackson::json)
85 | .ifPresentOrElse(context::render, () -> context.getResponse().status(Status.NOT_FOUND).send())
86 | );
87 | }
88 |
89 | void deleteTodo(Context context) {
90 | UUID id = UUID.fromString(context.getPathTokens().get(ID_PATH_PARAM));
91 | this.todoService.delete(id);
92 | context.getResponse().status(Status.NO_CONTENT).send();
93 | }
94 |
95 | private TodoDTO wrap(Todo todo) {
96 | return TodoDTO.from(todo, createUrl(todo));
97 | }
98 |
99 | private String createUrl(Todo todo) {
100 | return this.baseUrl + "/" + todo.getId().toString();
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/quarkus/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | quarkus
7 | jar
8 |
9 |
10 | nl.jaapcoomans.demo.microframeworks
11 | parent
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 1.13.6.Final
17 |
18 |
19 |
20 |
21 |
22 | io.quarkus
23 | quarkus-universe-bom
24 | ${quarkus.version}
25 | pom
26 | import
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | io.quarkus
35 | quarkus-resteasy
36 |
37 |
38 | io.quarkus
39 | quarkus-resteasy-jackson
40 |
41 |
42 | io.quarkus
43 | quarkus-arc
44 |
45 |
46 |
47 |
48 | nl.jaapcoomans.demo.microframeworks
49 | todo-backend
50 | 0.0.1-SNAPSHOT
51 |
52 |
53 |
54 |
55 |
56 |
57 | io.quarkus
58 | quarkus-maven-plugin
59 | ${quarkus.version}
60 | true
61 |
62 |
63 |
64 | build
65 | generate-code
66 | generate-code-tests
67 |
68 |
69 |
70 |
71 |
72 | org.apache.maven.plugins
73 | maven-compiler-plugin
74 | 3.8.1
75 |
76 | true
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/helidon-mp/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | nl.jaapcoomans.demo.microframeworks
7 | helidon-mp
8 | jar
9 | 0.0.1-SNAPSHOT
10 |
11 |
12 | io.helidon.applications
13 | helidon-mp
14 | 2.3.0
15 |
16 |
17 |
18 |
19 | 16
20 | ${java.version}
21 | ${java.version}
22 |
23 |
24 |
25 |
26 | io.helidon.microprofile.bundles
27 | helidon-microprofile
28 |
29 |
30 | org.glassfish.jersey.media
31 | jersey-media-json-binding
32 |
33 |
34 | org.jboss
35 | jandex
36 | runtime
37 | true
38 |
39 |
40 | jakarta.activation
41 | jakarta.activation-api
42 | runtime
43 |
44 |
45 |
46 |
47 | nl.jaapcoomans.demo.microframeworks
48 | todo-backend
49 | 0.0.1-SNAPSHOT
50 |
51 |
52 |
53 |
54 | org.slf4j
55 | slf4j-simple
56 |
57 |
58 |
59 |
60 | org.junit.jupiter
61 | junit-jupiter-api
62 |
63 |
64 | org.junit.jupiter
65 | junit-jupiter-engine
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.apache.maven.plugins
74 | maven-jar-plugin
75 |
76 | application
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | org.apache.maven.plugins
85 | maven-dependency-plugin
86 | 3.1.1
87 |
88 |
89 | dependencies
90 | package
91 |
92 | copy-dependencies
93 |
94 |
95 | target/libs
96 |
97 |
98 |
99 |
100 | false
101 | false
102 | true
103 | runtime
104 |
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/micronaut/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | micronaut
8 |
9 |
10 | parent
11 | nl.jaapcoomans.demo.microframeworks
12 | 0.0.1-SNAPSHOT
13 |
14 |
15 |
16 | 2.5.4
17 |
18 |
19 |
20 |
21 |
22 | io.micronaut
23 | micronaut-bom
24 | ${micronaut.version}
25 | pom
26 | import
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | io.micronaut
35 | micronaut-http-server-netty
36 |
37 |
38 |
39 |
40 | nl.jaapcoomans.demo.microframeworks
41 | todo-backend
42 | 0.0.1-SNAPSHOT
43 |
44 |
45 |
46 |
47 | org.slf4j
48 | slf4j-simple
49 |
50 |
51 |
52 |
53 |
54 |
55 | org.apache.maven.plugins
56 | maven-compiler-plugin
57 | 3.7.0
58 |
59 |
60 | -parameters
61 |
62 |
63 |
64 | io.micronaut
65 | micronaut-inject-java
66 | ${micronaut.version}
67 |
68 |
69 | io.micronaut
70 | micronaut-validation
71 | ${micronaut.version}
72 |
73 |
74 |
75 |
76 |
77 | test-compile
78 |
79 | testCompile
80 |
81 |
82 |
83 | -parameters
84 |
85 |
86 |
87 | io.micronaut
88 | micronaut-inject-java
89 | ${micronaut.version}
90 |
91 |
92 | io.micronaut
93 | micronaut-validation
94 | ${micronaut.version}
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | org.apache.maven.plugins
103 | maven-jar-plugin
104 |
105 |
106 | org.apache.maven.plugins
107 | maven-dependency-plugin
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | nl.jaapcoomans.demo.microframeworks
7 | parent
8 | pom
9 | 0.0.1-SNAPSHOT
10 |
11 |
12 | UTF-8
13 |
14 | 16
15 | ${java.version}
16 | ${java.version}
17 |
18 | 1.6.0
19 |
20 |
21 | 3.19.0
22 | 5.7.2
23 | 3.10.0
24 |
25 |
26 |
27 | armeria
28 | blade
29 | dropwizard
30 | helidon-mp
31 | helidon-se
32 | http4k
33 | javalin
34 | jooby
35 | ktor
36 | kumuluzee
37 | micronaut
38 | minijax
39 | pippo
40 | quarkus
41 | ratpack
42 | spark
43 |
44 | todo-backend
45 | todo-backend-test
46 |
47 |
48 |
49 |
50 |
51 | org.slf4j
52 | slf4j-simple
53 | 1.7.28
54 |
55 |
56 |
57 |
58 | org.jetbrains.kotlin
59 | kotlin-stdlib
60 | ${kotlin.version}
61 |
62 |
63 |
64 |
65 | org.junit.jupiter
66 | junit-jupiter-api
67 | ${junit.version}
68 | test
69 |
70 |
71 | org.junit.jupiter
72 | junit-jupiter-engine
73 | ${junit.version}
74 | test
75 |
76 |
77 | org.mockito
78 | mockito-junit-jupiter
79 | ${mockito.version}
80 | test
81 |
82 |
83 | org.assertj
84 | assertj-core
85 | ${assertj.version}
86 | test
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | org.apache.maven.plugins
96 | maven-jar-plugin
97 | 3.2.0
98 |
99 | application
100 |
101 |
102 |
103 | org.jetbrains.kotlin
104 | kotlin-maven-plugin
105 | ${kotlin.version}
106 |
107 |
108 | compile
109 | compile
110 |
111 | compile
112 |
113 |
114 |
115 | test-compile
116 | test-compile
117 |
118 | test-compile
119 |
120 |
121 |
122 |
123 |
124 | org.apache.maven.plugins
125 | maven-dependency-plugin
126 | 3.1.1
127 |
128 |
129 | dependencies
130 | package
131 |
132 | copy-dependencies
133 |
134 |
135 | target/libs
136 |
137 |
138 |
139 |
140 | false
141 | false
142 | true
143 | runtime
144 |
145 |
146 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/todo-backend-test/src/test/java/nl/jaapcoomans/demo/microframeworks/todo/test/BaseTodoBackendTest.java:
--------------------------------------------------------------------------------
1 | package nl.jaapcoomans.demo.microframeworks.todo.test;
2 |
3 | import io.restassured.RestAssured;
4 | import org.apache.http.HttpHeaders;
5 | import org.junit.jupiter.api.DisplayName;
6 | import org.junit.jupiter.api.MethodOrderer;
7 | import org.junit.jupiter.api.Order;
8 | import org.junit.jupiter.api.Test;
9 | import org.junit.jupiter.api.TestMethodOrder;
10 | import org.testcontainers.containers.GenericContainer;
11 |
12 | import static org.hamcrest.CoreMatchers.anyOf;
13 | import static org.hamcrest.CoreMatchers.equalTo;
14 | import static org.hamcrest.CoreMatchers.not;
15 | import static org.hamcrest.CoreMatchers.notNullValue;
16 | import static org.hamcrest.CoreMatchers.startsWith;
17 | import static org.hamcrest.Matchers.containsString;
18 | import static org.hamcrest.Matchers.empty;
19 | import static org.hamcrest.Matchers.emptyOrNullString;
20 | import static org.hamcrest.Matchers.equalToIgnoringCase;
21 | import static org.hamcrest.Matchers.hasSize;
22 |
23 | @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
24 | abstract class BaseTodoBackendTest {
25 | private static final String API_ROOT = "/todos";
26 |
27 | abstract GenericContainer> getContainer();
28 |
29 | String getBaseUrl() {
30 | return "http://" + getContainer().getContainerIpAddress() + ":" + getContainer().getFirstMappedPort();
31 | }
32 |
33 | String replacePort(String url) {
34 | return url.replaceFirst("[1-9][0-9]{1,4}", getContainer().getFirstMappedPort().toString());
35 | }
36 |
37 | @Test
38 | @Order(1)
39 | @DisplayName("the api root responds to a GET (i.e. the server is up and accessible, CORS headers are set up)")
40 | final void getApiRoot() {
41 | RestAssured.given()
42 | .header("Access-Control-Request-Headers", HttpHeaders.CONTENT_TYPE)
43 | .header("Access-Control-Request-Method", "GET")
44 | .header("Origin", "http://crossorigin.example.org")
45 | .baseUri(getBaseUrl())
46 | .when().options(API_ROOT)
47 | .then()
48 | .header("Access-Control-Allow-Origin", notNullValue())
49 | .header("Access-Control-Allow-Headers", anyOf(equalToIgnoringCase(HttpHeaders.CONTENT_TYPE), containsString(HttpHeaders.CONTENT_TYPE), equalTo("*")))
50 | .header("Access-Control-Allow-Methods", notNullValue());
51 |
52 | RestAssured.given()
53 | .header(HttpHeaders.ACCEPT, "application/json")
54 | .baseUri(getBaseUrl())
55 | .when().get(API_ROOT)
56 | .then()
57 | .statusCode(200)
58 | .body("$", empty());
59 | }
60 |
61 | @Test
62 | @Order(2)
63 | @DisplayName("the api root responds to a POST with the todo which was posted to it")
64 | void postApiRoot() {
65 | RestAssured.given()
66 | .header(HttpHeaders.CONTENT_TYPE, "application/json")
67 | .baseUri(getBaseUrl())
68 | .body("{\"title\": \"Test 123\", \"order\": 1 }")
69 | .when().post(API_ROOT)
70 | .then()
71 | .statusCode(200)
72 | .body("id", not(emptyOrNullString()))
73 | .body("title", equalTo("Test 123"))
74 | .body("url", startsWith("http://"))
75 | .body("order", equalTo(1))
76 | .body("completed", equalTo(false));
77 | }
78 |
79 | @Test
80 | @Order(3)
81 | @DisplayName("the api root responds successfully to a DELETE, after a DELETE the api root responds to a GET with a JSON representation of an empty array")
82 | void deleteApiRoot() {
83 | RestAssured.given()
84 | .baseUri(getBaseUrl())
85 | .when().delete(API_ROOT)
86 | .then()
87 | .statusCode(204);
88 | }
89 |
90 | @Test
91 | @Order(4)
92 | @DisplayName("after a DELETE the api root responds to a GET with a JSON representation of an empty array")
93 | void afterDeleteApiRoot() {
94 | RestAssured.given()
95 | .header(HttpHeaders.ACCEPT, "application/json")
96 | .baseUri(getBaseUrl())
97 | .when().get(API_ROOT)
98 | .then()
99 | .statusCode(200)
100 | .body("$", empty());
101 | }
102 |
103 | @Test
104 | @Order(5)
105 | @DisplayName("adds a new todo to the list of todos at the root url")
106 | void addTodo() {
107 | RestAssured.given()
108 | .header(HttpHeaders.CONTENT_TYPE, "application/json")
109 | .baseUri(getBaseUrl())
110 | .body("{\"title\": \"Test 1\", \"order\": 1 }")
111 | .when().post(API_ROOT)
112 | .then()
113 | .statusCode(200);
114 |
115 | RestAssured.given()
116 | .header(HttpHeaders.ACCEPT, "application/json")
117 | .baseUri(getBaseUrl())
118 | .when().get(API_ROOT)
119 | .then()
120 | .statusCode(200)
121 | .body("$", hasSize(1));
122 | }
123 |
124 | @Test
125 | @Order(6)
126 | @DisplayName("sets up a new todo as initially not completed")
127 | void todoInitiallyNotCompleted() {
128 | RestAssured.given()
129 | .header(HttpHeaders.CONTENT_TYPE, "application/json")
130 | .baseUri(getBaseUrl())
131 | .body("{\"title\": \"Test 2\", \"order\": 2 }")
132 | .when().post(API_ROOT)
133 | .then()
134 | .statusCode(200)
135 | .body("completed", equalTo(false));
136 | }
137 |
138 | @Test
139 | @Order(7)
140 | @DisplayName("each new todo has a url")
141 | void newTodoHasUrl() {
142 | RestAssured.given()
143 | .header(HttpHeaders.CONTENT_TYPE, "application/json")
144 | .baseUri(getBaseUrl())
145 | .body("{\"title\": \"Test 3\", \"order\": 3 }")
146 | .when().post(API_ROOT)
147 | .then()
148 | .statusCode(200)
149 | .body("url", startsWith("http://"));
150 | }
151 |
152 | @Test
153 | @Order(8)
154 | @DisplayName("each new todo has a url, which returns a todo")
155 | void newTodoHasUrlWhichReturnsTodo() {
156 | var response = RestAssured.given()
157 | .header(HttpHeaders.CONTENT_TYPE, "application/json")
158 | .baseUri(getBaseUrl())
159 | .body("{\"title\": \"Test 4\", \"order\": 4 }")
160 | .when().post(API_ROOT);
161 |
162 | response
163 | .then()
164 | .statusCode(200)
165 | .body("url", startsWith("http://"));
166 |
167 | var url = response.body().jsonPath().get("url").toString();
168 |
169 | var response2 = RestAssured.given()
170 | .header(HttpHeaders.ACCEPT, "application/json")
171 | .baseUri(replacePort(url))
172 | .when().get();
173 | response2.then()
174 | .statusCode(200)
175 | .body("id", not(emptyOrNullString()))
176 | .body("title", equalTo("Test 4"))
177 | .body("url", equalTo(url))
178 | .body("order", equalTo(4))
179 | .body("completed", equalTo(false));
180 | }
181 |
182 | @Test
183 | @Order(9)
184 | @DisplayName("can navigate from a list of todos to an individual todo via urls")
185 | void navigateFromListToIndividual() {
186 | var url = RestAssured.given()
187 | .header(HttpHeaders.ACCEPT, "application/json")
188 | .baseUri(getBaseUrl())
189 | .when().get(API_ROOT)
190 | .body().jsonPath().get("[0].url").toString();
191 |
192 | RestAssured.given()
193 | .header(HttpHeaders.CONTENT_TYPE, "application/json")
194 | .baseUri(replacePort(url))
195 | .when().get()
196 | .then()
197 | .statusCode(200)
198 | .body("id", not(emptyOrNullString()))
199 | .body("title", not(emptyOrNullString()))
200 | .body("url", equalTo(url))
201 | .body("order", notNullValue())
202 | .body("completed", equalTo(false));
203 | }
204 |
205 | @Test
206 | @Order(10)
207 | @DisplayName("can change the todo's title by PATCHing to the todo's url")
208 | void changeTitle() {
209 | var url = RestAssured.given()
210 | .header(HttpHeaders.ACCEPT, "application/json")
211 | .baseUri(getBaseUrl())
212 | .when().get(API_ROOT)
213 | .body().jsonPath().get("[0].url").toString();
214 |
215 | RestAssured.given()
216 | .header(HttpHeaders.CONTENT_TYPE, "application/json")
217 | .baseUri(replacePort(url))
218 | .body("{\"title\": \"Changed\"}")
219 | .when().patch()
220 | .then()
221 | .statusCode(200)
222 | .body("title", equalTo("Changed"));
223 | }
224 |
225 | @Test
226 | @Order(11)
227 | @DisplayName("can change the todo's completedness by PATCHing to the todo's url")
228 | void changeCompleted() {
229 | var url = RestAssured.given()
230 | .header(HttpHeaders.ACCEPT, "application/json")
231 | .baseUri(getBaseUrl())
232 | .when().get(API_ROOT)
233 | .body().jsonPath().get("[0].url").toString();
234 |
235 | RestAssured.given()
236 | .header(HttpHeaders.CONTENT_TYPE, "application/json")
237 | .baseUri(replacePort(url))
238 | .body("{\"completed\": true}")
239 | .when().patch()
240 | .then()
241 | .statusCode(200)
242 | .body("completed", equalTo(true));
243 | }
244 |
245 | @Test
246 | @Order(12)
247 | @DisplayName("changes to a todo are persisted and show up when re-fetching the todo")
248 | void changesArePersisted() {
249 | var url = RestAssured.given()
250 | .header(HttpHeaders.ACCEPT, "application/json")
251 | .baseUri(getBaseUrl())
252 | .when().get(API_ROOT)
253 | .body().jsonPath().get("[0].url").toString();
254 |
255 | RestAssured.given()
256 | .header(HttpHeaders.CONTENT_TYPE, "application/json")
257 | .baseUri(replacePort(url))
258 | .body("{\"title\": \"Persisted\"}")
259 | .when().patch()
260 | .then().statusCode(200);
261 |
262 | RestAssured.given()
263 | .header(HttpHeaders.ACCEPT, "application/json")
264 | .baseUri(replacePort(url))
265 | .when().get()
266 | .then().body("title", equalTo("Persisted"));
267 | }
268 |
269 | @Test
270 | @Order(13)
271 | @DisplayName("can delete a todo making a DELETE request to the todo's url")
272 | void deleteTodo() {
273 | var url = RestAssured.given()
274 | .header(HttpHeaders.ACCEPT, "application/json")
275 | .baseUri(getBaseUrl())
276 | .when().get(API_ROOT)
277 | .body().jsonPath().get("[0].url").toString();
278 |
279 | RestAssured.given()
280 | .baseUri(replacePort(url))
281 | .when().delete()
282 | .then().statusCode(204);
283 |
284 | RestAssured.given()
285 | .header(HttpHeaders.ACCEPT, "application/json")
286 | .baseUri(replacePort(url))
287 | .when().get()
288 | .then().statusCode(404);
289 | }
290 | }
291 |
--------------------------------------------------------------------------------