REST framework offering the route model to define non blocking endpoints
—
System for extracting request data including path parameters, query parameters, HTTP headers, and request body content with automatic type conversion and validation support.
Injects request parameters (path parameters and query parameters) into route method parameters with automatic type conversion support.
/**
* Injects request parameters into method parameters
* Supports path parameters (from route path) and query parameters
* @param value Parameter name, or ELEMENT_NAME constant for automatic naming
*/
@Param("parameterName")
// Supported parameter types:
// - String: Direct parameter value
// - Optional<String>: Optional parameter value
// - List<String>: Multiple parameter values
public static final String ELEMENT_NAME = "<<element name>>";Usage Examples:
import io.quarkus.vertx.web.Route;
import io.quarkus.vertx.web.Param;
import java.util.Optional;
import java.util.List;
@ApplicationScoped
public class ParameterExamples {
// Path parameter injection
@Route(path = "/users/:userId", methods = HttpMethod.GET)
public String getUser(@Param("userId") String userId) {
return "User ID: " + userId;
}
// Multiple path parameters
@Route(path = "/users/:userId/posts/:postId", methods = HttpMethod.GET)
public String getUserPost(
@Param("userId") String userId,
@Param("postId") String postId
) {
return "User: " + userId + ", Post: " + postId;
}
// Query parameter injection
@Route(path = "/search", methods = HttpMethod.GET)
public String search(
@Param("q") String query,
@Param("limit") Optional<String> limit,
@Param("sort") Optional<String> sortOrder
) {
int limitValue = limit.map(Integer::parseInt).orElse(10);
return "Query: " + query + ", Limit: " + limitValue;
}
// Multiple values for same parameter
@Route(path = "/filter", methods = HttpMethod.GET)
public String filter(@Param("category") List<String> categories) {
return "Categories: " + String.join(", ", categories);
}
// Automatic parameter name resolution
@Route(path = "/auto/:name", methods = HttpMethod.GET)
public String autoParam(@Param(Param.ELEMENT_NAME) String name) {
// Parameter name automatically resolved from method parameter name
return "Name: " + name;
}
}Injects HTTP headers into route method parameters with support for single and multiple header values.
/**
* Injects HTTP headers into method parameters
* @param value Header name, or ELEMENT_NAME constant for automatic naming
*/
@Header("headerName")
// Supported parameter types:
// - String: Single header value
// - Optional<String>: Optional header value
// - List<String>: Multiple header values (for headers that can appear multiple times)
public static final String ELEMENT_NAME = "<<element name>>";Usage Examples:
import io.quarkus.vertx.web.Header;
@ApplicationScoped
public class HeaderExamples {
// Single header injection
@Route(path = "/protected", methods = HttpMethod.GET)
public String protectedEndpoint(@Header("Authorization") String authHeader) {
if (authHeader.startsWith("Bearer ")) {
return "Authorized";
}
return "Unauthorized";
}
// Optional header injection
@Route(path = "/content", methods = HttpMethod.GET)
public String getContent(
@Header("Accept") Optional<String> acceptHeader,
@Header("User-Agent") Optional<String> userAgent
) {
String accept = acceptHeader.orElse("*/*");
String agent = userAgent.orElse("Unknown");
return "Accept: " + accept + ", User-Agent: " + agent;
}
// Multiple header values
@Route(path = "/cors", methods = HttpMethod.OPTIONS)
public String handleCors(@Header("Access-Control-Request-Headers") List<String> requestHeaders) {
return "Requested headers: " + String.join(", ", requestHeaders);
}
// Custom headers
@Route(path = "/api/data", methods = HttpMethod.GET)
public String getData(
@Header("X-API-Key") String apiKey,
@Header("X-Request-ID") Optional<String> requestId
) {
String reqId = requestId.orElse("generated-id");
return "API Key: " + apiKey + ", Request ID: " + reqId;
}
}Injects request body content into route method parameters with automatic deserialization support for various content types.
/**
* Injects request body into method parameters
* Supports automatic deserialization based on content type
*/
@Body
// Supported parameter types:
// - io.vertx.core.buffer.Buffer: Raw body content
// - String: Body as string
// - io.vertx.core.json.JsonObject: JSON object body
// - io.vertx.core.json.JsonArray: JSON array body
// - Custom objects: Automatic JSON deserialization via JacksonUsage Examples:
import io.quarkus.vertx.web.Body;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonObject;
import io.vertx.core.json.JsonArray;
@ApplicationScoped
public class BodyExamples {
// String body injection
@Route(path = "/text", methods = HttpMethod.POST, consumes = "text/plain")
public String handleText(@Body String textContent) {
return "Received text: " + textContent;
}
// Raw buffer body injection
@Route(path = "/binary", methods = HttpMethod.POST, consumes = "application/octet-stream")
public String handleBinary(@Body Buffer binaryData) {
return "Received " + binaryData.length() + " bytes";
}
// JSON object body injection
@Route(path = "/json", methods = HttpMethod.POST, consumes = "application/json")
public String handleJsonObject(@Body JsonObject jsonData) {
String name = jsonData.getString("name", "Unknown");
return "Received JSON with name: " + name;
}
// JSON array body injection
@Route(path = "/batch", methods = HttpMethod.POST, consumes = "application/json")
public String handleJsonArray(@Body JsonArray jsonArray) {
return "Received array with " + jsonArray.size() + " items";
}
// Custom object body injection (automatic JSON deserialization)
@Route(path = "/users", methods = HttpMethod.POST, consumes = "application/json")
public String createUser(@Body User user) {
return "Created user: " + user.getName() + " (" + user.getEmail() + ")";
}
// Complex object with nested properties
@Route(path = "/orders", methods = HttpMethod.POST, consumes = "application/json")
public String createOrder(@Body Order order) {
return "Created order for " + order.getCustomer().getName() +
" with " + order.getItems().size() + " items";
}
}
// Example domain classes for JSON deserialization
public class User {
private String name;
private String email;
private int age;
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
public class Order {
private Customer customer;
private List<OrderItem> items;
private BigDecimal total;
// Getters and setters
public Customer getCustomer() { return customer; }
public void setCustomer(Customer customer) { this.customer = customer; }
public List<OrderItem> getItems() { return items; }
public void setItems(List<OrderItem> items) { this.items = items; }
public BigDecimal getTotal() { return total; }
public void setTotal(BigDecimal total) { this.total = total; }
}Multiple injection types can be combined in a single method for comprehensive request data access.
@Route(path = "/api/users/:userId", methods = HttpMethod.PUT, consumes = "application/json")
public String updateUser(
@Param("userId") String userId, // Path parameter
@Param("version") Optional<String> version, // Query parameter
@Header("Authorization") String authHeader, // HTTP header
@Header("Content-Type") String contentType, // Content type header
@Body User updatedUser // Request body
) {
// Validate authorization
if (!authHeader.startsWith("Bearer ")) {
return "Unauthorized";
}
// Check version for optimistic locking
int versionNum = version.map(Integer::parseInt).orElse(1);
// Update user logic
return "Updated user " + userId + " to version " + (versionNum + 1);
}While the reactive routes extension doesn't provide built-in validation, it integrates well with Bean Validation (JSR-303) annotations:
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Email;
@Route(path = "/users", methods = HttpMethod.POST, consumes = "application/json")
public String createUser(@Valid @Body User user) {
return "Created valid user: " + user.getName();
}
public class User {
@NotNull
private String name;
@Email
private String email;
// Getters and setters with validation annotations
}The extension automatically handles type conversion for basic types when using @Param:
// String to numeric conversion
@Route(path = "/items/:id", methods = HttpMethod.GET)
public String getItem(@Param("id") String itemId) {
long id = Long.parseLong(itemId); // Manual conversion needed
return "Item: " + id;
}
// Boolean parameter handling
@Route(path = "/search", methods = HttpMethod.GET)
public String search(
@Param("q") String query,
@Param("includeInactive") Optional<String> includeInactive
) {
boolean includeFlag = includeInactive
.map("true"::equalsIgnoreCase)
.orElse(false);
return "Search: " + query + ", Include inactive: " + includeFlag;
}Install with Tessl CLI
npx tessl i tessl/maven-io-quarkus--quarkus-reactive-routes