Deployment artifact for Quarkus Reactive Routes extension that enables declarative, non-blocking HTTP endpoint creation using @Route annotations
npx @tessl/cli install tessl/maven-io-quarkus--quarkus-reactive-routes-deployment@3.26.0A deployment artifact for the Quarkus Reactive Routes extension that enables declarative, non-blocking HTTP endpoint creation using @Route annotations. This module provides build-time processing and code generation for reactive HTTP routing in Quarkus applications.
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-routes-deployment</artifactId>
<version>3.26.2</version>
</dependency>// Core deployment classes
import io.quarkus.vertx.web.deployment.ReactiveRoutesProcessor;
import io.quarkus.vertx.web.deployment.ReactiveRoutesMethodsProcessor;
import io.quarkus.vertx.web.deployment.AnnotatedRouteHandlerBuildItem;
import io.quarkus.vertx.web.deployment.AnnotatedRouteFilterBuildItem;
import io.quarkus.vertx.web.deployment.HandlerDescriptor;
import io.quarkus.vertx.web.deployment.DotNames;
import io.quarkus.vertx.web.deployment.Methods;
// Jandex annotation processing
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodParameterInfo;
// Quarkus build system
import io.quarkus.arc.processor.BeanInfo;
import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.annotations.ExecutionTime;
// Reactive types
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.Multi;
// Vert.x types
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.RoutingContext;
// Build items
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.vertx.http.deployment.FilterBuildItem;
import io.quarkus.vertx.http.deployment.RouteBuildItem;This is a build-time extension module that processes @Route annotations and generates runtime routing code. It's not used directly in application code but rather consumed by the Quarkus build pipeline when processing reactive routes.
// In a Quarkus extension processor
@BuildStep
void processCustomRoutes(
List<AnnotatedRouteHandlerBuildItem> routeHandlers,
BuildProducer<RouteBuildItem> routes) {
for (AnnotatedRouteHandlerBuildItem handler : routeHandlers) {
// Process route handler build items
BeanInfo bean = handler.getBean();
MethodInfo method = handler.getMethod();
List<AnnotationInstance> routes = handler.getRoutes();
// Custom processing logic...
}
}The deployment module follows Quarkus's build-time processing architecture:
The processor transforms declarative @Route annotations into optimized runtime code, eliminating reflection overhead and enabling native compilation.
Main build processors that handle route annotation discovery, validation, and code generation during Quarkus build pipeline execution.
class ReactiveRoutesProcessor {
@BuildStep
FeatureBuildItem feature();
@BuildStep
void unremovableBeans(BuildProducer<UnremovableBeanBuildItem> unremovableBeans);
@BuildStep
void validateBeanDeployment(
BeanArchiveIndexBuildItem beanArchive,
ValidationPhaseBuildItem validationPhase,
TransformedAnnotationsBuildItem transformedAnnotations,
BuildProducer<AnnotatedRouteHandlerBuildItem> routeHandlerBusinessMethods,
BuildProducer<AnnotatedRouteFilterBuildItem> routeFilterBusinessMethods,
BuildProducer<ValidationErrorBuildItem> errors,
VertxHttpBuildTimeConfig httpBuildTimeConfig);
@BuildStep
@Record(value = ExecutionTime.STATIC_INIT)
void replaceDefaultAuthFailureHandler(
VertxWebRecorder recorder,
Capabilities capabilities,
BuildProducer<FilterBuildItem> filterBuildItemBuildProducer);
@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
void addAdditionalRoutes(
VertxWebRecorder recorder,
List<AnnotatedRouteHandlerBuildItem> routeHandlerBusinessMethods,
List<AnnotatedRouteFilterBuildItem> routeFilterBusinessMethods,
BuildProducer<GeneratedClassBuildItem> generatedClass,
BuildProducer<GeneratedResourceBuildItem> generatedResource,
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses,
BuildProducer<ReflectiveHierarchyBuildItem> reflectiveHierarchy,
BodyHandlerBuildItem bodyHandler,
BuildProducer<RouteBuildItem> routeProducer,
BuildProducer<FilterBuildItem> filterProducer,
List<RequireBodyHandlerBuildItem> bodyHandlerRequired,
BeanArchiveIndexBuildItem beanArchive,
TransformedAnnotationsBuildItem transformedAnnotations,
ShutdownContextBuildItem shutdown,
LaunchModeBuildItem launchMode,
BuildProducer<RouteDescriptionBuildItem> descriptions,
Capabilities capabilities,
Optional<BeanValidationAnnotationsBuildItem> beanValidationAnnotations,
List<ApplicationClassPredicateBuildItem> predicates);
@BuildStep
AutoAddScopeBuildItem autoAddScope();
}
class ReactiveRoutesMethodsProcessor {
@BuildStep
ExecutionModelAnnotationsAllowedBuildItem reactiveRoutesMethods();
}Build items represent discovered route handlers and filters that can be consumed by other build processors.
class AnnotatedRouteHandlerBuildItem extends MultiBuildItem {
AnnotatedRouteHandlerBuildItem(
BeanInfo bean,
MethodInfo method,
List<AnnotationInstance> routes,
AnnotationInstance routeBase);
AnnotatedRouteHandlerBuildItem(
BeanInfo bean,
MethodInfo method,
List<AnnotationInstance> routes,
AnnotationInstance routeBase,
boolean blocking,
HttpCompression compression,
boolean alwaysAuthenticateRoute);
BeanInfo getBean();
MethodInfo getMethod();
List<AnnotationInstance> getRoutes();
AnnotationInstance getRouteBase();
boolean isBlocking();
boolean shouldAlwaysAuthenticateRoute();
HttpCompression getCompression();
}
public final class AnnotatedRouteFilterBuildItem extends MultiBuildItem {
public AnnotatedRouteFilterBuildItem(
BeanInfo bean,
MethodInfo method,
AnnotationInstance routeFilter);
public BeanInfo getBean();
public MethodInfo getMethod();
public AnnotationInstance getRouteFilter();
}Describes request handlers for code generation, including return types, validation requirements, and payload analysis.
class HandlerDescriptor {
HandlerDescriptor(
MethodInfo method,
BeanValidationAnnotationsBuildItem bvAnnotations,
boolean failureHandler,
String[] producedTypes);
Type getReturnType();
boolean isReturningUni();
boolean isReturningMulti();
boolean isReturningCompletionStage();
String getFirstContentType();
boolean requireValidation();
boolean isProducedResponseValidated();
Type getPayloadType();
boolean isPayloadString();
boolean isPayloadBuffer();
boolean isPayloadMutinyBuffer();
boolean isFailureHandler();
}Annotation and type name constants used during build-time processing for efficient type checking and matching.
class DotNames {
// Reactive types
static final DotName UNI;
static final DotName MULTI;
static final DotName COMPLETION_STAGE;
// Buffer types
static final DotName BUFFER;
static final DotName MUTINY_BUFFER;
// HTTP types
static final DotName HTTP_SERVER_REQUEST;
static final DotName HTTP_SERVER_RESPONSE;
static final DotName MUTINY_HTTP_SERVER_REQUEST;
static final DotName MUTINY_HTTP_SERVER_RESPONSE;
// Routing types
static final DotName ROUTING_CONTEXT;
static final DotName ROUTING_EXCHANGE;
// Route annotations
static final DotName ROUTE;
static final DotName ROUTES;
static final DotName ROUTE_BASE;
static final DotName ROUTE_FILTER;
// Parameter annotations
static final DotName BODY;
static final DotName HEADER;
static final DotName PARAM;
// JSON types
static final DotName JSON_OBJECT;
static final DotName JSON_ARRAY;
// Execution annotations
static final DotName BLOCKING;
static final DotName RUN_ON_VIRTUAL_THREAD;
// Compression annotations
static final DotName COMPRESSED;
static final DotName UNCOMPRESSED;
// Collection and exception types
static final DotName LIST;
static final DotName EXCEPTION;
static final DotName THROWABLE;
}Utility methods and constants for generating efficient bytecode using Gizmo during build-time processing.
class Methods {
// HTTP method descriptors
static final MethodDesc REQUEST;
static final MethodDesc RESPONSE;
static final MethodDesc GET_BODY;
static final MethodDesc GET_BODY_AS_STRING;
static final MethodDesc GET_BODY_AS_JSON;
static final MethodDesc GET_BODY_AS_JSON_ARRAY;
static final MethodDesc REQUEST_GET_PARAM;
static final MethodDesc REQUEST_GET_HEADER;
// Reactive method descriptors
static final MethodDesc UNI_SUBSCRIBE;
static final MethodDesc UNI_SUBSCRIBE_WITH;
static final MethodDesc MULTI_SUBSCRIBE_VOID;
static final MethodDesc MULTI_SUBSCRIBE_STRING;
static final MethodDesc MULTI_SUBSCRIBE_BUFFER;
static final MethodDesc MULTI_SUBSCRIBE_MUTINY_BUFFER;
static final MethodDesc MULTI_SUBSCRIBE_OBJECT;
// CDI method descriptors
static final MethodDesc ARC_CONTAINER;
static final MethodDesc ARC_CONTAINER_GET_ACTIVE_CONTEXT;
static final MethodDesc ARC_CONTAINER_BEAN;
static final MethodDesc BEAN_GET_SCOPE;
static final MethodDesc CONTEXT_GET;
static final MethodDesc CONTEXT_GET_IF_PRESENT;
// Validation method descriptors
static final MethodDesc VALIDATOR_VALIDATE;
static final MethodDesc VALIDATION_GET_VALIDATOR;
static final MethodDesc VALIDATION_HANDLE_VIOLATION;
// Utility methods
static boolean isNoContent(HandlerDescriptor descriptor);
static Expr createNpeItemIsNull(BlockCreator bc);
static MethodDesc getEndMethodForContentType(HandlerDescriptor descriptor);
static void setContentTypeToJson(Var response, BlockCreator b0);
static Var validateProducedItem(
Var response,
BlockCreator b0,
Var res,
Expr this_,
FieldDesc validatorField);
}The processor validates route methods and produces detailed error messages for:
This deployment module integrates with:
// Build items
abstract class MultiBuildItem {}
// Build producers for generating build items
interface BuildProducer<T> {
void produce(T item);
}
// Jandex annotation and type model
interface AnnotationInstance {
DotName name();
AnnotationValue value();
AnnotationValue value(String name);
AnnotationValue valueWithDefault(IndexView index, String name);
String toString(boolean simple);
}
interface MethodInfo {
String name();
Type returnType();
List<Type> parameterTypes();
List<MethodParameterInfo> parameters();
int parametersCount();
ClassInfo declaringClass();
List<AnnotationInstance> annotations();
boolean hasDeclaredAnnotation(DotName name);
boolean isSynthetic();
int flags();
}
interface BeanInfo {
ClassInfo getTarget();
String getIdentifier();
Class<?> getScope();
ClassInfo getImplClazz();
ClassInfo getBeanClass();
}
interface Type {
DotName name();
Kind kind();
ParameterizedType asParameterizedType();
enum Kind {
CLASS, PARAMETERIZED_TYPE, VOID
}
}
// Bytecode generation types
interface BlockCreator {
LocalVar localVar(String name, Expr value);
Expr invokeInterface(MethodDesc method, Expr... args);
Expr invokeStatic(MethodDesc method, Expr... args);
Expr invokeVirtual(MethodDesc method, Expr instance, Expr... args);
void ifNull(Expr condition, Consumer<BlockCreator> thenBlock);
void ifNotNull(Expr condition, Consumer<BlockCreator> thenBlock);
void ifElse(Expr condition, Consumer<BlockCreator> thenBlock, Consumer<BlockCreator> elseBlock);
void set(Var variable, Expr value);
void return_();
}
interface Expr {
boolean isVoid();
ClassDesc getType();
}
interface Var extends Expr {
FieldVar field(FieldDesc field);
}
// HTTP and validation types
enum HttpCompression {
UNDEFINED, ON, OFF
}
// Build-time configuration
interface VertxHttpBuildTimeConfig {
AuthConfig auth();
interface AuthConfig {
boolean proactive();
}
}
// Additional Gizmo2 bytecode generation types used in Methods class
interface InterfaceMethodDesc extends MethodDesc {}
final class MethodTypeDesc {
static MethodTypeDesc of(ClassDesc returnType, ClassDesc... paramTypes);
}
final class FieldDesc {
static FieldDesc of(ClassDesc owner, String name, ClassDesc type);
}
final class ConstructorDesc {
static ConstructorDesc of(Class<?> owner, Class<?>... paramTypes);
}
interface UniSubscribe {}
interface Cancellable {}
// Multi support runtime classes
class MultiSupport {}
class MultiSseSupport {}
class MultiNdjsonSupport {}
class MultiJsonArraySupport {}
class ValidationSupport {}
class RouteHandlers {}interface ParameterInjector {
boolean matches(Type paramType, Set<AnnotationInstance> paramAnnotations, IndexView index);
Route.HandlerType getTargetHandlerType();
void validate(BeanInfo bean, MethodInfo method, AnnotationInstance routeInstance,
Type paramType, Set<AnnotationInstance> paramAnnotations);
Expr getValue(MethodParameterInfo methodParam, Set<AnnotationInstance> annotations,
Var routingContext, BlockCreator bc,
BuildProducer<ReflectiveHierarchyBuildItem> reflectiveHierarchy);
static Builder builder() { return new Builder(); }
class Builder {
Builder matchType(DotName className);
Builder matchType(Type type);
Builder matchOptionalOf(DotName className);
Builder matchListOf(DotName className);
Builder skipType(DotName className);
Builder requireAnnotations(DotName... names);
Builder valueProvider(ValueProvider provider);
Builder targetHandlerType(Route.HandlerType handlerType);
Builder validate(ParamValidator validator);
Builder canEndResponse();
ParameterInjector build();
}
}
@FunctionalInterface
interface ValueProvider {
Expr get(MethodParameterInfo methodParam, Set<AnnotationInstance> annotations,
Var routingContext, BlockCreator bc,
BuildProducer<ReflectiveHierarchyBuildItem> reflectiveHierarchy);
}
@FunctionalInterface
interface ParamValidator {
void validate(BeanInfo bean, MethodInfo method, AnnotationInstance routeAnnotation,
Type paramType, Set<AnnotationInstance> paramAnnotations);
}
@FunctionalInterface
interface TriPredicate<A, B, C> {
boolean test(A a, B b, C c);
}