Skip to content

Commit

Permalink
Merge pull request #10871 from mkouba/issue-10858
Browse files Browse the repository at this point in the history
  • Loading branch information
cescoffier authored Jul 21, 2020
2 parents 96ece8e + 53ad1e8 commit e8b0e4b
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -756,23 +757,10 @@ private FunctionCreator getUniOnItemCallback(HandlerDescriptor descriptor, Metho
return callback;
}

/**
* Generates the following function:
*
* <pre>
* throwable -> rc.fail(throwable);
* </pre>
*
* @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,
Expand Down Expand Up @@ -1119,9 +1107,17 @@ public ResultHandle get(MethodInfo method, Type paramType, Set<AnnotationInstanc
public ResultHandle get(MethodInfo method, Type paramType, Set<AnnotationInstance> 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());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
* Identifies a route method parameter that should be injected with a value returned from
* {@link HttpServerRequest#getHeader(String)}.
* <p>
* The parameter type must be {@link String} or {@code Optional<String>}, otherwise the build fails.
* The parameter type must be {@link String}, {@code java.util.Optional<String>} or {@code java.util.List<String>}, otherwise
* the build fails.
*
* @see HttpServerRequest#getHeader(String)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
* Identifies a route method parameter that should be injected with a value returned from
* {@link HttpServerRequest#getParam(String)}.
* <p>
* The parameter type must be {@link String} or {@code Optional<String>}, otherwise the build fails.
* The parameter type must be {@link String}, {@code java.util.Optional<String>} or {@code java.util.List<String>}, otherwise
* the build fails.
*
* @see HttpServerRequest#getParam(String)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,47 @@
* <li>{@code io.vertx.reactivex.core.http.HttpServerRequest}</li>
* <li>{@code io.vertx.reactivex.core.http.HttpServerResponse}</li>
* </ul>
* Furthermore, it is possible to inject the request parameters into a method parameter annotated with
* {@link io.quarkus.vertx.web.Param}:
*
* <pre>
* <code>
* class Routes {
* {@literal @Route}
* String hello({@literal @Param Optional<String>} name) {
* return "Hello " + name.orElse("world");
* }
* }
* </code>
* </pre>
*
* The request headers can be injected into a method parameter annotated with {@link io.quarkus.vertx.web.Header}:
*
* <pre>
* <code>
* class Routes {
* {@literal @Route}
* String helloFromHeader({@literal @Header("My-Header")} String header) {
* return "Hello " + header;
* }
* }
* </code>
* </pre>
*
* The request body can be injected into a method parameter annotated with {@link io.quarkus.vertx.web.Body}:
*
* <pre>
* <code>
* class Routes {
* {@literal @Route(produces = "application/json")}
* Person updatePerson({@literal @Body} Person person) {
* person.setName("Bob");
* return person;
* }
* }
* </code>
* </pre>
*
* 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.
* <p>
Expand Down
Original file line number Diff line number Diff line change
@@ -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<Throwable> {

private final RoutingContext context;

public UniFailureCallback(RoutingContext context) {
this.context = context;
}

@Override
public void accept(Throwable t) {
context.fail(t);
}

}

0 comments on commit e8b0e4b

Please sign in to comment.