### Basic HTTP Client Setup and GET Request Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/quick-start.md Set up a basic HTTP client with a base URL and request timeout. Demonstrates a simple GET request to fetch a single product. ```java import io.avaje.http.client.*; HttpClient client = HttpClient.builder() .baseUrl("http://localhost:8080/api") .requestTimeout(Duration.ofSeconds(30)) .build(); // Simple GET request Product product = client.request() .path("products") .path(1) .GET() .bean(Product.class) .execute(); System.out.println("Product: " + product.getName()); ``` -------------------------------- ### Example Curl Request Source: https://github.com/avaje/avaje-http/blob/master/tests/test-javalin/README.md This is an example curl command to test the Javalin application's /hello endpoint. ```curl http://localhost:7000/hello/42/Roberto?otherParam=banana ``` -------------------------------- ### GET Request as String Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Demonstrates how to perform a synchronous GET request and receive the response body as a String. Requires an initialized HttpClient. ```java HttpClient client = HttpClient.builder() .baseUrl(baseUrl) .build(); HttpResponse hres = client.request() .path("hello") .GET() .asString(); ``` -------------------------------- ### Async GET Request as String Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Provides an example of making an asynchronous GET request and handling the response using CompletableFuture. The response is processed as a String. ```java client.request() .path("hello") .GET() .async().asString() // CompletableFuture> .whenComplete((hres, throwable) -> { if (throwable != null) { // CompletionException ... } else { // HttpResponse int statusCode = hres.statusCode(); String body = hres.body(); ... } }); ``` -------------------------------- ### Start Avaje HTTP Server with Javalin Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/quick-start.md Configure and start the Javalin server, integrating Avaje HTTP plugins for routing and dependency injection. Sets the server port and enables route overview. ```java package com.example; import io.avaje.inject.BeanScope; import io.avaje.http.api.AvajeJavalinPlugin; import io.javalin.Javalin; public class Server { public static void main(String[] args) { // Get generated DI component and retrieve route plugins BeanScope scope = BeanScope.builder().build(); List plugins = scope.list(AvajeJavalinPlugin.class); // Create and start Javalin app Javalin app = Javalin.create(cfg -> { plugins.forEach(cfg::registerPlugin); cfg.http.port = 8080; cfg.bundledPlugins.enableRouteOverview("/routes"); }).start(); System.out.println("Server started on http://localhost:8080"); System.out.println("View routes at http://localhost:8080/routes"); } } ``` -------------------------------- ### AuthToken Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/types.md Example of creating an AuthToken instance with a token string and expiry time. Ensure the token string is valid and the expiry is set appropriately. ```java AuthToken token = AuthToken.of( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", Instant.now().plusSeconds(3600) ); ``` -------------------------------- ### Client Interface Usage Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/annotations.md Example of an interface annotated with @Client, defining methods for HTTP GET and POST requests. ```java @Client public interface CustomerApi { @Get("/{id}") Customer getById(long id); @Get List getAll(); @Post long save(Customer customer); } ``` -------------------------------- ### RequestListener Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/types.md Implement RequestListener to track request lifecycle events like start, response time, and status codes. ```java class MetricsListener implements RequestListener { @Override public void onRequest(HttpClientRequest request) { // Track request start } @Override public void onResponse(HttpResponse response, HttpClientRequest request) { // Track response time, status codes } } HttpClient client = HttpClient.builder() .requestListener(new MetricsListener()) .build(); ``` -------------------------------- ### GET Request as String Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Performs a GET request and returns the response body as a String. No special setup is required beyond having an HTTP client instance. ```java HttpResponse hres = client.request() .path("hello") .GET() .asString(); ``` -------------------------------- ### Example HttpMethod Annotation: @Get Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/additional-types.md An example of a custom HTTP method annotation, @Get, derived from HttpMethod. It defaults to an empty string for the value. ```java @HttpMethod("GET") public @interface Get { String value() default ""; } ``` -------------------------------- ### HttpClient Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Demonstrates how to instantiate and configure an HttpClient with common settings like base URL, body adapter, request timeout, and a custom retry handler. ```java HttpClient client = HttpClient.builder() .baseUrl("http://api.example.com") .bodyAdapter(new JacksonBodyAdapter()) .requestTimeout(Duration.ofSeconds(30)) .retryHandler(new MyRetryHandler()) .build(); ``` -------------------------------- ### Define a REST Controller with GET Endpoints Source: https://github.com/avaje/avaje-http/blob/master/README.md Define a Java controller class annotated with `@Controller` and specify endpoints using `@Get` annotations. This example demonstrates fetching a single widget by ID and retrieving a list of all widgets. ```java package org.example.hello; import io.avaje.http.api.Controller; import io.avaje.http.api.Get; import java.util.List; @Controller("/widgets") public class WidgetController { private final HelloComponent hello; public WidgetController(HelloComponent hello) { this.hello = hello; } @Get("/{id}") Widget getById(int id) { return new Widget(id, "you got it"+ hello.hello()); } @Get() List getAll() { return List.of(new Widget(1, "Rob"), new Widget(2, "Fi")); } record Widget(int id, String name){}; } ``` -------------------------------- ### LoggingInterceptor Implementation Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Example of implementing RequestIntercept to log request and response details. ```java class LoggingInterceptor implements RequestIntercept { @Override public void beforeRequest(HttpClientRequest request) { System.out.println(">> " + request.method() + " " + request.url()); } @Override public void afterResponse(HttpResponse response, HttpClientRequest request) { System.out.println("<< " + response.statusCode()); } } ``` -------------------------------- ### Handle Specific Exception with Status Code Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/annotations.md Example of handling a NotFoundException and returning a 404 status code. ```java @ExceptionHandler(value = NotFoundException.class, statusCode = 404) ErrorResponse handleNotFound(NotFoundException e) { return new ErrorResponse("Resource not found", e.getMessage()); } ``` -------------------------------- ### Java @Body Annotation Usage Examples Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/annotations.md Examples demonstrating how to use the @Body annotation with different parameter types like List and Map for POST requests. ```java @Post("/filter") List filterByIds(@Body List ids) { return productService.findByIds(ids); } ``` ```java @Post("/search") List search(@Body Map criteria) { return productService.search(criteria); } ``` -------------------------------- ### Implement and Register AvajeJavalinPlugin Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/types.md Shows an example of a generated controller route handler extending AvajeJavalinPlugin and how to register these plugins with Javalin. ```java // Generated class (auto-created by annotation processor) @Singleton public class ProductController$Route extends AvajeJavalinPlugin { private final ProductController controller; @Override public void onStart(JavalinState state) { state.routes.get("/products/{id}", ctx -> { int id = Integer.parseInt(ctx.pathParam("id")); Product product = controller.getById(id); ctx.json(product); }); } } // Usage List plugins = ...; // Retrieved from DI container Javalin app = Javalin.create(cfg -> plugins.forEach(cfg::registerPlugin) ); ``` -------------------------------- ### Vert.x Server Runtime Configuration Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/configuration.md Configure and start a Vert.x server with Avaje HTTP routes. Register routes with the Vert.x router and specify the listening port. ```java List routes = ...; // Retrieved from DI container Router router = Router.router(vertx); routes.forEach(route -> route.register(router)); HttpServer server = vertx.createHttpServer() .requestHandler(router) .listen(8080); ``` -------------------------------- ### Async GET Request as String Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Performs an asynchronous GET request and handles the response using a CompletableFuture. Errors are wrapped in CompletionException. ```java client.request() .path("hello") .GET() .async().asString() .whenComplete((hres, throwable) -> { if (throwable != null) { // CompletionException ... } else { // HttpResponse int statusCode = hres.statusCode(); String body = hres.body(); ... } }); ``` -------------------------------- ### MatrixParam Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/additional-types.md Demonstrates how to use the @MatrixParam annotation to bind matrix parameters from a URL path to method arguments. ```java @Controller public class MatrixController { @Get("/items;color={color};size={size}") List getByAttributes( @MatrixParam String color, @MatrixParam String size ) { return itemService.findByAttributes(color, size); } } // Called with: GET /items;color=red;size=large ``` -------------------------------- ### StreamingOutput Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/types.md Example of returning StreamingOutput from a controller method to stream a PDF response. Ensure the generatePdf method is implemented. ```java @Get("/download/{id}") @Produces("application/pdf") StreamingOutput downloadPdf(long id) { return os -> { byte[] pdfBytes = generatePdf(id); os.write(pdfBytes); }; } ``` -------------------------------- ### Get All Widgets Source: https://github.com/avaje/avaje-http/blob/master/README.md Retrieves a list of all available widgets. ```APIDOC ## GET /widgets ### Description Retrieves a list of all widgets. ### Method GET ### Endpoint /widgets ### Response #### Success Response (200) - **List** (List) - A list of all widget objects. #### Response Example ```json [ { "id": 1, "name": "Widget One" }, { "id": 2, "name": "Widget Two" } ] ``` ``` -------------------------------- ### BodyReader Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/types.md Example of obtaining a BodyReader for a User class and using it to deserialize response bytes. Ensure the correct BodyAdapter is configured for the desired content type. ```java BodyReader reader = bodyAdapter.beanReader(User.class); User user = reader.read(responseBytes); ``` -------------------------------- ### Javalin Server Runtime Configuration Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/configuration.md Configure and start a Javalin server with Avaje HTTP routes. Set the HTTP port and enable bundled plugins like route overview and CORS. ```java List routes = ...; // Retrieved from DI container Javalin app = Javalin.create(cfg -> { routes.forEach(cfg::registerPlugin); cfg.http.port = 8080; cfg.bundledPlugins.enableRouteOverview("/routes"); cfg.bundledPlugins.enableCors(it -> it.addRule(it -> it.allowHost("* "))); }) .start(); ``` -------------------------------- ### Handling List Responses Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/quick-start.md Fetch a list of products using a GET request and process the response as a list of beans. ```java // Fetch list of products List products = client.request() .path("products") .GET() .list(Product.class) .execute(); System.out.println("Found " + products.size() + " products"); products.forEach(p -> System.out.println("- " + p.getName())); ``` -------------------------------- ### GET Request as JSON Bean Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Shows how to make a synchronous GET request and unmarshal the JSON response directly into a Java class (DTO). ```java HttpResponse customer = client.request() .path("customers").path(42) .GET() .as(CustomerDto.class); // just get the bean without HttpResponse CustomerDto customer = client.request() .path("customers").path(42) .GET() .bean(CustomerDto.class); ``` -------------------------------- ### BodyWriter Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/types.md Shows how to obtain and use a BodyWriter to serialize a User object to JSON bytes. ```java BodyWriter writer = bodyAdapter.beanWriter(User.class); byte[] json = writer.write(new User("John", "john@example.com")); ``` -------------------------------- ### RequestObserver Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/types.md Implement RequestObserver to log request details such as method, path, status code, and duration. ```java class TracingObserver implements RequestObserver { @Override public void observe(Event event) { long durationMs = (event.endTime() - event.startTime()) / 1_000_000; System.out.println(event.method() + " " + event.path() + " -> " + event.statusCode() + " (" + durationMs + "ms)"); } } HttpClient client = HttpClient.builder() .requestObserver(new TracingObserver()) .build(); ``` -------------------------------- ### GET Request with Matrix Parameters Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Applies matrix parameters to a path segment in a GET request. Multiple parameters can be added to the same or different path segments. ```java HttpResponse httpRes = client.request() .path("books") .matrixParam("author", "rob") .matrixParam("country", "nz") .path("foo") .matrixParam("extra", "banana") .GET() .asString(); ``` -------------------------------- ### Catching HttpException Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/errors.md Demonstrates how to catch HttpException and handle different HTTP status codes, such as 404 (Not Found), 401 (Authentication Failed), and 500 (Server Error), by inspecting the status code and response body. ```java try { User user = client.request() .path("users") .path(123) .GET() .bean(User.class) .execute(); } catch (HttpException e) { int status = e.statusCode(); if (status == 404) { System.out.println("User not found"); } else if (status == 401) { System.out.println("Authentication failed"); } else if (status == 500) { String error = e.bodyAsString(); System.out.println("Server error: " + error); } else { System.out.println("HTTP error: " + status); } } ``` -------------------------------- ### AuthInterceptor Implementation Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Example of implementing RequestIntercept for authentication, including token refresh logic. ```java class AuthInterceptor implements RequestIntercept { @Override public void intercept(HttpClientRequest request, InterceptChain chain) { request.header("Authorization", "Bearer " + getToken()); HttpResponse response = chain.proceed(request); if (response.statusCode() == 401) { // Token expired, refresh and retry request.header("Authorization", "Bearer " + refreshToken()); response = chain.proceed(request); } afterResponse(response, request); } } ``` -------------------------------- ### Implement Request Filter for Authentication Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/annotations.md Example of a request filter that checks for a valid Authorization header. ```java @Controller public class AuthController { @Filter void checkAuth(Context ctx) { String token = ctx.header("Authorization"); if (token == null || !validateToken(token)) { ctx.status(401); } } } ``` -------------------------------- ### GET Request as List of JSON Beans Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Illustrates performing a synchronous GET request to retrieve a collection of JSON objects, unmarshalled into a List of Java beans. Supports query parameters. ```java HttpResponse> customers = client.request() .path("customers") .queryParam("active", "true") .GET() .asList(CustomerDto.class); ``` -------------------------------- ### BodyString Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/additional-types.md Shows how to use the @BodyString annotation to receive raw string content in the request body. ```java @Controller public class RawController { @Post("/raw") String processRaw(@BodyString String rawContent) { return process(rawContent); } } ``` -------------------------------- ### Javalin Integration with Avaje HTTP Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/INDEX.md Shows the integration flow for Javalin using Avaje HTTP, starting from HttpClient.Builder and ending with registering plugins in Javalin. ```java HttpClient.Builder config // from avaje-http-api + generator ↓ AvajeJavalinPlugin (generated) ↓ Javalin.create(cfg -> plugins.forEach(cfg::registerPlugin)) ``` -------------------------------- ### OAuthTokenProvider Implementation Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md An example implementation of AuthTokenProvider using OAuth 2.0 client credentials. It obtains an access token and calculates its expiry, refreshing 60 seconds early. ```java class OAuthTokenProvider implements AuthTokenProvider { private String clientId = "..."; private String clientSecret = "..."; @Override public AuthToken obtainToken(HttpClientRequest request) { TokenResponse response = request .url("https://oauth.example.com/token") .header("Content-Type", "application/json") .body(Map.of( "client_id", clientId, "client_secret", clientSecret, "grant_type", "client_credentials" )) .POST() .bean(TokenResponse.class); Instant expiresAt = Instant.now() .plusSeconds(response.getExpiresIn()) .minusSeconds(60); // Refresh 60 seconds early return AuthToken.of(response.getAccessToken(), expiresAt); } } ``` -------------------------------- ### RequestListener Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/types.md Interface for observing request/response events. Implement this to track request lifecycle events like start, response, and errors. ```APIDOC ## RequestListener ### Description Interface for observing request/response events. Implement this to track request lifecycle events like start, response, and errors. ### Definition ```java public interface RequestListener { void onRequest(HttpClientRequest request); void onResponse(HttpResponse response, HttpClientRequest request); void onError(Throwable exception, HttpClientRequest request); } ``` ### Usage Added via `HttpClient.Builder.requestListener()` to track request lifecycle events. ```java class MetricsListener implements RequestListener { @Override public void onRequest(HttpClientRequest request) { // Track request start } @Override public void onResponse(HttpResponse response, HttpClientRequest request) { // Track response time, status codes } } HttpClient client = HttpClient.builder() .requestListener(new MetricsListener()) .build(); ``` **Location:** `http-client/src/main/java/io/avaje/http/client/RequestListener.java` ``` -------------------------------- ### PathTypeConversion Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/types.md Demonstrates how to use PathTypeConversion to convert a path parameter string to an integer. This is typically used within route handlers. ```java @Get("/{id}") void handleRequest(String id) { int intId = PathTypeConversion.asInt(id); } ``` -------------------------------- ### HttpClient Metrics and Request Execution Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/quick-start.md Demonstrates how to build an HttpClient, make multiple requests, gather performance metrics, and reset them. Useful for performance monitoring. ```java HttpClient client = HttpClient.builder() .baseUrl("http://api.example.com") .build(); // Make some requests for (int i = 0; i < 100; i++) { client.request() .path("products") .path(i) .GET() .asString() .execute(); } // Gather metrics HttpClient.Metrics metrics = client.metrics(); System.out.println("Total requests: " + metrics.totalCount()); System.out.println("Error responses: " + metrics.errorCount()); System.out.println("Total bytes: " + metrics.responseBytes()); System.out.println("Avg time: " + metrics.avgMicros() + " µs"); System.out.println("Max time: " + metrics.maxMicros() + " µs"); // Reset metrics client.metrics(true); ``` -------------------------------- ### Handle ValidationException Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/errors.md Provides an example of an exception handler for ValidationException. This handler formats validation errors into a map of field names to messages. ```java @Controller("/users") public class UserController { @Post @Valid void createUser(User user) { userService.save(user); } @ExceptionHandler(ValidationException.class) ErrorResponse handleValidation(ValidationException e) { Map errors = new HashMap<>(); for (ConstraintViolation violation : e.getViolations()) { String field = violation.getPropertyPath().toString(); String message = violation.getMessage(); errors.put(field, message); } return new ErrorResponse("Validation failed", errors); } } ``` -------------------------------- ### MediaType Usage in @Produces Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/types.md Example demonstrating the use of MediaType constants within an @Produces annotation for a GET endpoint. ```java @Produces(MediaType.APPLICATION_JSON) @Get("/{id}") User getUser(long id) { ... } ``` -------------------------------- ### Implement Custom Retry Logic Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Provides an example implementation of the RetryHandler interface for custom retry logic. Configure retry behavior for status exceptions and underlying client exceptions. ```java public final class ExampleRetry implements RetryHandler { private static final int MAX_RETRIES = 2; @Override public boolean isRetry(int retryCount, HttpResponse response) { final var code = response.statusCode(); if (retryCount >= MAX_RETRIES || code <= 400) { return false; } return true; } @Override public boolean isExceptionRetry(int retryCount, HttpException response) { //unwrap the exception final var cause = response.getCause(); if (retryCount >= MAX_RETRIES) { return false; } if (cause instanceof ConnectException) { return true; } return false; } } ``` -------------------------------- ### Handle HTTP Exception with Bean Deserialization Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Example of catching an `HttpException` and using `bean()` to deserialize a 400 Bad Request response into an `ErrorResponse` object. ```java @PostMapping("/register") void register(User user) { try { client.request() .path("users") .body(user) .POST() .asVoid() .execute(); } catch (HttpException e) { if (e.statusCode() == 400) { ErrorResponse error = e.bean(ErrorResponse.class); System.out.println("Validation errors: " + error.getErrors()); } } } ``` -------------------------------- ### Building Path with Multiple path() calls Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Demonstrates how multiple calls to `path()` can be chained to construct a URL path, appending segments with '/'. ```java HttpResponse res = client.request() .path("customers") .path("42") .path("contacts") .GET() .asString(); // is the same as ... HttpResponse res = client.request() .path("customers/42/contacts") .GET() .asString(); ``` -------------------------------- ### Usage of @Default for Query Parameters Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/annotations.md Demonstrates how to use the @Default annotation to set default values for 'limit' and 'offset' query parameters in a GET endpoint. If these parameters are not provided in the request, '10' and '0' will be used respectively. ```java @Get List search( @QueryParam String query, @QueryParam @Default("10") int limit, @QueryParam @Default("0") int offset ) { return productService.search(query, limit, offset); } ``` -------------------------------- ### Get Annotation Signature Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/annotations.md The @Get annotation marks a method to handle HTTP GET requests. It can specify a path suffix that appends to the @Controller path. ```java @Get("/{id}") Product getById(long id) { return productService.findById(id); } ``` ```java @Get List listAll() { return productService.findAll(); } ``` ```java @Get("/search") List search(String query) { return productService.search(query); } ``` -------------------------------- ### Client with Query Parameters Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/quick-start.md Make HTTP requests using the client, specifying query parameters individually or as a map. ```java List results = client.request() .path("search") .queryParam("q", "laptop") .queryParam("category", "computers") .queryParam("limit", 20) .queryParam("sort", "price") .GET() .list(Product.class) .execute(); ``` ```java Map params = new HashMap<>(); params.put("q", "laptop"); params.put("limit", 20); List results = client.request() .path("search") .queryParam(params) .GET() .list(Product.class) .execute(); ``` -------------------------------- ### @Get Annotation Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/annotations.md Marks a method to handle HTTP GET requests. It can specify a path suffix that appends to the @Controller path. ```APIDOC ## @Get ### Description Marks a method to handle HTTP GET requests. ### Parameters #### Path Parameters - **value** (String) - Optional - Path suffix for this route (appends to @Controller path). Defaults to "". ``` -------------------------------- ### Build HttpClient Instance Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Use the builder to configure and construct an HttpClient instance. Set the base URL, body adapter, and request timeout. ```java HttpClient client = HttpClient.builder() .baseUrl("http://localhost:8080") .bodyAdapter(new JacksonBodyAdapter()) .requestTimeout(Duration.ofSeconds(30)) .build(); ``` -------------------------------- ### Product Controller with Avaje HTTP Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/quick-start.md Create a REST controller using Avaje HTTP annotations to expose product-related endpoints. Includes exception handling for 'Not Found' scenarios. ```java package com.example.controller; import io.avaje.http.api.*; import com.example.service.ProductService; @Controller("/api/products") public class ProductController { private final ProductService productService; public ProductController(ProductService productService) { this.productService = productService; } @Get List getAll() { return productService.findAll(); } @Get("/{id}") Product getById(long id) { Product product = productService.findById(id); if (product == null) { throw new IllegalArgumentException("Product not found"); } return product; } @Post @Valid Product create(Product product) { return productService.save(product); } @Put("/{id}") @Valid Product update(long id, Product product) { return productService.update(id, product); } @Delete("/{id}") void delete(long id) { productService.delete(id); } @ExceptionHandler(IllegalArgumentException.class) @Produces("application/json") ErrorResponse handleNotFound(IllegalArgumentException e) { return new ErrorResponse("Not Found", e.getMessage()); } } public class ErrorResponse { public String error; public String message; public ErrorResponse(String error, String message) { this.error = error; this.message = message; } } ``` -------------------------------- ### GET Request with Query Parameters Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Adds query parameters to a GET request to filter or sort the results. The response is deserialized into a List of beans. ```java List beans = client.request() .path("products") .queryParam("sortBy", "name") .queryParam("maxCount", "100") .GET() .list(Product.class); ``` -------------------------------- ### Create HttpClient Instance Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Instantiate a HttpClient with a base URL, a JSON body adapter (e.g., JsonbBodyAdapter), and optionally a logger. This client can then be used to make HTTP requests. ```java HttpClient client = HttpClient.builder() .baseUrl(baseUrl) .bodyAdapter(new JsonbBodyAdapter()) //.bodyAdapter(new JacksonBodyAdapter(new ObjectMapper())) //.bodyAdapter(new GsonBodyAdapter(new Gson())) .build(); HttpResponse hres = client.request() .path("hello") .GET() .asString(); ``` -------------------------------- ### Build Configured HttpClient Instance Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Finalizes the configuration and returns a ready-to-use HttpClient instance. This method should be called after all desired configurations have been applied. ```java HttpClient build() ``` -------------------------------- ### Java @Form Annotation Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/annotations.md An example showing a LoginForm bean used with the @Form annotation to bind form parameters for a login endpoint. ```java public class LoginForm { public String email; public String password; @Header public String remember; } ``` ```java @Post("/login") void login(@Form LoginForm form) { authenticate(form.email, form.password); } ``` -------------------------------- ### Helidon SE Server Runtime Configuration Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/configuration.md Set up and launch a Helidon SE server with Avaje HTTP routes. Define routing features and specify the server port. ```java List routes = ...; // Retrieved from DI container final var builder = HttpRouting.builder(); routes.forEach(builder::addFeature); WebServer.builder() .addRouting(builder) .port(8080) .build() .start(); ``` -------------------------------- ### Java @FormParam Annotation Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/annotations.md Example of using @FormParam to map bean properties 'searchTerm' and 'maxResults' to form parameters 'search-term' and 'max-results' respectively. ```java public class SearchForm { @FormParam("search-term") public String searchTerm; @FormParam("max-results") public int maxResults; } ``` -------------------------------- ### Dependency Injection with Avaje HTTP Clients Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/INDEX.md Explains how to use Avaje HTTP clients with dependency injection. It shows the pattern of defining an interface annotated with @Client and using HttpApiProvider to generate an injectable bean. ```java @Client interface (annotated with @Client) ↓ HttpClient.create(Class clientInterface) ↓ Generated implementation (via HttpApiProvider) ↓ Ready to use as injected bean ``` -------------------------------- ### Access and Display HttpClient Metrics Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/types.md Demonstrates how to obtain HttpClient metrics and display them. It also shows how to reset these metrics by passing 'true' to the metrics method. ```java HttpClient client = HttpClient.builder() .baseUrl("http://api.example.com") .build(); // ... make requests ... HttpClient.Metrics metrics = client.metrics(); System.out.println("Total requests: " + metrics.totalCount()); System.out.println("Error responses: " + metrics.errorCount()); System.out.println("Avg response time: " + metrics.avgMicros() + "µs"); System.out.println("Total data received: " + metrics.responseBytes() + " bytes"); // Reset metrics client.metrics(true); ``` -------------------------------- ### Use Generated Client Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/quick-start.md Build an HttpClient, create an instance of the API client using httpClient.create(), and then use it like a normal Java interface. ```java // Build HTTP client HttpClient httpClient = HttpClient.builder() .baseUrl("http://localhost:8080") .bodyAdapter(new JacksonBodyAdapter()) .build(); // Create API client (implementation is auto-generated) ProductApi api = httpClient.create(ProductApi.class); // Use like normal Java interface List products = api.getAll(); Product p = api.getById(1); Product created = api.create(new Product("Keyboard", 75.00)); api.delete(1); ``` -------------------------------- ### Get Widget by ID Source: https://github.com/avaje/avaje-http/blob/master/README.md Retrieves a specific widget using its unique identifier. ```APIDOC ## GET /widgets/:id ### Description Retrieves a specific widget by its ID. ### Method GET ### Endpoint /widgets/:id ### Parameters #### Path Parameters - **id** (int) - Required - The unique identifier of the widget. ### Response #### Success Response (200) - **Widget** (Widget) - The requested widget object. #### Response Example ```json { "id": 1, "name": "Example Widget" } ``` ``` -------------------------------- ### Basic Avaje HTTP Client Telemetry Configuration Source: https://github.com/avaje/avaje-http/blob/master/http-client-otel/README.md Configure AvajeHttpClientTelemetry with OpenTelemetry, capturing specific headers, and build the HTTP client. ```java import io.avaje.http.client.HttpClient; import io.avaje.http.client.otel.AvajeHttpClientTelemetry; var client = AvajeHttpClientTelemetry.builder(openTelemetry) .useLabelAsUrlTemplate(true) .capturedRequestHeaders(List.of("x-request-id")) .capturedResponseHeaders(List.of("x-request-id")) .build() .configure( HttpClient.builder() .baseUrl("https://api.example.com")) .build(); ``` -------------------------------- ### HttpClient.builder() Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Returns a builder to configure and construct an HttpClient instance. ```APIDOC ## HttpClient.builder() ### Description Returns a builder to configure and construct an HttpClient instance. ### Method ```java static Builder builder() ``` ### Returns `HttpClient.Builder` — fluent builder for configuration ### Usage ```java HttpClient client = HttpClient.builder() .baseUrl("http://localhost:8080") .bodyAdapter(new JacksonBodyAdapter()) .requestTimeout(Duration.ofSeconds(30)) .build(); ``` ``` -------------------------------- ### HttpClient.Builder Configuration Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Configure various aspects of the HttpClient, such as base URL, timeouts, and interceptors. ```APIDOC ## HttpClient.Builder Fluent builder for configuring HttpClient instances. ### Configuration Methods #### baseUrl(String baseUrl) Sets the base URL for all requests. ```java Builder baseUrl(String baseUrl) ``` **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | baseUrl | String | Base URL (e.g., "http://api.example.com") | **Returns:** `Builder` — this builder instance #### bodyAdapter(BodyAdapter adapter) Sets the adapter for JSON serialization/deserialization. ```java Builder bodyAdapter(BodyAdapter adapter) ``` **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | adapter | BodyAdapter | Jackson, Gson, or custom adapter | **Returns:** `Builder` — this builder instance #### requestTimeout(Duration requestTimeout) Sets the default request timeout. ```java Builder requestTimeout(Duration requestTimeout) ``` **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | requestTimeout | Duration | Timeout duration | **Returns:** `Builder` — this builder instance #### retryHandler(RetryHandler retryHandler) Sets a handler to retry failed requests. ```java Builder retryHandler(RetryHandler retryHandler) ``` **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | retryHandler | RetryHandler | Custom retry logic | **Returns:** `Builder` — this builder instance #### requestIntercept(RequestIntercept... requestIntercept) Adds request/response interceptors. ```java Builder requestIntercept(RequestIntercept... requestIntercept) ``` **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | requestIntercept | RequestIntercept[] | Interceptor(s) to add | **Returns:** `Builder` — this builder instance #### authTokenProvider(AuthTokenProvider authTokenProvider) Sets a provider for Bearer token authorization. ```java Builder authTokenProvider(AuthTokenProvider authTokenProvider) ``` **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | authTokenProvider | AuthTokenProvider | Token provider implementation | **Returns:** `Builder` — this builder instance #### build() Builds and returns the configured HttpClient. ```java HttpClient build() ``` **Returns:** `HttpClient` — configured client instance **Usage:** ```java HttpClient client = HttpClient.builder() .baseUrl("http://api.example.com") .bodyAdapter(new JacksonBodyAdapter()) .requestTimeout(Duration.ofSeconds(30)) .retryHandler(new MyRetryHandler()) .build(); ``` **Location:** `http-client/src/main/java/io/avaje/http/client/HttpClient.java` ``` -------------------------------- ### Handle Generic Exception with JSON Response Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/annotations.md Example of handling IllegalArgumentException and producing a JSON response. ```java @ExceptionHandler(IllegalArgumentException.class) @Produces("application/json") ErrorResponse handleValidation(IllegalArgumentException e) { return new ErrorResponse("Invalid argument", e.getMessage()); } ``` -------------------------------- ### Custom RetryHandler Implementation Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Example of implementing RetryHandler to retry on specific status codes up to a maximum count. ```java class MyRetryHandler implements RetryHandler { @Override public boolean isRetry(int retryCount, HttpResponse response) { int status = response.statusCode(); // Retry on 429 (rate limit) or 5XX errors, but max 3 times if (retryCount >= 3) return false; return status == 429 || status >= 500; } } HttpClient client = HttpClient.builder() .retryHandler(new MyRetryHandler()) .build(); ``` -------------------------------- ### POST Request with Request Body Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/quick-start.md Send a POST request with a Java bean as the request body to create a new product. The response is expected to be a Product bean. ```java Product newProduct = new Product(); newProduct.setName("Monitor"); newProduct.setPrice(350.00); Product created = client.request() .path("products") .body(newProduct) .POST() .bean(Product.class) .execute(); System.out.println("Created product with ID: " + created.getId()); ``` -------------------------------- ### Generated Annotation Usage Example Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/additional-types.md Illustrates the @Generated annotation applied to a generated route handler class. ```java @Generated("avaje-javalin-generator") @Singleton public final class ProductController$Route extends AvajeJavalinPlugin { // ... } ``` -------------------------------- ### Register Avaje HTTP Plugins with Javalin Source: https://github.com/avaje/avaje-http/blob/master/README.md Retrieve generated `AvajeJavalinPlugin` routes using a DI framework and register them with Javalin. ```java List routes = ...; //retrieve using a DI framework Javalin.create(cfg -> routes.forEach(cfg::registerPlugin)).start(); ``` -------------------------------- ### Handle DefaultException Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/errors.md Example of an @ExceptionHandler that catches DefaultException. This is used to handle any exception not matched by more specific types. ```java @ExceptionHandler(DefaultException.class) ErrorResponse handleDefault(Exception e) { // Catches all unhandled exceptions return new ErrorResponse("Internal error", e.getMessage()); } ``` -------------------------------- ### Catch RequiredArgumentException in Controller Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/errors.md Example of catching RequiredArgumentException in a controller to handle cases where required parameters are missing. ```java @Controller("/items") public class ItemController { @Get("/{id}") Item getById(long id) { return itemService.findById(id); } @Get("/search") List search(@QueryParam String query) { return itemService.search(query); } @ExceptionHandler(RequiredArgumentException.class) ErrorResponse handleMissingRequired(RequiredArgumentException e) { return new ErrorResponse( "Missing required parameter", "The required parameter was not provided" ); } } // GET /items/search // Throws: RequiredArgumentException("query", "String") ``` -------------------------------- ### Get Bean Reader Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Obtain a reader to deserialize response content into a bean. Specify the target bean class. ```java BodyReader beanReader(Class type) ``` -------------------------------- ### HttpClient Builder Configuration Methods Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Defines the fluent interface for configuring HttpClient instances. Use these methods to set base URL, timeouts, body adapters, retry handlers, and other client-specific settings. ```java public interface HttpClient.Builder { Builder baseUrl(String baseUrl); Builder globalErrorMapper(Function errorMapper); Builder connectionTimeout(Duration connectionTimeout); Builder requestTimeout(Duration requestTimeout); Builder bodyAdapter(BodyAdapter adapter); Builder retryHandler(RetryHandler retryHandler); Builder requestLogging(boolean requestLogging); Builder requestListener(RequestListener... requestListener); Builder requestIntercept(RequestIntercept... requestIntercept); Builder requestObserver(RequestObserver... requestObserver); Builder authTokenProvider(AuthTokenProvider authTokenProvider); Builder backgroundTokenRefresh(Duration backgroundTokenRefresh); Builder client(java.net.http.HttpClient client); Builder cookieHandler(CookieHandler cookieHandler); Builder redirect(java.net.http.HttpClient.Redirect redirect); Builder version(java.net.http.HttpClient.Version version); Builder executor(Executor executor); Builder proxy(ProxySelector proxySelector); Builder sslContext(SSLContext sslContext); Builder sslParameters(SSLParameters sslParameters); Builder authenticator(Authenticator authenticator); Builder priority(int priority); Builder configureWith(BeanScope beanScope); Builder suppressHeader(String header); Builder.State state(); HttpClient build(); } ``` -------------------------------- ### Get HTTP Status Code from HttpException Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Use `statusCode()` to retrieve the HTTP status code associated with an `HttpException`. ```java int statusCode() ``` -------------------------------- ### HttpClient.create(Class clientInterface) Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Creates a dynamic implementation of a `@Client` annotated interface using the default ClassLoader. ```APIDOC ## HttpClient.create(Class clientInterface) ### Description Creates a dynamic implementation of a `@Client` annotated interface using the default ClassLoader. ### Method ```java T create(Class clientInterface) ``` ### Parameters #### Path Parameters - **clientInterface** (Class) - Required - Interface marked with `@Client` annotation ### Returns `T` — dynamic proxy implementation of the client interface ### Usage ```java @Client interface TodoApi { @Get("/{id}") Todo getTodo(long id); @Post Todo createTodo(Todo todo); } TodoApi api = client.create(TodoApi.class); Todo todo = api.getTodo(1); ``` ``` -------------------------------- ### BasicAuthIntercept Usage Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/additional-types.md Demonstrates how to use BasicAuthIntercept to automatically include Authorization: Basic header in HTTP requests. ```java HttpClient client = HttpClient.builder() .baseUrl("http://api.example.com") .requestIntercept(new BasicAuthIntercept("user", "password")) .build(); // All requests will include Authorization: Basic base64(user:password) client.request() .path("protected-resource") .GET() .bean(Resource.class) .execute(); ``` -------------------------------- ### Consumes Annotation Usage Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/additional-types.md Example of using the Consumes annotation to specify accepted media types for controller methods. ```java @Controller("/api/data") @Consumes("application/json") public class DataController { @Post void acceptJson(Data data) { // Only accepts application/json } @Post("/xml") @Consumes("application/xml") void acceptXml(String xmlData) { // Only accepts application/xml } } ``` -------------------------------- ### Configure Maven Compiler Plugin for Javax Source: https://github.com/avaje/avaje-http/blob/master/README.md Use this compiler argument to force the annotation processor to generate with `@javax.inject.Singleton` when both jakarta and javax are on the classpath. ```xml org.apache.maven.plugins maven-compiler-plugin -AuseJavax=true ``` -------------------------------- ### Get Bean Writer Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Obtain a writer to serialize beans into request body content. Specify the class of the bean to be serialized. ```java BodyWriter beanWriter(Class type) ``` -------------------------------- ### Controller with Query Parameters Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/quick-start.md Define a controller endpoint that accepts query parameters with default values. ```java import io.avaje.http.Controller; import io.avaje.http.Get; import io.avaje.http.QueryParam; import io.avaje.http.Default; import java.util.List; @Controller("/search") public class SearchController { @Get List search( @QueryParam String q, @QueryParam(value = "category") @Default("electronics") String category, @QueryParam(value = "sort") @Default("name") String sortBy, @QueryParam(value = "limit") @Default("10") int limit ) { // Perform search with parameters return productService.search(q, category, sortBy, limit); } } // Called with: GET /search?q=laptop&category=computers&limit=20 ``` -------------------------------- ### Async HTTP Request Execution Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/quick-start.md Perform an HTTP GET request asynchronously and handle the response or errors using CompletableFuture. ```java client.request() .path("products") .GET() .list(Product.class) .async() .thenAccept(products -> { System.out.println("Got " + products.size() + " products"); }) .exceptionally(e -> { System.err.println("Error: " + e.getMessage()); return null; }); // Continue with other work... ``` -------------------------------- ### Implement AuthTokenProvider for Bearer Tokens Source: https://github.com/avaje/avaje-http/blob/master/http-client/README.md Implement the `AuthTokenProvider` interface to obtain and manage Bearer tokens. The `obtainToken` method should fetch the token, calculate its validity, and return an `AuthToken` object. ```java class MyAuthTokenProvider implements AuthTokenProvider { @Override public AuthToken obtainToken(HttpClientRequest tokenRequest) { AuthTokenResponse res = tokenRequest .url("https://foo/v2/token") .header("content-type", "application/json") .body(authRequestAsJson()) .POST() .bean(AuthTokenResponse.class); Instant validUntil = Instant.now().plusSeconds(res.expires_in).minusSeconds(60); return AuthToken.of(res.access_token, validUntil); } } ``` -------------------------------- ### Configure HttpClient with Dependency Injection Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/configuration.md Integrate HttpClient with a dependency injection container (e.g., avaje-inject) using configureWith(). This allows DI to manage and provide dependencies like BodyAdapter and RetryHandler. ```java BeanScope scope = ...; // From avaje-inject HttpClient client = HttpClient.builder() .baseUrl("http://api.example.com") .configureWith(scope) .build(); ``` -------------------------------- ### Catch InvalidTypeArgumentException in Controller Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/errors.md Example of catching InvalidTypeArgumentException in a controller to handle cases where query parameters are not convertible to the expected type. ```java @Controller("/search") public class SearchController { @Get List search( @QueryParam String q, @QueryParam(value = "limit") int limit ) { return searchService.search(q, limit); } @ExceptionHandler(InvalidTypeArgumentException.class) ErrorResponse handleInvalidType(InvalidTypeArgumentException e) { return new ErrorResponse( "Invalid query parameter", "Query parameter could not be converted to expected type" ); } } // GET /search?q=java&limit=abc // Throws: InvalidTypeArgumentException("limit", "abc", "int") ``` -------------------------------- ### HTTP Server Classes Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/SUMMARY.txt Core classes for building HTTP servers and handling specific server-side functionalities. ```APIDOC ## HTTP Server Classes ### Description Core classes and utilities for building HTTP servers and managing server-side operations. ### Classes - `AvajeJavalinPlugin`: Integration plugin for Javalin. - `StreamingOutput`: Represents data that can be streamed in responses. - `ValidationException`: Exception thrown for validation failures. - `Validator`: Interface for performing custom validation. ``` -------------------------------- ### Get List Reader Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Obtain a reader to deserialize response content into a list of beans. Specify the element bean class for the list. ```java BodyReader> listReader(Class type) ``` -------------------------------- ### Build URL Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Use the UrlBuilder to construct URLs relative to the base URL. This is helpful for creating complex or dynamic URLs. ```java String url = client.url() .path("api") .path("users") .path("123") .build(); ``` -------------------------------- ### Get Error Response Body as String Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Use `bodyAsString()` to retrieve the error response body as a UTF-8 encoded string from an `HttpException`. ```java String bodyAsString() ``` -------------------------------- ### Create Dynamic Client Interface Implementation Source: https://github.com/avaje/avaje-http/blob/master/_autodocs/api-reference/http-client.md Create a dynamic proxy implementation of a `@Client` annotated interface using the default ClassLoader. This is useful for defining API endpoints as interfaces. ```java @Client interface TodoApi { @Get("/{id}") Todo getTodo(long id); @Post Todo createTodo(Todo todo); } TodoApi api = client.create(TodoApi.class); Todo todo = api.getTodo(1); ```