Skip to content

Commit

Permalink
Merge pull request #20192 from cescoffier/fire-mutiny-router
Browse files Browse the repository at this point in the history
Expose Mutiny variant of the Router
  • Loading branch information
mkouba authored Sep 17, 2021
2 parents 459ebf4 + 0030389 commit 4a3c380
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 50 deletions.
9 changes: 9 additions & 0 deletions docs/src/main/asciidoc/reactive-routes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,15 @@ Check the https://vertx.io/docs/vertx-web/java/#_basic_vert_x_web_concepts[Vert.
If you use `quarkus-resteasy` or `quarkus-reactive-routes`, the extension will be added automatically.
====
You can also receive the Mutiny variant of the Router (`io.vertx.mutiny.ext.web.Router`):
[source,java]
----
public void init(@Observes io.vertx.mutiny.ext.web.Router router) {
router.get("/my-route").handler(rc -> rc.response().endAndForget("Hello from my route"));
}
----
== Intercepting HTTP requests
You can also register filters that would intercept incoming HTTP requests.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.util.function.Function;

import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.vertx.http.runtime.RouterProducer;
import io.vertx.core.Handler;
import io.vertx.core.http.HttpMethod;
import io.vertx.ext.web.Router;
Expand All @@ -18,7 +17,7 @@ public Handler<RoutingContext> createHandler(String handlerClassName) {
try {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
cl = RouterProducer.class.getClassLoader();
cl = VertxWebRecorder.class.getClassLoader();
}
Class<? extends Handler<RoutingContext>> handlerClazz = (Class<? extends Handler<RoutingContext>>) cl
.loadClass(handlerClassName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import java.util.Optional;

import io.quarkus.arc.deployment.BeanContainerBuildItem;
import io.quarkus.builder.item.SimpleBuildItem;
import io.quarkus.deployment.Capabilities;
import io.quarkus.deployment.Capability;
Expand Down Expand Up @@ -72,7 +71,6 @@ public void boot(ShutdownContextBuildItem shutdown,
BuildProducer<DefaultRouteBuildItem> defaultRoutes,
BuildProducer<RouteBuildItem> routes,
CoreVertxBuildItem vertx,
BeanContainerBuildItem beanContainer,
ResteasyStandaloneBuildItem standalone,
Optional<RequireVirtualHttpBuildItem> requireVirtual,
ExecutorBuildItem executorBuildItem,
Expand All @@ -86,7 +84,7 @@ public void boot(ShutdownContextBuildItem shutdown,

// Handler used for both the default and non-default deployment path (specified as application path or resteasyConfig.path)
// Routes use the order VertxHttpRecorder.DEFAULT_ROUTE_ORDER + 1 to ensure the default route is called before the resteasy one
Handler<RoutingContext> handler = recorder.vertxRequestHandler(vertx.getVertx(), beanContainer.getValue(),
Handler<RoutingContext> handler = recorder.vertxRequestHandler(vertx.getVertx(),
executorBuildItem.getExecutorProxy(), httpConfiguration, resteasyVertxConfig);
// Exact match for resources matched to the root path
routes.produce(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.quarkus.arc.runtime.BeanContainer;
import io.quarkus.resteasy.runtime.ResteasyVertxConfig;
import io.quarkus.runtime.ShutdownContext;
import io.quarkus.runtime.annotations.Recorder;
Expand Down Expand Up @@ -52,10 +51,10 @@ public void run() {
useDirect = !isVirtual;
}

public Handler<RoutingContext> vertxRequestHandler(Supplier<Vertx> vertx,
BeanContainer beanContainer, Executor executor, HttpConfiguration readTimeout, ResteasyVertxConfig config) {
public Handler<RoutingContext> vertxRequestHandler(Supplier<Vertx> vertx, Executor executor, HttpConfiguration readTimeout,
ResteasyVertxConfig config) {
if (deployment != null) {
return new VertxRequestHandler(vertx.get(), beanContainer, deployment, contextPath,
return new VertxRequestHandler(vertx.get(), deployment, contextPath,
new ResteasyVertxAllocator(config.responseBufferSize), executor,
readTimeout.readTimeout.toMillis());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
import org.jboss.resteasy.spi.Failure;
import org.jboss.resteasy.spi.ResteasyDeployment;

import io.quarkus.arc.Arc;
import io.quarkus.arc.ManagedContext;
import io.quarkus.arc.runtime.BeanContainer;
import io.quarkus.resteasy.runtime.ContextUtil;
import io.quarkus.runtime.BlockingOperationControl;
import io.quarkus.security.identity.CurrentIdentityAssociation;
Expand All @@ -45,19 +45,16 @@ public class VertxRequestHandler implements Handler<RoutingContext> {
protected final RequestDispatcher dispatcher;
protected final String rootPath;
protected final BufferAllocator allocator;
protected final BeanContainer beanContainer;
protected final CurrentIdentityAssociation association;
protected final CurrentVertxRequest currentVertxRequest;
protected final Executor executor;
protected final long readTimeout;

public VertxRequestHandler(Vertx vertx,
BeanContainer beanContainer,
ResteasyDeployment deployment,
String rootPath,
BufferAllocator allocator, Executor executor, long readTimeout) {
this.vertx = vertx;
this.beanContainer = beanContainer;
this.dispatcher = new RequestDispatcher((SynchronousDispatcher) deployment.getDispatcher(),
deployment.getProviderFactory(), null, Thread.currentThread().getContextClassLoader());
this.rootPath = rootPath;
Expand Down Expand Up @@ -101,7 +98,7 @@ public void run() {
}

private void dispatch(RoutingContext routingContext, InputStream is, VertxOutput output) {
ManagedContext requestContext = beanContainer.requestContext();
ManagedContext requestContext = Arc.container().requestContext();
requestContext.activate();
routingContext.remove(QuarkusHttpUser.AUTH_FAILURE_HANDLER);
if (association != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.quarkus.vertx.http.deployment;

import io.quarkus.builder.item.SimpleBuildItem;
import io.quarkus.runtime.RuntimeValue;
import io.vertx.ext.web.Router;

final class InitialRouterBuildItem extends SimpleBuildItem {

private final RuntimeValue<Router> httpRouter;
private final RuntimeValue<io.vertx.mutiny.ext.web.Router> mutinyRouter;

public InitialRouterBuildItem(RuntimeValue<Router> httpRouter, RuntimeValue<io.vertx.mutiny.ext.web.Router> mutinyRouter) {
this.httpRouter = httpRouter;
this.mutinyRouter = mutinyRouter;
}

public RuntimeValue<Router> getHttpRouter() {
return httpRouter;
}

public RuntimeValue<io.vertx.mutiny.ext.web.Router> getMutinyRouter() {
return mutinyRouter;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.deployment.BeanContainerBuildItem;
import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
import io.quarkus.arc.processor.BuiltinScope;
import io.quarkus.bootstrap.util.ZipUtils;
import io.quarkus.builder.BuildException;
import io.quarkus.deployment.annotations.BuildProducer;
Expand Down Expand Up @@ -53,7 +55,6 @@
import io.quarkus.vertx.http.runtime.HttpBuildTimeConfig;
import io.quarkus.vertx.http.runtime.HttpConfiguration;
import io.quarkus.vertx.http.runtime.HttpHostConfigSource;
import io.quarkus.vertx.http.runtime.RouterProducer;
import io.quarkus.vertx.http.runtime.VertxHttpRecorder;
import io.quarkus.vertx.http.runtime.attribute.ExchangeAttributeBuilder;
import io.quarkus.vertx.http.runtime.cors.CORSRecorder;
Expand Down Expand Up @@ -96,7 +97,6 @@ FilterBuildItem cors(CORSRecorder recorder, HttpConfiguration configuration) {
AdditionalBeanBuildItem additionalBeans() {
return AdditionalBeanBuildItem.builder()
.setUnremovable()
.addBeanClass(RouterProducer.class)
.addBeanClass(CurrentVertxRequest.class)
.addBeanClass(CurrentRequestProducer.class)
.build();
Expand Down Expand Up @@ -132,16 +132,38 @@ void notFoundRoutes(
}
}

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
void preinitializeRouter(CoreVertxBuildItem vertx, VertxHttpRecorder recorder,
BuildProducer<InitialRouterBuildItem> initialRouter, BuildProducer<SyntheticBeanBuildItem> syntheticBeans) {
// We need to initialize the routers that are exposed as synthetic beans in a separate build step to avoid cycles in the build chain
RuntimeValue<Router> httpRouteRouter = recorder.initializeRouter(vertx.getVertx());
RuntimeValue<io.vertx.mutiny.ext.web.Router> mutinyRouter = recorder.createMutinyRouter(httpRouteRouter);
initialRouter.produce(new InitialRouterBuildItem(httpRouteRouter, mutinyRouter));

// Also note that we need a client proxy to handle the use case where a bean also @Observes Router
syntheticBeans.produce(SyntheticBeanBuildItem.configure(Router.class)
.scope(BuiltinScope.APPLICATION.getInfo())
.setRuntimeInit()
.runtimeValue(httpRouteRouter).done());
syntheticBeans.produce(SyntheticBeanBuildItem.configure(io.vertx.mutiny.ext.web.Router.class)
.scope(BuiltinScope.APPLICATION.getInfo())
.setRuntimeInit()
.runtimeValue(mutinyRouter).done());
}

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
VertxWebRouterBuildItem initializeRouter(VertxHttpRecorder recorder,
InitialRouterBuildItem initialRouter,
CoreVertxBuildItem vertx,
List<RouteBuildItem> routes,
HttpBuildTimeConfig httpBuildTimeConfig,
NonApplicationRootPathBuildItem nonApplicationRootPath,
ShutdownContextBuildItem shutdown) {

RuntimeValue<Router> httpRouteRouter = recorder.initializeRouter(vertx.getVertx());
RuntimeValue<Router> httpRouteRouter = initialRouter.getHttpRouter();
RuntimeValue<io.vertx.mutiny.ext.web.Router> mutinyRouter = initialRouter.getMutinyRouter();
RuntimeValue<Router> frameworkRouter = null;
RuntimeValue<Router> mainRouter = null;

Expand Down Expand Up @@ -182,7 +204,7 @@ VertxWebRouterBuildItem initializeRouter(VertxHttpRecorder recorder,
}
}

return new VertxWebRouterBuildItem(httpRouteRouter, mainRouter, frameworkRouter);
return new VertxWebRouterBuildItem(httpRouteRouter, mainRouter, frameworkRouter, mutinyRouter);
}

@BuildStep
Expand Down Expand Up @@ -258,6 +280,7 @@ ServiceStartBuildItem finalizeRouter(
recorder.finalizeRouter(beanContainer.getValue(),
defaultRoute.map(DefaultRouteBuildItem::getRoute).orElse(null),
listOfFilters, vertx.getVertx(), lrc, mainRouter, httpRouteRouter.getHttpRouter(),
httpRouteRouter.getMutinyRouter(),
httpRootPathBuildItem.getRootPath(),
launchMode.getLaunchMode(),
!requireBodyHandlerBuildItems.isEmpty(), bodyHandler, httpConfiguration, gracefulShutdownFilter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,27 @@

public final class VertxWebRouterBuildItem extends SimpleBuildItem {

private RuntimeValue<Router> httpRouter;
private RuntimeValue<Router> mainRouter;
private RuntimeValue<Router> frameworkRouter;
private final RuntimeValue<Router> httpRouter;
private final RuntimeValue<Router> mainRouter;
private final RuntimeValue<Router> frameworkRouter;
private final RuntimeValue<io.vertx.mutiny.ext.web.Router> mutinyRouter;

VertxWebRouterBuildItem(RuntimeValue<Router> httpRouter, RuntimeValue<Router> mainRouter,
RuntimeValue<Router> frameworkRouter) {
RuntimeValue<Router> frameworkRouter, RuntimeValue<io.vertx.mutiny.ext.web.Router> mutinyRouter) {
this.httpRouter = httpRouter;
this.mainRouter = mainRouter;
this.frameworkRouter = frameworkRouter;
this.mutinyRouter = mutinyRouter;
}

public RuntimeValue<Router> getHttpRouter() {
return httpRouter;
}

public RuntimeValue<io.vertx.mutiny.ext.web.Router> getMutinyRouter() {
return mutinyRouter;
}

/**
* Will be {@code null} if `${quarkus.http.root-path}` is {@literal /}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,21 @@ public class UserRouteRegistrationTest {
@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(BeanRegisteringRouteUsingObserves.class, BeanRegisteringRouteUsingInject.class));
.addClasses(BeanRegisteringRouteUsingObserves.class,
BeanRegisteringRouteUsingObservesWithMutinyRouter.class,
BeanRegisteringRouteUsingInject.class,
BeanRegisteringRouteUsingInjectWithMutinyRouter.class));

@Test
public void test() {
assertThat(RestAssured.get("/observes").asString()).isEqualTo("observers - ok");
assertThat(RestAssured.get("/observes-mutiny").asString()).isEqualTo("observers mutiny - ok");
assertThat(RestAssured.get("/inject").asString()).isEqualTo("inject - ok");
assertThat(RestAssured.get("/inject-mutiny").asString()).isEqualTo("inject mutiny - ok");
assertThat(given().body("test").contentType("text/plain").post("/body").asString()).isEqualTo("test");
assertThat(given().body("test mutiny").contentType("text/plain").post("/body-mutiny").asString())
.isEqualTo("test mutiny");

}

@ApplicationScoped
Expand All @@ -41,6 +49,15 @@ public void register(@Observes Router router) {

}

@ApplicationScoped
static class BeanRegisteringRouteUsingObservesWithMutinyRouter {

public void register(@Observes io.vertx.mutiny.ext.web.Router router) {
router.route("/observes-mutiny").handler(rc -> rc.response().endAndForget("observers mutiny - ok"));
}

}

@ApplicationScoped
static class BeanRegisteringRouteUsingInject {

Expand All @@ -55,4 +72,18 @@ public void register(@Observes StartupEvent ignored) {
}

}

@ApplicationScoped
static class BeanRegisteringRouteUsingInjectWithMutinyRouter {

@Inject
io.vertx.mutiny.ext.web.Router router;

public void register(@Observes StartupEvent ignored) {
router.route("/inject-mutiny").handler(rc -> rc.response().endAndForget("inject mutiny - ok"));
router.route("/body-mutiny").consumes("text/plain").handler(io.vertx.mutiny.ext.web.handler.BodyHandler.create())
.handler(rc -> rc.response().endAndForget(rc.getBodyAsString()));
}

}
}
4 changes: 4 additions & 0 deletions extensions/vertx-http/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>smallrye-mutiny-vertx-web</artifactId>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ public RuntimeValue<Router> initializeRouter(final Supplier<Vertx> vertxRuntimeV
return new RuntimeValue<>(router);
}

public RuntimeValue<io.vertx.mutiny.ext.web.Router> createMutinyRouter(final RuntimeValue<Router> router) {
return new RuntimeValue<>(new io.vertx.mutiny.ext.web.Router(router.getValue()));
}

public void startServer(Supplier<Vertx> vertx, ShutdownContext shutdown,
HttpBuildTimeConfig httpBuildTimeConfig, HttpConfiguration httpConfiguration,
LaunchMode launchMode,
Expand Down Expand Up @@ -271,7 +275,8 @@ public void mountFrameworkRouter(RuntimeValue<Router> mainRouter, RuntimeValue<R
public void finalizeRouter(BeanContainer container, Consumer<Route> defaultRouteHandler,
List<Filter> filterList, Supplier<Vertx> vertx,
LiveReloadConfig liveReloadConfig, Optional<RuntimeValue<Router>> mainRouterRuntimeValue,
RuntimeValue<Router> httpRouterRuntimeValue, String rootPath, LaunchMode launchMode, boolean requireBodyHandler,
RuntimeValue<Router> httpRouterRuntimeValue, RuntimeValue<io.vertx.mutiny.ext.web.Router> mutinyRouter,
String rootPath, LaunchMode launchMode, boolean requireBodyHandler,
Handler<RoutingContext> bodyHandler, HttpConfiguration httpConfiguration,
GracefulShutdownFilter gracefulShutdownFilter, ShutdownConfig shutdownConfig,
Executor executor) {
Expand All @@ -289,6 +294,8 @@ public void finalizeRouter(BeanContainer container, Consumer<Route> defaultRoute

// Then, fire the resuming router
event.select(Router.class).fire(httpRouteRouter);
// Also fires the Mutiny one
event.select(io.vertx.mutiny.ext.web.Router.class).fire(mutinyRouter.getValue());

for (Filter filter : filterList) {
if (filter.getHandler() != null) {
Expand All @@ -301,7 +308,6 @@ public void finalizeRouter(BeanContainer container, Consumer<Route> defaultRoute
defaultRouteHandler.accept(httpRouteRouter.route().order(DEFAULT_ROUTE_ORDER));
}

container.instance(RouterProducer.class).initialize(httpRouteRouter);
httpRouteRouter.route().last().failureHandler(new QuarkusErrorHandler(launchMode.isDevOrTest()));

if (requireBodyHandler) {
Expand Down

0 comments on commit 4a3c380

Please sign in to comment.