diff --git a/README.md b/README.md index 11d0a869..21fbdde4 100644 --- a/README.md +++ b/README.md @@ -74,9 +74,9 @@ 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. +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 @@ -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)); } + } ``` 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 49fb1619..1cd272f2 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). */ @@ -296,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). */ 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 c092c37f..35fa5a6c 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"); 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 9a33f1b1..1d71a749 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 @@ -104,6 +104,14 @@ void writeHandler(boolean requestScoped) { } 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(); + } + } + final var bodyType = method.bodyType(); if (bodyType != null && !method.isErrorMethod() && !isFilter) { if ("InputStream".equals(bodyType)) { @@ -253,10 +261,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;