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 utility interfaces for resource metadata access and resource cleanup.
import org.jboss.resteasy.reactive.server.SimpleResourceInfo;
import io.quarkus.resteasy.reactive.server.Closer;
import jakarta.ws.rs.core.Context;Lightweight interface providing resource method metadata.
public interface SimpleResourceInfo {
Class<?> getResourceClass(); // Resource class containing the method
String getMethodName(); // Method name
Class<?>[] parameterTypes(); // Parameter types array
}@ServerRequestFilter
public Optional<Response> filter(SimpleResourceInfo resourceInfo) {
Class<?> resourceClass = resourceInfo.getResourceClass();
String methodName = resourceInfo.getMethodName();
Class<?>[] paramTypes = resourceInfo.parameterTypes();
logger.info("Executing {}.{}({})",
resourceClass.getSimpleName(),
methodName,
Arrays.toString(paramTypes)
);
return Optional.empty();
}@ServerExceptionMapper
public Response mapException(
BusinessException ex,
SimpleResourceInfo resourceInfo
) {
ErrorResponse error = new ErrorResponse();
error.setMessage(ex.getMessage());
error.setResource(resourceInfo.getResourceClass().getSimpleName());
error.setMethod(resourceInfo.getMethodName());
return Response.status(400).entity(error).build();
}@ServerRequestFilter
public Optional<Response> filter(SimpleResourceInfo resourceInfo) {
// Apply logic only to specific resources
if (resourceInfo.getResourceClass().equals(AdminResource.class)) {
if (!securityService.isAdmin()) {
return Optional.of(Response.status(403).build());
}
}
return Optional.empty();
}Interface for registering resources to be closed after request completion.
public interface Closer {
/**
* Register a new Closeable that is to be closed when the request completes.
*/
void add(Closeable closeable);
}@GET
@Path("/{id}/download")
public Response download(@RestPath String id, @Context Closer closer) throws IOException {
InputStream stream = fileService.openStream(id);
// Register for automatic cleanup
closer.add(stream);
return Response.ok(stream)
.type("application/octet-stream")
.build();
}@GET
@Path("/combined")
public Response getCombined(@Context Closer closer) throws IOException {
InputStream stream1 = service1.openStream();
InputStream stream2 = service2.openStream();
Connection conn = database.getConnection();
// Register all for cleanup
closer.add(stream1);
closer.add(stream2);
closer.add(conn);
CombinedData data = processStreams(stream1, stream2, conn);
return Response.ok(data).build();
}@GET
@Path("/query")
public Response query(@RestQuery String sql, @Context Closer closer) throws SQLException {
Connection conn = dataSource.getConnection();
closer.add(conn);
Statement stmt = conn.createStatement();
closer.add(stmt);
ResultSet rs = stmt.executeQuery(sql);
closer.add(rs);
List<Map<String, Object>> results = processResultSet(rs);
return Response.ok(results).build();
}public class CustomResource implements Closeable {
@Override
public void close() throws IOException {
// Cleanup logic
}
}
@GET
@Path("/custom")
public Response getCustom(@Context Closer closer) {
CustomResource resource = new CustomResource();
closer.add(resource);
Data data = resource.getData();
return Response.ok(data).build();
}SimpleResourceInfo is a lightweight alternative to JAX-RS's ResourceInfo:
| Feature | SimpleResourceInfo | ResourceInfo |
|---|---|---|
| Resource class | ✅ getResourceClass() | ✅ getResourceClass() |
| Method info | ✅ getMethodName(), parameterTypes() | ✅ getResourceMethod() (full Method object) |
| Performance | ✅ Lightweight | ❌ Heavier (full reflection) |
| Use case | Filters, mappers | Complex reflection needs |
Use SimpleResourceInfo unless you need full Method reflection:
// SimpleResourceInfo (preferred for filters)
@ServerRequestFilter
public void filter(SimpleResourceInfo info) {
String methodName = info.getMethodName();
}
// ResourceInfo (for complex reflection)
@ServerRequestFilter
public void filter(ResourceInfo info) {
Method method = info.getResourceMethod();
Annotation[] annotations = method.getAnnotations();
}Resources registered with Closer are guaranteed to be closed:
@GET
public Response get(@Context Closer closer) {
Closeable first = openFirst();
closer.add(first);
Closeable second = openSecond();
closer.add(second);
// Closed in order: second, then first
return Response.ok().build();
}Closer complements try-with-resources for response streaming:
// Don't use try-with-resources for response streaming
@GET
public Response streamBad(@Context Closer closer) {
try (InputStream stream = openStream()) {
// BAD: Stream closed before response sent
return Response.ok(stream).build();
}
}
// Use Closer instead
@GET
public Response streamGood(@Context Closer closer) {
InputStream stream = openStream();
closer.add(stream); // Closed after response sent
return Response.ok(stream).build();
}Closer logs but doesn't throw exceptions during cleanup:
@GET
public Response get(@Context Closer closer) {
Closeable resource = new Closeable() {
@Override
public void close() throws IOException {
throw new IOException("Close failed");
}
};
closer.add(resource);
// Close exception is logged, not thrown
return Response.ok().build();
}