From aa0b638f87b7aa27899b526e4af6d5fffc29e55c Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Tue, 12 Sep 2023 08:41:41 -0400 Subject: [PATCH 1/6] add bigInteger --- .../java/io/avaje/http/api/PathTypeConversion.java | 13 +++++++++++++ .../java/io/avaje/http/generator/core/TypeMap.java | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/http-api/src/main/java/io/avaje/http/api/PathTypeConversion.java b/http-api/src/main/java/io/avaje/http/api/PathTypeConversion.java index 49fb16192..eff727720 100644 --- a/http-api/src/main/java/io/avaje/http/api/PathTypeConversion.java +++ b/http-api/src/main/java/io/avaje/http/api/PathTypeConversion.java @@ -2,6 +2,7 @@ import java.math.BigDecimal; import java.time.*; +import java.math.BigInteger; import java.util.List; import java.util.Set; import java.util.UUID; @@ -131,6 +132,18 @@ public static boolean asBool(String value) { return asBoolean(value); } + /** + * Convert to BigInteger (not nullable). + */ + public static BigInteger asBigInteger(String value) { + checkNull(value); + try { + return new BigInteger(value); + } catch (RuntimeException e) { + throw new InvalidPathArgumentException(e); + } + } + /** * Convert to BigDecimal (not nullable). */ diff --git a/http-generator-core/src/main/java/io/avaje/http/generator/core/TypeMap.java b/http-generator-core/src/main/java/io/avaje/http/generator/core/TypeMap.java index c092c37fa..35fa5a6cb 100644 --- a/http-generator-core/src/main/java/io/avaje/http/generator/core/TypeMap.java +++ b/http-generator-core/src/main/java/io/avaje/http/generator/core/TypeMap.java @@ -34,6 +34,7 @@ private static void add(TypeHandler h) { add(new UuidHandler()); add(new BigDecimalHandler()); + add(new BigDecimalHandler()); add(new LocalDateHandler()); add(new LocalTimeHandler()); add(new LocalDateTimeHandler()); @@ -269,6 +270,12 @@ static class BigDecimalHandler extends ObjectHandler { } } + static class BigIntegerHandler extends ObjectHandler { + BigIntegerHandler() { + super("java.math.BigInteger", "BigInteger"); + } + } + static class LocalDateHandler extends ObjectHandler { LocalDateHandler() { super("java.time.LocalDate", "LocalDate"); From c556c7bd71d1db2891bf25b548ad4338182ff3b0 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Tue, 12 Sep 2023 19:35:24 -0400 Subject: [PATCH 2/6] Update README.md --- README.md | 57 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 11d0a8698..ebacbb423 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ public class WidgetController { } ``` ## DI Usage -The annotation processor will generate controller adapters to 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 examples below do; they use [Avaje-Inject](https://avaje.io/inject/) to do this. The AP will automatically detect the presence of avaje-inject and generate the class to use avaje-inject's `@Component` as the DI annotation. +The annotation processor will generate controller adapters to register routes to Javalin/Helidon. The natural way to use the generated adapters is to get a DI library to find and wire them. The AP will automatically detect the presence of avaje-inject and generate the class to use avaje-inject's `@Component` as the DI annotation. There isn't a hard requirement to use Avaje for dependency injection. In the absence of avaje-inject, the generated class will use `@jakarta.inject.Singleton` or `@javax.inject.Singleton` depending on what's on the classpath. 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. @@ -93,22 +93,20 @@ To force the AP to generate with `@javax.inject.Singleton`(in the case where you ### Usage with Javalin -The annotation processor will generate controller classes implementing the Javalin `Plugin` interface, which means we can -get all the WebRoutes and register them with Javalin using: +The annotation processor will generate controller classes implementing the Javalin `Plugin` interface, which means we can register them with Javalin using: ```java -List routes = BeanScope.builder().build().list(Plugin.class); +List routes = ...; //retrieve using a DI framework Javalin.create(cfg -> routes.forEach(cfg.plugins::register)).start(); ``` -### Usage with Helidon Nima +### Usage with Helidon SE (4.x) -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`. +The annotation processor will generate controller classes implementing the Helidon HttpFeature interface, which we can register with the Helidon `HttpRouting`. ```java -List routes = BeanScope.builder().build().list(HttpFeature.class); +List routes = ... //retrieve using a DI framework final var builder = HttpRouting.builder(); routes.forEach(builder::addFeature); @@ -153,14 +151,15 @@ public class WidgetController$Route implements Plugin { } ``` -### (Helidon Nima) The generated WidgetController$Route.java is: +### (Helidon SE) The generated WidgetController$Route.java is: ```java -@Generated("avaje-helidon-nima-generator") -@Singleton +@Generated("avaje-helidon-generator") +@Component public class WidgetController$Route implements HttpFeature { private final WidgetController controller; + public WidgetController$Route(WidgetController controller) { this.controller = controller; } @@ -172,17 +171,19 @@ public class WidgetController$Route implements HttpFeature { } private void _getById(ServerRequest req, ServerResponse res) throws Exception { + res.status(OK_200); var pathParams = req.path().pathParameters(); - int id = asInt(pathParams.first("id").get()); + var 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(); + private void _getAll(ServerRequest req, ServerResponse res) throws Exception { + res.status(OK_200); var result = controller.getAll(); res.send(result); } + } ``` @@ -225,21 +226,21 @@ public class WidgetController$Route implements Plugin { } ``` -### (Helidon Nima) The generated WidgetController$Route.java is: +### (Helidon SE) The generated WidgetController$Route.java is: ```java -@Generated("avaje-helidon-nima-generator") +@Generated("avaje-helidon-generator") @Component public class WidgetController$Route implements HttpFeature { private final WidgetController controller; - private final JsonType widgetJsonType; - private final JsonType> listWidgetJsonType; + private final JsonType widgetController$WidgetJsonType; + private final JsonType> listWidgetController$WidgetJsonType; - public WidgetController$Route(WidgetController controller, Jsonb jsonB) { + public WidgetController$Route(WidgetController controller, Jsonb jsonb) { this.controller = controller; - this.widgetJsonType = jsonB.type(Widget.class); - this.listWidgetJsonType = jsonB.type(Widget.class).list(); + this.widgetController$WidgetJsonType = jsonb.type(WidgetController.Widget.class); + this.listWidgetController$WidgetJsonType = jsonb.type(WidgetController.Widget.class).list(); } @Override @@ -249,18 +250,20 @@ public class WidgetController$Route implements HttpFeature { } private void _getById(ServerRequest req, ServerResponse res) throws Exception { + res.status(OK_200); var pathParams = req.path().pathParameters(); - int id = asInt(pathParams.first("id").get()); + var id = asInt(pathParams.first("id").get()); var result = controller.getById(id); - res.headers().contentType(HttpMediaType.APPLICATION_JSON); - widgetJsonType.toJson(result, JsonOutput.of(res)); + res.headers().contentType(MediaTypes.APPLICATION_JSON); + widgetController$WidgetJsonType.toJson(result, JsonOutput.of(res)); } private void _getAll(ServerRequest req, ServerResponse res) throws Exception { - var pathParams = req.path().pathParameters(); + res.status(OK_200); var result = controller.getAll(); - res.headers().contentType(HttpMediaType.APPLICATION_JSON); - listWidgetJsonType.toJson(result, JsonOutput.of(res)); + res.headers().contentType(MediaTypes.APPLICATION_JSON); + listWidgetController$WidgetJsonType.toJson(result, JsonOutput.of(res)); } + } ``` From 0896582a386325a0bd441e795b924d8a0d122421 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Tue, 12 Sep 2023 19:35:49 -0400 Subject: [PATCH 3/6] move status writing higher up --- .../generator/helidon/nima/ControllerMethodWriter.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/http-generator-helidon/src/main/java/io/avaje/http/generator/helidon/nima/ControllerMethodWriter.java b/http-generator-helidon/src/main/java/io/avaje/http/generator/helidon/nima/ControllerMethodWriter.java index 9a33f1b14..e6f9c13df 100644 --- a/http-generator-helidon/src/main/java/io/avaje/http/generator/helidon/nima/ControllerMethodWriter.java +++ b/http-generator-helidon/src/main/java/io/avaje/http/generator/helidon/nima/ControllerMethodWriter.java @@ -103,7 +103,12 @@ void writeHandler(boolean requestScoped) { writer.append(" private void _%s(FilterChain chain, RoutingRequest req, RoutingResponse res) {", method.simpleName()).eol(); } else { writer.append(" private void _%s(ServerRequest req, ServerResponse res) throws Exception {", method.simpleName()).eol(); + int statusCode = method.statusCode(); + if (statusCode > 0) { + writer.append(" res.status(%s);", lookupStatusCode(statusCode)).eol(); + } } + final var bodyType = method.bodyType(); if (bodyType != null && !method.isErrorMethod() && !isFilter) { if ("InputStream".equals(bodyType)) { @@ -253,10 +258,6 @@ private boolean usesFormParams() { } private void writeContextReturn() { - int statusCode = method.statusCode(); - if (statusCode > 0) { - writer.append(" res.status(%s);", lookupStatusCode(statusCode)).eol(); - } final var producesOp = Optional.ofNullable(method.produces()); if (producesOp.isEmpty() && !useJsonB) { return; From 223afb4cba1a0d5a1ccb414880df55253e971b44 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Tue, 12 Sep 2023 19:40:37 -0400 Subject: [PATCH 4/6] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ebacbb423..21fbdde48 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ public class WidgetController { ## DI Usage The annotation processor will generate controller adapters to register routes to Javalin/Helidon. The natural way to use the generated adapters is to get a DI library to find and wire them. The AP will automatically detect the presence of avaje-inject and generate the class to use avaje-inject's `@Component` as the DI annotation. -There isn't a hard requirement to use Avaje for dependency injection. In the absence of avaje-inject, the generated class will use `@jakarta.inject.Singleton` or `@javax.inject.Singleton` depending on what's on the classpath. 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. +There isn't a hard requirement to use [Avaje](https://avaje.io/inject/) for dependency injection. In the absence of avaje-inject, the generated class will use `@jakarta.inject.Singleton` or `@javax.inject.Singleton` depending on what's on the classpath. 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. To force the AP to generate with `@javax.inject.Singleton`(in the case where you have both jakarta and javax on the classpath), use the compiler arg `-AuseJavax=true` ```xml From b60cac98b0639013a96009473d72dce42cf31770 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Tue, 12 Sep 2023 19:54:40 -0400 Subject: [PATCH 5/6] Update ControllerMethodWriter.java --- .../http/generator/helidon/nima/ControllerMethodWriter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/http-generator-helidon/src/main/java/io/avaje/http/generator/helidon/nima/ControllerMethodWriter.java b/http-generator-helidon/src/main/java/io/avaje/http/generator/helidon/nima/ControllerMethodWriter.java index e6f9c13df..1d71a7491 100644 --- a/http-generator-helidon/src/main/java/io/avaje/http/generator/helidon/nima/ControllerMethodWriter.java +++ b/http-generator-helidon/src/main/java/io/avaje/http/generator/helidon/nima/ControllerMethodWriter.java @@ -103,6 +103,9 @@ void writeHandler(boolean requestScoped) { writer.append(" private void _%s(FilterChain chain, RoutingRequest req, RoutingResponse res) {", method.simpleName()).eol(); } else { writer.append(" private void _%s(ServerRequest req, ServerResponse res) throws Exception {", method.simpleName()).eol(); + } + + if (!isFilter) { int statusCode = method.statusCode(); if (statusCode > 0) { writer.append(" res.status(%s);", lookupStatusCode(statusCode)).eol(); From 5b0c0a0580f13063929338037ba4a750bf4a7c79 Mon Sep 17 00:00:00 2001 From: Josiah Noel <32279667+SentryMan@users.noreply.github.com> Date: Tue, 12 Sep 2023 21:42:32 -0400 Subject: [PATCH 6/6] Update PathTypeConversion.java --- .../java/io/avaje/http/api/PathTypeConversion.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/http-api/src/main/java/io/avaje/http/api/PathTypeConversion.java b/http-api/src/main/java/io/avaje/http/api/PathTypeConversion.java index eff727720..1cd272f20 100644 --- a/http-api/src/main/java/io/avaje/http/api/PathTypeConversion.java +++ b/http-api/src/main/java/io/avaje/http/api/PathTypeConversion.java @@ -309,6 +309,20 @@ public static BigDecimal toBigDecimal(String value) { } } + /** + * Convert to BigInteger (allowing nulls). + */ + public static BigInteger toBigInteger(String value) { + if (isNullOrEmpty(value)) { + return null; + } + try { + return new BigInteger(value); + } catch (Exception e) { + throw new InvalidTypeArgumentException(e); + } + } + /** * Convert to Boolean (allowing nulls). */