diff --git a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/Methods.java b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/Methods.java index 947e157b76c01..ed63d6c1eb430 100644 --- a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/Methods.java +++ b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/Methods.java @@ -172,10 +172,6 @@ private Methods() { // Avoid direct instantiation } - static void fail(BytecodeCreator creator, ResultHandle rc, ResultHandle exception) { - creator.invokeInterfaceMethod(FAIL, rc, exception); - } - static void returnAndClose(BytecodeCreator creator) { creator.returnValue(null); creator.close(); diff --git a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java index 05c551858da16..cca73832f3c8e 100644 --- a/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java +++ b/extensions/vertx-web/deployment/src/main/java/io/quarkus/vertx/web/deployment/VertxWebProcessor.java @@ -84,6 +84,7 @@ import io.quarkus.vertx.web.runtime.RouteHandler; import io.quarkus.vertx.web.runtime.RouteMatcher; import io.quarkus.vertx.web.runtime.RoutingExchangeImpl; +import io.quarkus.vertx.web.runtime.UniFailureCallback; import io.quarkus.vertx.web.runtime.VertxWebRecorder; import io.vertx.core.Handler; import io.vertx.core.http.HttpMethod; @@ -557,11 +558,11 @@ void implementInvoke(HandlerDescriptor descriptor, BeanInfo bean, MethodInfo met // If the provided item is not null, and it's an object, the item is mapped to JSON and written into the response FunctionCreator successCallback = getUniOnItemCallback(descriptor, invoke, routingContext, end, response); - FunctionCreator failureCallback = getUniOnFailureCallback(invoke, routingContext); + ResultHandle failureCallback = getUniOnFailureCallback(invoke, routingContext); ResultHandle sub = invoke.invokeInterfaceMethod(Methods.UNI_SUBSCRIBE, res); invoke.invokeVirtualMethod(Methods.UNI_SUBSCRIBE_WITH, sub, successCallback.getInstance(), - failureCallback.getInstance()); + failureCallback); } else if (descriptor.isReturningMulti()) { // 3 cases - regular multi vs. sse multi vs. json array multi, we need to check the type. @@ -756,23 +757,10 @@ private FunctionCreator getUniOnItemCallback(HandlerDescriptor descriptor, Metho return callback; } - /** - * Generates the following function: - * - *
-     *     throwable -> rc.fail(throwable);
-     * 
- * - * @param writer the bytecode writer - * @param rc the reference to the RoutingContext variable - * @return the function creator. - */ - private FunctionCreator getUniOnFailureCallback(MethodCreator writer, ResultHandle rc) { - FunctionCreator callback = writer.createFunction(Consumer.class); - BytecodeCreator creator = callback.getBytecode(); - Methods.fail(creator, rc, creator.getMethodParam(0)); - Methods.returnAndClose(creator); - return callback; + private ResultHandle getUniOnFailureCallback(MethodCreator writer, ResultHandle routingContext) { + // new UniFailureCallback(ctx) + return writer.newInstance(MethodDescriptor.ofConstructor(UniFailureCallback.class, RoutingContext.class), + routingContext); } private ResultHandle getContentToWrite(HandlerDescriptor descriptor, ResultHandle response, ResultHandle res, @@ -1119,9 +1107,17 @@ public ResultHandle get(MethodInfo method, Type paramType, Set annotations, ResultHandle routingContext, MethodCreator invoke, int position) { - return invoke.invokeVirtualMethod(Methods.JSON_OBJECT_MAP_TO, - invoke.invokeInterfaceMethod(Methods.GET_BODY_AS_JSON, routingContext), - invoke.loadClass(paramType.name().toString())); + AssignableResultHandle ret = invoke.createVariable(Object.class); + ResultHandle bodyAsJson = invoke.invokeInterfaceMethod(Methods.GET_BODY_AS_JSON, + routingContext); + BranchResult bodyIfNotNull = invoke.ifNotNull(bodyAsJson); + BytecodeCreator bodyNotNull = bodyIfNotNull.trueBranch(); + bodyNotNull.assign(ret, bodyNotNull.invokeVirtualMethod(Methods.JSON_OBJECT_MAP_TO, + bodyAsJson, + invoke.loadClass(paramType.name().toString()))); + BytecodeCreator bodyNull = bodyIfNotNull.falseBranch(); + bodyNull.assign(ret, bodyNull.loadNull()); + return ret; } }).build()); diff --git a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Header.java b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Header.java index d70b8366d70d9..7133a3cf37bc6 100644 --- a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Header.java +++ b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Header.java @@ -11,7 +11,8 @@ * Identifies a route method parameter that should be injected with a value returned from * {@link HttpServerRequest#getHeader(String)}. *

- * The parameter type must be {@link String} or {@code Optional}, otherwise the build fails. + * The parameter type must be {@link String}, {@code java.util.Optional} or {@code java.util.List}, otherwise + * the build fails. * * @see HttpServerRequest#getHeader(String) */ diff --git a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Param.java b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Param.java index 05f8663b18141..67cdd08afde54 100644 --- a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Param.java +++ b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Param.java @@ -11,7 +11,8 @@ * Identifies a route method parameter that should be injected with a value returned from * {@link HttpServerRequest#getParam(String)}. *

- * The parameter type must be {@link String} or {@code Optional}, otherwise the build fails. + * The parameter type must be {@link String}, {@code java.util.Optional} or {@code java.util.List}, otherwise + * the build fails. * * @see HttpServerRequest#getParam(String) */ diff --git a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Route.java b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Route.java index d4221b7252e7f..634e29dc11065 100644 --- a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Route.java +++ b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/Route.java @@ -26,6 +26,47 @@ *

  • {@code io.vertx.reactivex.core.http.HttpServerRequest}
  • *
  • {@code io.vertx.reactivex.core.http.HttpServerResponse}
  • * + * Furthermore, it is possible to inject the request parameters into a method parameter annotated with + * {@link io.quarkus.vertx.web.Param}: + * + *
    + * 
    + *  class Routes {
    + *      {@literal @Route}
    + *      String hello({@literal @Param Optional} name) {
    + *         return "Hello " + name.orElse("world");
    + *     }
    + *  }
    + *  
    + * 
    + * + * The request headers can be injected into a method parameter annotated with {@link io.quarkus.vertx.web.Header}: + * + *
    + * 
    + *  class Routes {
    + *     {@literal @Route}
    + *     String helloFromHeader({@literal @Header("My-Header")} String header) {
    + *         return "Hello " + header;
    + *     }
    + *  }
    + *  
    + * 
    + * + * The request body can be injected into a method parameter annotated with {@link io.quarkus.vertx.web.Body}: + * + *
    + * 
    + *  class Routes {
    + *     {@literal @Route(produces = "application/json")}
    + *     Person updatePerson({@literal @Body} Person person) {
    + *        person.setName("Bob");
    + *        return person;
    + *     }
    + *  }
    + *  
    + * 
    + * * If the annotated method returns {@code void} then it has to accept at least one argument. * If the annotated method does not return {@code void} then the arguments are optional. *

    diff --git a/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/UniFailureCallback.java b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/UniFailureCallback.java new file mode 100644 index 0000000000000..c2ecb5acaa96b --- /dev/null +++ b/extensions/vertx-web/runtime/src/main/java/io/quarkus/vertx/web/runtime/UniFailureCallback.java @@ -0,0 +1,20 @@ +package io.quarkus.vertx.web.runtime; + +import java.util.function.Consumer; + +import io.vertx.ext.web.RoutingContext; + +public final class UniFailureCallback implements Consumer { + + private final RoutingContext context; + + public UniFailureCallback(RoutingContext context) { + this.context = context; + } + + @Override + public void accept(Throwable t) { + context.fail(t); + } + +}