From 2a331c049c4e22d59eed4b1c525e2fbdb40f01af Mon Sep 17 00:00:00 2001
From: Josiah Noel <32279667+SentryMan@users.noreply.github.com>
Date: Tue, 3 Jan 2023 10:10:28 -0600
Subject: [PATCH 1/5] Bring the README more in line with the Docs
---
README.md | 328 ++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 267 insertions(+), 61 deletions(-)
diff --git a/README.md b/README.md
index 84359f626..377539d53 100644
--- a/README.md
+++ b/README.md
@@ -1,122 +1,328 @@
-# avaje-http
+# [Avaje-HTTP](https://avaje.io/http/)
-Http server and client libraries and code generation.
+HTTP server and client libraries via code generation.
-## http server
+## HTTP Server
A jax-rs style controllers with annotations (`@Path`, `@Get` ...)
that is lightweight by using source code generation (annotation processors)
-to generate adapter code for Javalin and Helidon SE.
+to generate adapter code for Javalin and Helidon SE/Nima.
- Lightweight as in 65Kb library + generated source code
-- Full use of Javalin or Helidon SE as desired
+- Full use of Javalin or Helidon SE/Nima as desired
+## Quick Start
-## Define a Controller
+#### 1. Add dependencies
+```xml
+
+ io.avaje
+ avaje-http-api
+ ${avaje.http.version}
+
+```
+#### 2. Add the generator module for your desired microframework as a annotation processor.
+
+```xml
+
+
+ io.avaje
+ avaje-inject-generator
+ ${avaje-inject.version}
+ provided
+
+
+ io.avaje
+ avaje-http-javalin-generator
+ ${avaje-http.version}
+ provided
+
+```
+If there are other annotation processors and they are specified via maven-compiler-plugin then we add avaje-http-generator there instead.
+```xml
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+ io.avaje
+ avaje-inject-generator
+ ${avaje-inject.version}
+
+
+ io.avaje
+ avaje-http-javalin-generator
+ ${avaje-http.version}
+
+
+ ... other annotation processor ...
+
+
+
+
+```
+#### 3. Define a Controller (These APT processors work with both Java and Kotlin.)
```java
-package org.example.hello
+package org.example.hello;
-import io.avaje.http.api.Controller
-import io.avaje.http.api.Get
-import io.avaje.http.api.Path
+import io.avaje.http.api.Controller;
+import io.avaje.http.api.Get;
+import io.avaje.http.api.Path;
+import java.util.List;
@Path("/widgets")
@Controller
-class WidgetController(private val hello: HelloComponent) {
+public class WidgetController {
+ private final HelloComponent hello;
+ public WidgetController(HelloComponent hello) {
+ this.hello = hello;
+ }
+
+ @Get("/{id}")
+ Widget getById(int id) {
+ return new Widget(id, "you got it"+ hello.hello());
+ }
- @Get("/:id")
- fun getById(id : Int): Widget {
- return Widget(id, "you got it${hello.hello()}")
+ @Get()
+ List getAll() {
+ return List.of(new Widget(1, "Rob"), new Widget(2, "Fi"));
}
- @Get
- fun getAll(): MutableList {
+ record Widget(int id, String name){};
+}
+```
- val list = mutableListOf()
- list.add(Widget(1, "Rob"))
- list.add(Widget(2, "Fi"))
+## Usage
+The annotation processor will generate controller adapters that can register routes to Javalin/Helidon. The natural way to use the generated adapters is to get a DI library to find and wire them. This is what the below examples do and they use [Avaje-Inject](https://avaje.io/inject/) to do this.
- return list
- }
+Note that there isn't a requirement to use Avaje for dependency injection. Any DI library that can find and wire the generated @Singleton beans can be used. You can even use Dagger2 or Guice to wire the controllers if you so desire.
- data class Widget(var id: Int, var name: String)
-}
+### Usage with Javalin
+
+The annotation processor will generate controller classes implementing the WebRoutes interface, which means we can
+get all the WebRoutes and register them with Javalin using:
+```java
+var routes = BeanScope.builder().build().list(WebRoutes.class);
+
+Javalin.create()
+ .routes(() -> routes.forEach(WebRoutes::registerRoutes))
+ .start();
+```
+
+### Usage with Helidon SE
+
+The annotation processor will generate controller classes implementing the Helidon Service interface, which we can use
+get all the Services and register them with Helidon `RoutingBuilder`.
+
+```java
+var routes = BeanScope.builder().build().list(Service.class);
+var routingBuilder = Routing.builder().register(routes.stream().toArray(Service[]::new));
+WebServer.builder()
+ .addMediaSupport(JacksonSupport.create())
+ .routing(routingBuilder)
+ .build()
+ .start();
```
-## Generated source
+### Usage with Helidon Nima
+
+The annotation processor will generate controller classes implementing the Helidon HttpService interface, which we can use
+get all the services and register them with the Helidon `HttpRouting`.
+
+```java
+var routes = BeanScope.builder().build().list(HttpService.class);
+final var builder = HttpRouting.builder();
+
+for (final HttpService httpService : routes) {
+ httpService.routing(builder);
+}
-The annotation processor will generate a `$Route` for the controller like below.
+WebServer.builder()
+ .addRouting(builder.build())
+ .build()
+ .start();
+```
+## Generated sources
-Note that this class implements the WebRoutes interface, which means we can
-get all the WebRoutes and register them with Javalin using.
+### (Javalin) The generated WidgetController$Route.java is:
```java
-fun main(args: Array) {
+@Generated("avaje-javalin-generator")
+@Component
+public class WidgetController$Route implements WebRoutes {
- // get all the webRoutes
- val webRoutes = ApplicationScope.list(WebRoutes::class.java)
+ private final WidgetController controller;
- val javalin = Javalin.create()
+ public WidgetController$Route(WidgetController controller) {
+ this.controller = controller;
+ }
- javalin.routes {
- // register all the routes with Javalin
- webRoutes.forEach { it.registerRoutes() }
+ @Override
+ public void registerRoutes() {
+
+ ApiBuilder.get("/widgets/{id}", ctx -> {
+ ctx.status(200);
+ var id = asInt(ctx.pathParam("id"));
+ var result = controller.getById(id);
+ ctx.json(result);
+ });
+
+ ApiBuilder.get("/widgets", ctx -> {
+ ctx.status(200);
+ var result = controller.getAll();
+ ctx.json(result);
+ });
- // other routes etc as desired
- ApiBuilder.get("/foo") { ctx ->
- ctx.html("bar")
- ctx.status(200)
- }
- ...
}
- javalin.start(7000)
}
-
```
-### The generated WidgetController$Route.java is:
+### (Helidon SE) The generated WidgetController$Route.java is:
+```java
+@Generated("io.dinject.helidon-generator")
+@Singleton
+public class WidgetController$Route implements Service {
+
+ private final WidgetController controller;
+ public WidgetController$Route(WidgetController controller) {
+ this.controller = controller;
+ }
+
+ @Override
+ public void update(Routing.Rules rules) {
+
+ rules.get("/widgets/{id}", this::_getById);
+ rules.post("/widgets", this::_getAll);
+ }
+
+ private void _getById(ServerRequest req, ServerResponse res) {
+ int id = asInt(req.path().param("id"));
+ res.send(controller.getById(id));
+ }
+
+ private void _getAll(ServerRequest req, ServerResponse res) {
+ res.send(controller.getAll());
+ }
+
+}
+```
+
+### (Helidon Nima) The generated WidgetController$Route.java is:
```java
-package org.example.hello;
+@Generated("avaje-helidon-nima-generator")
+@Component
+public class WidgetController$Route implements HttpService {
-import static io.avaje.http.api.PathTypeConversion.*;
-import io.avaje.http.api.WebRoutes;
-import io.javalin.apibuilder.ApiBuilder;
-import javax.annotation.Generated;
-import javax.inject.Singleton;
-import org.example.hello.WidgetController;
+ private final WidgetController controller;
+ public WidgetController$Route(WidgetController controller) {
+ this.controller = controller;
+ }
-@Generated("io.avaje.javalin-generator")
-@Singleton
+ @Override
+ public void routing(HttpRules rules) {
+ rules.get("/widgets/{id}", this::_getById);
+ rules.get("/widgets", this::_getAll);
+ }
+
+ private void _getById(ServerRequest req, ServerResponse res) {
+ var pathParams = req.path().pathParameters();
+ int id = asInt(pathParams.first("id").get());
+ var result = controller.getById(id);
+ res.send(result);
+ }
+
+ private void _getAll(ServerRequest req, ServerResponse res) {
+ var pathParams = req.path().pathParameters();
+ var result = controller.getAll();
+ res.send(result);
+ }
+
+}
+```
+
+## Generated sources ([Avaje-Jsonb](https://github.com/avaje/avaje-jsonb))
+If [Avaje-Jsonb](https://github.com/avaje/avaje-jsonb) is detected, http generators with support will use it for faster Json message processing.
+
+### (Javalin) The generated WidgetController$Route.java is:
+```java
+@Generated("avaje-javalin-generator")
+@Component
public class WidgetController$Route implements WebRoutes {
- private final WidgetController controller;
+ private final WidgetController controller;
+ private final JsonType> listWidgetJsonType;
+ private final JsonType widgetJsonType;
- public WidgetController$route(WidgetController controller) {
- this.controller = controller;
- }
+ public WidgetController$Route(WidgetController controller, Jsonb jsonB) {
+ this.controller = controller;
+ this.listWidgetJsonType = jsonB.type(Widget.class).list();
+ this.widgetJsonType = jsonB.type(Widget.class);
+ }
@Override
public void registerRoutes() {
- ApiBuilder.get("/widgets/:id", ctx -> {
- int id = asInt(ctx.pathParam("id"));
- ctx.json(controller.getById(id));
+ ApiBuilder.get("/widgets/{id}", ctx -> {
ctx.status(200);
+ var id = asInt(ctx.pathParam("id"));
+ var result = controller.getById(id);
+ widgetJsonType.toJson(result, ctx.contentType("application/json").outputStream());
});
ApiBuilder.get("/widgets", ctx -> {
- ctx.json(controller.getAll());
ctx.status(200);
+ var result = controller.getAll();
+ listWidgetJsonType.toJson(result, ctx.contentType("application/json").outputStream());
});
}
+
}
```
-Note that this APT processor works with both Java and Kotlin.
+### (Helidon Nima) The generated WidgetController$Route.java is:
+
+```java
+@Generated("avaje-helidon-nima-generator")
+@Component
+public class WidgetController$Route implements HttpService {
+
+
+ private final WidgetController controller;
+ private final JsonType widgetJsonType;
+ private final JsonType> listWidgetJsonType;
+ public WidgetController$Route(WidgetController controller, Jsonb jsonB) {
+ this.controller = controller;
+ this.widgetJsonType = jsonB.type(Widget.class);
+ this.listWidgetJsonType = jsonB.type(Widget.class).list();
+ }
+
+ @Override
+ public void routing(HttpRules rules) {
+ rules.get("/widgets/{id}", this::_getById);
+ rules.get("/widgets", this::_getAll);
+ }
+
+ private void _getById(ServerRequest req, ServerResponse res) {
+ var pathParams = req.path().pathParameters();
+ int id = asInt(pathParams.first("id").get());
+ var result = controller.getById(id);
+ res.headers().contentType(io.helidon.common.http.HttpMediaType.APPLICATION_JSON);
+ widgetJsonType.toJson(result, res.outputStream());
+ }
+
+ private void _getAll(ServerRequest req, ServerResponse res) {
+ var pathParams = req.path().pathParameters();
+ var result = controller.getAll();
+ res.headers().contentType(io.helidon.common.http.HttpMediaType.APPLICATION_JSON);
+ listWidgetJsonType.toJson(result, res.outputStream());
+ }
+}
+```
From 93eca1fe6e525c4f7f37ba0e3b37fd539de5b231 Mon Sep 17 00:00:00 2001
From: Josiah Noel <32279667+SentryMan@users.noreply.github.com>
Date: Tue, 3 Jan 2023 10:14:38 -0600
Subject: [PATCH 2/5] Update README.md
---
README.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/README.md b/README.md
index aeafce8fb..3c9a96784 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,11 @@ to generate adapter code for Javalin and Helidon SE/Nima.
#### 1. Add dependencies
```xml
+
+ io.avaje
+ avaje-inject
+ ${avaje-inject.version}
+
io.avaje
avaje-http-api
From e8334d042fe8066d2755b078e553a0bc33c5846c Mon Sep 17 00:00:00 2001
From: Josiah Noel <32279667+SentryMan@users.noreply.github.com>
Date: Tue, 3 Jan 2023 10:17:40 -0600
Subject: [PATCH 3/5] Update README.md
---
README.md | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index 3c9a96784..379de37d7 100644
--- a/README.md
+++ b/README.md
@@ -11,9 +11,7 @@ to generate adapter code for Javalin and Helidon SE/Nima.
- Lightweight as in 65Kb library + generated source code
- Full use of Javalin or Helidon SE/Nima as desired
-## Quick Start
-
-#### 1. Add dependencies
+## Add dependencies
```xml
io.avaje
@@ -26,7 +24,7 @@ to generate adapter code for Javalin and Helidon SE/Nima.
${avaje.http.version}
```
-#### 2. Add the generator module for your desired microframework as a annotation processor.
+#### Add the generator module for your desired microframework as a annotation processor.
```xml
@@ -67,7 +65,7 @@ If there are other annotation processors and they are specified via maven-com
```
-#### 3. Define a Controller (These APT processors work with both Java and Kotlin.)
+## Define a Controller (These APT processors work with both Java and Kotlin.)
```java
package org.example.hello;
From 05833c69181fd0f80a02001867ba24680bd9a0de Mon Sep 17 00:00:00 2001
From: Josiah Noel <32279667+SentryMan@users.noreply.github.com>
Date: Tue, 3 Jan 2023 14:34:14 -0600
Subject: [PATCH 4/5] Update README.md
---
README.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/README.md b/README.md
index 379de37d7..1aab095d1 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
# [Avaje-HTTP](https://avaje.io/http/)
+[](https://github.com/avaje/avaje-http/actions/workflows/build.yml)
+[](https://github.com/avaje/avaje-inject/blob/master/LICENSE)
+
HTTP server and client libraries via code generation.
From e902d91336a4b1435f6d0c1fe3dec4fda58dcf14 Mon Sep 17 00:00:00 2001
From: Josiah Noel <32279667+SentryMan@users.noreply.github.com>
Date: Tue, 3 Jan 2023 14:36:29 -0600
Subject: [PATCH 5/5] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 1aab095d1..60334e3a2 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# [Avaje-HTTP](https://avaje.io/http/)
[](https://github.com/avaje/avaje-http/actions/workflows/build.yml)
-[](https://github.com/avaje/avaje-inject/blob/master/LICENSE)
+[](https://github.com/avaje/avaje-inject/blob/master/LICENSE)
HTTP server and client libraries via code generation.