diff --git a/.gitignore b/.gitignore index 5100048..b312012 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ .idea/**/usage.statistics.xml .idea/**/dictionaries .idea/**/shelf - .idea/**/contentModel.xml ## Sensitive or high-churn files @@ -31,4 +30,11 @@ # Others .envrc +# Eclipse + +.classpath +.project +.settings/ + +# Maven target/ diff --git a/complete-tutorial/.gitignore b/complete-tutorial/.gitignore new file mode 100644 index 0000000..d9e5eda --- /dev/null +++ b/complete-tutorial/.gitignore @@ -0,0 +1,4 @@ +# Intellij + +.idea + diff --git a/complete-tutorial/README.md b/complete-tutorial/README.md index 46f0d32..4681997 100644 --- a/complete-tutorial/README.md +++ b/complete-tutorial/README.md @@ -1,5 +1,17 @@ # QuantumMaid - Creating a Complete Application +(Author: [@lestephane](https://github.com/lestephane)) + +Let us implement a backend in the style of todobackend.com! + +We’ll refer to this project as todomaid-api. PRs are welcome. + +Originally inspired from a [Tech Enthusiasts blog post](https://techenthusiasts.atlassian.net/wiki/spaces/TE/pages/71434262/Quantummaid+zero+to+lambda) + +## Step 1 - First failing test(s) ([step1/README.md](step1/README.md)) + +--- + This site is under construction. Contributions are greatly appreciated. diff --git a/complete-tutorial/step1/README.md b/complete-tutorial/step1/README.md new file mode 100644 index 0000000..a07a3ef --- /dev/null +++ b/complete-tutorial/step1/README.md @@ -0,0 +1,147 @@ +# Step 1 - First failing test(s) + +## Initial pom.xml + +The `pom.xml` we'll start from is + +```xml + + 4.0.0 + todomaid + todomaid-api + 1.0.0 + + + 11 + true + ${java.version} + ${java.version} + 1.0.48 + + + + + + de.quantummaid.quantummaid + quantummaid-bom + ${quantummaid.version} + pom + import + + + + + + + de.quantummaid.quantummaid.packagings + quantummaid-essentials + + + +``` + +- ⓵ QuantumMaid requires reflection metadata for method parameters (ie the compiler `-parameters` command-line argument). This enables it. + +- ⓶ In order to ensure that the various quantummaid libraries work together, we import their versions from the `quantummaid-bom` dependency, which tracks the latest good known versions. + +- ⓷ Grouping of dependencies that enables serving use case classes without having to hunt down artifact IDs. + +--- + +## Initial main class + +We need a main class that will serve as the entrypoint for QuantumMaid. +It must be located where maven expects production classes (src/main). + +```bash +$ tree src/main +src/main +└── java + └── todomaid + └── api + └── Server.java +``` + +An initial version of the Server class will dump all requests to System.err: + +```java +package todomaid.api; +... +public final class Server { + public static void main(String[] args) { + serverInstance(8080).run(); + } + + @NotNull + private static QuantumMaid serverInstance(int port) { + QuantumMaid quantumMaid = quantumMaid() + .withHttpMaid(anHttpMaid() + .get("/*", dumpRequest()) + //.options("/*", dumpRequest()) ⓵ + //.patch("/*", dumpRequest()) ⓶ + .post("/*", dumpRequest()) + .put("/*", dumpRequest()) + .delete("/*", dumpRequest()).build()) + .withLocalHostEndpointOnPort(port); + return quantumMaid; + } + + private static HttpHandler dumpRequest() { + return (req, res) -> + System.err.printf("%s %s %n", req.method(), req.path()); + } +} +``` + +⓵ ⓶ [Additional support](https://github.com/quantummaid/httpmaid/issues/80) is needed to catch these request methods. An any() routing method will further reduce the method size. + +--- + +## First start + +Starting the server is a rather involved maven command, and I never remember how to do it, so here it is: + +```shell +(in terminal 1) +$ mvn exec:java -Dexec.mainClass="todomaid.api.Server" +... +21:28:41.373 [todomaid.api.Server.main()] INFO de.quantummaid.quantummaid.QuantumMaid - + ____ _ __ __ _ _ + / __ \ | | | \/ | (_) | | + | | | |_ _ __ _ _ __ | |_ _ _ _ __ ___ | \ / | __ _ _ __| | + | | | | | | |/ _` | '_ \| __| | | | '_ ` _ \| |\/| |/ _` | |/ _` | + | |__| | |_| | (_| | | | | |_| |_| | | | | | | | | | (_| | | (_| | + \___\_\\__,_|\__,_|_| |_|\__|\__,_|_| |_| |_|_| |_|\__,_|_|\__,_| + +21:28:41.374 [todomaid.api.Server.main()] INFO de.quantummaid.quantummaid.QuantumMaid - Startup took: 341ms (317ms initialization, 24ms endpoint startup) +21:28:41.376 [todomaid.api.Server.main()] INFO de.quantummaid.quantummaid.QuantumMaid - Serving http://localhost:8080/ +21:28:41.376 [todomaid.api.Server.main()] INFO de.quantummaid.quantummaid.QuantumMaid - Ready. +``` + +Run a curl command from another terminal to verify that the server is receiving requests + +```shell +(in terminal 2) +$ curl localhost:8080 +``` + +As expected, the server dumps the request to System.err + +```shell +(in terminal 1) +HttpRequestMethod(value=GET) Path(path=/) +``` + +Let's see the extent of the endpoints we need to support by running the todobackend test suite: + +```bash +$ cd /tmp +$ git clone https://github.com/TodoBackend/todo-backend-js-spec.git +$ cd todo-backend-js-spec +$ firefox index.html +(enter http://localhost:8080) +``` + +The server output STDERR output is rather verbose with internal server errors caused by unmapped OPTIONS request. This is tracked under issue https://github.com/quantummaid/httpmaid/issues/81 + +## To be continued... diff --git a/complete-tutorial/step1/pom.xml b/complete-tutorial/step1/pom.xml new file mode 100644 index 0000000..9085591 --- /dev/null +++ b/complete-tutorial/step1/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + todomaid + todomaid-api + 1.0.0 + + + 11 + true + ${java.version} + ${java.version} + 1.0.48 + + + + + + de.quantummaid.quantummaid + quantummaid-bom + ${quantummaid.version} + import + pom + + + + + + + de.quantummaid.quantummaid.packagings + quantummaid-essentials + + + diff --git a/complete-tutorial/step1/src/main/java/todomaid/api/Server.java b/complete-tutorial/step1/src/main/java/todomaid/api/Server.java new file mode 100644 index 0000000..d29fadd --- /dev/null +++ b/complete-tutorial/step1/src/main/java/todomaid/api/Server.java @@ -0,0 +1,33 @@ +package todomaid.api; + +import de.quantummaid.httpmaid.handler.http.HttpHandler; +import de.quantummaid.quantummaid.QuantumMaid; +import org.jetbrains.annotations.NotNull; + +import static de.quantummaid.httpmaid.HttpMaid.anHttpMaid; +import static de.quantummaid.quantummaid.QuantumMaid.quantumMaid; + +public final class Server { + public static void main(String[] args) { + serverInstance(8080).run(); + } + + @NotNull + private static QuantumMaid serverInstance(int port) { + QuantumMaid quantumMaid = quantumMaid() + .withHttpMaid(anHttpMaid() + .get("/*", dumpRequest()) + //.options("/*", dumpRequest()) + //.patch("/*", dumpRequest()) + .post("/*", dumpRequest()) + .put("/*", dumpRequest()) + .delete("/*", dumpRequest()).build()) + .withLocalHostEndpointOnPort(port); + return quantumMaid; + } + + private static HttpHandler dumpRequest() { + return (request, response) -> System.err.printf("%s %s %n", request.method(), request.path()); + } +} +