docs
reference
tessl install tessl/maven-io-quarkus--quarkus-resteasy-reactive@3.15.0A Jakarta REST implementation utilizing build time processing and Vert.x for high-performance REST endpoints with reactive capabilities in cloud-native environments.
Quarkus REST provides several advanced integration points for framework developers and extension authors. These APIs are primarily used for custom integrations, observability, and low-level framework customization.
import io.quarkus.resteasy.reactive.server.runtime.ResteasyReactiveInitialiser;
import io.quarkus.resteasy.reactive.server.runtime.QuarkusContextProducers;
import io.quarkus.resteasy.reactive.server.runtime.observability.ObservabilityCustomizer;
import org.jboss.resteasy.reactive.server.core.Deployment;
import org.jboss.resteasy.reactive.server.spi.ServerRestHandler;
import org.jboss.resteasy.reactive.server.handlers.ServerResourceMethod;
import org.jboss.resteasy.reactive.server.model.HandlerChainCustomizer;
import org.jboss.resteasy.reactive.server.model.HandlerChainCustomizer.Phase;Interface for generated static initialization calls during application startup.
/**
* Interface for generated static init calls
* Typically used by Quarkus extensions for custom initialization
*/
public interface ResteasyReactiveInitialiser {
/**
* Initialize the deployment with custom configuration
* @param deployment The RESTEasy Reactive deployment
*/
void init(Deployment deployment);
}CDI producers for injectable REST context objects.
/**
* CDI producers for @Context-injectable objects
* Provides standard Jakarta REST context objects as CDI beans
*/
public class QuarkusContextProducers {
/**
* Produces HttpServerResponse for request-scoped injection
* @return Current HTTP server response
*/
@Produces
@RequestScoped
HttpServerResponse httpServerResponse();
/**
* Produces Providers for application-scoped injection
* @return Providers instance for looking up providers
*/
@Produces
@ApplicationScoped
Providers providers();
/**
* Produces Closer for request-scoped resource cleanup
* @return Closer instance for registering closeables
*/
@Produces
@RequestScoped
Closer closer();
}Handler chain customizer for integrating observability features (metrics, tracing, etc.).
/**
* HandlerChainCustomizer for observability integration
* Used by Quarkus extensions to add observability handlers
*/
public class ObservabilityCustomizer implements HandlerChainCustomizer {
/**
* Provide handlers for specific phases of request processing
* @param phase The processing phase
* @param resourceClass The resource class being processed
* @param serverResourceMethod The resource method being processed
* @return List of handlers to add to the chain
*/
List<ServerRestHandler> handlers(
Phase phase,
ResourceClass resourceClass,
ServerResourceMethod serverResourceMethod
);
}Create a custom initialiser for framework-level setup:
import io.quarkus.resteasy.reactive.server.runtime.ResteasyReactiveInitialiser;
import org.jboss.resteasy.reactive.server.core.Deployment;
public class CustomInitialiser implements ResteasyReactiveInitialiser {
@Override
public void init(Deployment deployment) {
// Custom deployment initialization
System.out.println("Initializing custom REST deployment");
// Access deployment configuration
var config = deployment.getApplicationSupplier();
// Register custom handlers, filters, etc.
// This is typically done by Quarkus extensions
}
}Extend context producers for custom injectable objects:
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import jakarta.enterprise.context.RequestScoped;
@ApplicationScoped
public class CustomContextProducers {
@Produces
@RequestScoped
public CustomContext produceCustomContext() {
// Provide custom context object
return new CustomContext();
}
}Implement a custom observability handler:
import io.quarkus.resteasy.reactive.server.runtime.observability.ObservabilityCustomizer;
import org.jboss.resteasy.reactive.server.spi.ServerRestHandler;
import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext;
public class CustomObservabilityHandler implements ServerRestHandler {
@Override
public void handle(ResteasyReactiveRequestContext requestContext) {
// Record metrics, start spans, etc.
long startTime = System.nanoTime();
try {
// Process request
requestContext.resume();
} finally {
// Record duration
long duration = System.nanoTime() - startTime;
// Report to metrics system
recordMetric(requestContext.getMethod(), duration);
}
}
private void recordMetric(String method, long duration) {
// Implementation specific
}
}Create a custom handler chain customizer:
import org.jboss.resteasy.reactive.server.model.HandlerChainCustomizer;
import org.jboss.resteasy.reactive.server.spi.ServerRestHandler;
import java.util.List;
@ApplicationScoped
public class CustomHandlerCustomizer implements HandlerChainCustomizer {
@Override
public List<ServerRestHandler> handlers(
Phase phase,
ResourceClass resourceClass,
ServerResourceMethod serverResourceMethod
) {
if (phase == Phase.AFTER_METHOD_INVOKE) {
// Add custom post-processing handler
return List.of(new CustomPostProcessingHandler());
}
return List.of();
}
}Use ResteasyReactiveInitialiser to access deployment metadata:
public class DeploymentInspector implements ResteasyReactiveInitialiser {
@Override
public void init(Deployment deployment) {
// Inspect registered resources
var resources = deployment.getResourceClasses();
for (var resource : resources) {
System.out.println("Resource: " + resource.getClassName());
// Inspect methods
for (var method : resource.getMethods()) {
System.out.println(" Method: " + method.getName());
System.out.println(" Path: " + method.getPath());
System.out.println(" HTTP Method: " + method.getHttpMethod());
}
}
}
}Handlers can be added at different phases of request processing:
public enum Phase {
BEFORE_METHOD_INVOKE, // Before resource method execution
AFTER_METHOD_INVOKE, // After resource method execution
RESOLVED, // After method resolution
AFTER_MATCH; // After path matching
}@ApplicationScoped
public class PhaseAwareCustomizer implements HandlerChainCustomizer {
@Override
public List<ServerRestHandler> handlers(
Phase phase,
ResourceClass resourceClass,
ServerResourceMethod serverResourceMethod
) {
return switch (phase) {
case BEFORE_METHOD_INVOKE -> List.of(new PreInvokeHandler());
case AFTER_METHOD_INVOKE -> List.of(new PostInvokeHandler());
case RESOLVED -> List.of(new ResolvedHandler());
case AFTER_MATCH -> List.of(new MatchHandler());
};
}
}These APIs are primarily for Quarkus extension developers:
// In a Quarkus extension's processor class
@BuildStep
void registerInitialiser(BuildProducer<ResteasyReactiveInitialiserBuildItem> producer) {
producer.produce(new ResteasyReactiveInitialiserBuildItem(
CustomInitialiser.class.getName()
));
}For metrics, tracing, and monitoring:
@ApplicationScoped
public class MetricsCustomizer implements HandlerChainCustomizer {
@Inject
MeterRegistry registry;
@Override
public List<ServerRestHandler> handlers(
Phase phase,
ResourceClass resourceClass,
ServerResourceMethod serverResourceMethod
) {
if (phase == Phase.BEFORE_METHOD_INVOKE) {
return List.of(new MetricsHandler(registry, serverResourceMethod));
}
return List.of();
}
}Handlers execute in the order they're added:
@Override
public List<ServerRestHandler> handlers(...) {
return List.of(
new FirstHandler(), // Executes first
new SecondHandler(), // Executes second
new ThirdHandler() // Executes third
);
}public class CustomAuthHandler implements ServerRestHandler {
@Override
public void handle(ResteasyReactiveRequestContext ctx) {
String authHeader = ctx.getHeader("Authorization", true);
if (authHeader == null || !isValid(authHeader)) {
ctx.setResult(Response.status(401).build());
return;
}
// Continue processing
ctx.resume();
}
private boolean isValid(String authHeader) {
// Validate token
return true;
}
}public class RequestLoggingHandler implements ServerRestHandler {
private static final Logger LOG = Logger.getLogger(RequestLoggingHandler.class);
@Override
public void handle(ResteasyReactiveRequestContext ctx) {
LOG.infof("Request: %s %s", ctx.getMethod(), ctx.getPath());
ctx.resume();
LOG.infof("Response: %d", ctx.getResponse().getStatus());
}
}public class CachingHandler implements ServerRestHandler {
private final Cache cache;
public CachingHandler(Cache cache) {
this.cache = cache;
}
@Override
public void handle(ResteasyReactiveRequestContext ctx) {
String cacheKey = ctx.getMethod() + ":" + ctx.getPath();
var cached = cache.get(cacheKey);
if (cached != null) {
ctx.setResult(cached);
return;
}
// Continue and cache result
ctx.resume();
cache.put(cacheKey, ctx.getResult());
}
}These APIs provide low-level access to the request processing pipeline. Use them carefully and ensure proper security measures are in place when modifying request/response handling.
Use these advanced integration points when:
For application-level logic, use standard filters (@ServerRequestFilter, @ServerResponseFilter) instead.