CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-quarkus--quarkus-reactive-routes

REST framework offering the route model to define non blocking endpoints

Pending
Overview
Eval results
Files

parameter-injection.mddocs/

Parameter Injection

System for extracting request data including path parameters, query parameters, HTTP headers, and request body content with automatic type conversion and validation support.

Capabilities

@Param Annotation

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;
    }
}

@Header Annotation

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;
    }
}

@Body Annotation

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 Jackson

Usage 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; }
}

Combined Parameter Injection

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);
}

Parameter Validation

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
}

Type Conversion

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

docs

index.md

parameter-injection.md

reactive-streaming.md

request-context.md

request-filtering.md

route-declaration.md

tile.json