CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework--spring-web

Spring Web module providing web application infrastructure including HTTP integration, servlet filters, Spring web MVC framework, and reactive web stack support

Overview
Eval results
Files

http-clients.mddocs/

HTTP Clients

Comprehensive HTTP client support for consuming REST APIs and web services. Spring Web provides both traditional template-based clients (RestTemplate) and modern fluent clients (RestClient), along with configurable client infrastructure.

Capabilities

RestClient - Modern Fluent API

Modern synchronous HTTP client with a fluent API design for type-safe and readable HTTP operations.

/**
 * Fluent synchronous HTTP client interface
 */
interface RestClient {
    // HTTP method specifications
    RequestHeadersUriSpec<?> get();
    RequestBodyUriSpec post();
    RequestBodyUriSpec put();
    RequestBodyUriSpec patch();
    RequestHeadersUriSpec<?> delete();
    RequestHeadersUriSpec<?> head();
    RequestHeadersUriSpec<?> options();
    RequestBodyUriSpec method(HttpMethod method);
    
    // Factory methods
    static RestClient create();
    static RestClient create(String baseUrl);
    static RestClient create(RestTemplate restTemplate);
    static RestClient.Builder builder();
    static RestClient.Builder builder(RestTemplate restTemplate);
}

/**
 * RestClient builder for configuration
 */
interface RestClient.Builder {
    RestClient.Builder baseUrl(String baseUrl);
    RestClient.Builder defaultUriVariables(Map<String, ?> defaultUriVariables);
    RestClient.Builder defaultHeader(String header, String... values);
    RestClient.Builder defaultHeaders(Consumer<HttpHeaders> headersConsumer);
    RestClient.Builder defaultRequest(Consumer<RequestHeadersSpec<?>> defaultRequest);
    RestClient.Builder requestFactory(ClientHttpRequestFactory requestFactory);
    RestClient.Builder messageConverters(Consumer<List<HttpMessageConverter<?>>> configurer);
    RestClient.Builder requestInterceptor(ClientHttpRequestInterceptor interceptor);
    RestClient.Builder requestInterceptors(Consumer<List<ClientHttpRequestInterceptor>> interceptorsConsumer);
    RestClient.Builder requestInitializer(ClientHttpRequestInitializer initializer);
    RestClient.Builder requestInitializers(Consumer<List<ClientHttpRequestInitializer>> initializersConsumer);
    RestClient.Builder statusHandler(Predicate<HttpStatusCode> statusPredicate, ResponseErrorHandler errorHandler);
    RestClient.Builder defaultStatusHandler(ResponseErrorHandler errorHandler);
    RestClient.Builder observationRegistry(ObservationRegistry observationRegistry);
    RestClient.Builder observationConvention(ClientRequestObservationConvention observationConvention);
    RestClient build();
}

/**
 * URI specification for requests without body
 */
interface RequestHeadersUriSpec<S extends RequestHeadersSpec<S>> extends UriSpec<S> {
    // Inherited from UriSpec: uri methods
}

/**
 * URI specification for requests with body
 */
interface RequestBodyUriSpec extends RequestBodySpec, RequestHeadersUriSpec<RequestBodySpec> {
    // Combines URI and body specification
}

/**
 * Headers specification for all request types
 */
interface RequestHeadersSpec<S extends RequestHeadersSpec<S>> {
    S header(String headerName, String... headerValues);
    S headers(Consumer<HttpHeaders> headersConsumer);
    S accept(MediaType... acceptableMediaTypes);
    S acceptCharset(Charset... acceptableCharsets);
    S ifModifiedSince(ZonedDateTime ifModifiedSince);
    S ifNoneMatch(String... ifNoneMatches);
    
    // Execute and retrieve response
    ResponseEntity<Void> retrieve();
    <T> ResponseEntity<T> retrieve(Class<T> bodyType);
    <T> ResponseEntity<T> retrieve(ParameterizedTypeReference<T> bodyType);
    
    // Exchange for full control
    <T> T exchange(ExchangeFunction<T> exchangeFunction);
}

/**
 * Body specification for requests with content
 */
interface RequestBodySpec extends RequestHeadersSpec<RequestBodySpec> {
    RequestBodySpec contentType(MediaType contentType);
    RequestBodySpec contentLength(long contentLength);
    RequestBodySpec body(Object body);
    <T> RequestBodySpec body(T body, Class<T> bodyType);
    <T> RequestBodySpec body(T body, ParameterizedTypeReference<T> bodyType);
}

/**
 * URI specification methods
 */
interface UriSpec<S extends RequestHeadersSpec<S>> {
    S uri(String uri, Object... uriVariables);
    S uri(String uri, Map<String, ?> uriVariables);
    S uri(URI uri);
    S uri(Function<UriBuilder, URI> uriFunction);
}

Usage Examples:

// Create RestClient
RestClient restClient = RestClient.create("https://api.example.com");

// Simple GET request
String response = restClient.get()
    .uri("/users/{id}", 123)
    .retrieve()
    .body(String.class);

// POST request with JSON body
User user = new User("John", "john@example.com");
User createdUser = restClient.post()
    .uri("/users")
    .contentType(MediaType.APPLICATION_JSON)
    .body(user)
    .retrieve()
    .body(User.class);

// GET with custom headers
List<User> users = restClient.get()
    .uri("/users")
    .header("Authorization", "Bearer token")
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .body(new ParameterizedTypeReference<List<User>>() {});

// Error handling with exchange
String result = restClient.get()
    .uri("/users/{id}", 404)
    .exchange((request, response) -> {
        if (response.getStatusCode().is4xxClientError()) {
            return "User not found";
        }
        return response.bodyTo(String.class);
    });

// Builder configuration
RestClient configuredClient = RestClient.builder()
    .baseUrl("https://api.example.com")
    .defaultHeader("Authorization", "Bearer token")
    .defaultHeader("User-Agent", "MyApp/1.0")
    .statusHandler(HttpStatus::is4xxClientError, (request, response) -> {
        throw new ClientErrorException(response.getStatusCode());
    })
    .build();

RestTemplate - Traditional Template API

Traditional synchronous HTTP client providing template method patterns for HTTP operations.

/**
 * Traditional synchronous client to perform HTTP requests
 */
class RestTemplate extends InterceptingHttpAccessor implements RestOperations {
    RestTemplate();
    RestTemplate(ClientHttpRequestFactory requestFactory);
    RestTemplate(List<HttpMessageConverter<?>> messageConverters);
    
    // GET operations
    <T> T getForObject(String url, Class<T> responseType, Object... uriVariables);
    <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables);
    <T> T getForObject(URI url, Class<T> responseType);
    
    <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables);
    <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables);
    <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType);
    
    // HEAD operations
    HttpHeaders headForHeaders(String url, Object... uriVariables);
    HttpHeaders headForHeaders(String url, Map<String, ?> uriVariables);
    HttpHeaders headForHeaders(URI url);
    
    // POST operations
    <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables);
    <T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables);
    <T> T postForObject(URI url, Object request, Class<T> responseType);
    
    <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables);
    <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables);
    <T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType);
    
    URI postForLocation(String url, Object request, Object... uriVariables);
    URI postForLocation(String url, Object request, Map<String, ?> uriVariables);
    URI postForLocation(URI url, Object request);
    
    // PUT operations
    void put(String url, Object request, Object... uriVariables);
    void put(String url, Object request, Map<String, ?> uriVariables);
    void put(URI url, Object request);
    
    // PATCH operations
    <T> T patchForObject(String url, Object request, Class<T> responseType, Object... uriVariables);
    <T> T patchForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables);
    <T> T patchForObject(URI url, Object request, Class<T> responseType);
    
    // DELETE operations
    void delete(String url, Object... uriVariables);
    void delete(String url, Map<String, ?> uriVariables);
    void delete(URI url);
    
    // OPTIONS operations
    Set<HttpMethod> optionsForAllow(String url, Object... uriVariables);
    Set<HttpMethod> optionsForAllow(String url, Map<String, ?> uriVariables);
    Set<HttpMethod> optionsForAllow(URI url);
    
    // Generic exchange operations
    <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, 
                                 Class<T> responseType, Object... uriVariables);
    <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, 
                                 Class<T> responseType, Map<String, ?> uriVariables);
    <T> ResponseEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?> requestEntity, 
                                 Class<T> responseType);
    <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, Class<T> responseType);
    <T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, ParameterizedTypeReference<T> responseType);
    
    // Async execute methods  
    <T> ListenableFuture<ResponseEntity<T>> execute(String url, HttpMethod method, 
                                                   RequestCallback requestCallback, 
                                                   ResponseExtractor<ResponseEntity<T>> responseExtractor, 
                                                   Object... uriVariables);
}

/**
 * RestOperations interface defining the template contract
 */
interface RestOperations {
    // All the same methods as RestTemplate class
    // This interface is implemented by RestTemplate
}

Usage Examples:

RestTemplate restTemplate = new RestTemplate();

// Simple GET operations
String result = restTemplate.getForObject("https://api.example.com/users/{id}", String.class, 123);
ResponseEntity<User> userResponse = restTemplate.getForEntity("https://api.example.com/users/{id}", User.class, 123);

// POST operations
User newUser = new User("John", "john@example.com");
User createdUser = restTemplate.postForObject("https://api.example.com/users", newUser, User.class);
URI location = restTemplate.postForLocation("https://api.example.com/users", newUser);

// Exchange for full control
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth("token");
HttpEntity<User> requestEntity = new HttpEntity<>(newUser, headers);

ResponseEntity<User> response = restTemplate.exchange(
    "https://api.example.com/users",
    HttpMethod.POST,
    requestEntity,
    User.class
);

// Using RequestEntity
RequestEntity<User> request = RequestEntity.post("https://api.example.com/users")
    .contentType(MediaType.APPLICATION_JSON)
    .body(newUser);
    
ResponseEntity<User> response = restTemplate.exchange(request, User.class);

HTTP Client Infrastructure

Low-level HTTP client infrastructure for creating and configuring HTTP requests and responses.

/**
 * Factory for creating ClientHttpRequest objects
 */
interface ClientHttpRequestFactory {
    /** Create a new request for the given URI and HTTP method */
    ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException;
}

/**
 * Client-side HTTP request
 */
interface ClientHttpRequest extends HttpRequest, HttpOutputMessage {
    /** Execute this request and return the response */
    ClientHttpResponse execute() throws IOException;
}

/**
 * Client-side HTTP response
 */
interface ClientHttpResponse extends HttpInputMessage, Closeable {
    /** Get the HTTP status code */
    HttpStatusCode getStatusCode() throws IOException;
    /** Get the status text */
    String getStatusText() throws IOException;
    /** Close this response */
    void close();
}

/**
 * Execution context for client HTTP requests
 */
interface ClientHttpRequestExecution {
    /** Execute the request with the given body */
    ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException;
}

/**
 * Interceptor for client-side HTTP requests
 */
interface ClientHttpRequestInterceptor {
    /** Intercept the request before execution */
    ClientHttpResponse intercept(HttpRequest request, byte[] body, 
                               ClientHttpRequestExecution execution) throws IOException;
}

/**
 * Initializer for client HTTP requests
 */
interface ClientHttpRequestInitializer {
    /** Initialize the request before execution */
    void initialize(ClientHttpRequest request);
}

HTTP Client Factory Implementations

Concrete implementations of ClientHttpRequestFactory for different HTTP client libraries.

/**
 * Simple factory based on standard JDK HTTP facilities
 */
class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory {
    SimpleClientHttpRequestFactory();
    
    /** Set the proxy to use for connections */
    void setProxy(Proxy proxy);
    /** Set whether to buffer request body in memory */
    void setBufferRequestBody(boolean bufferRequestBody);
    /** Set the chunk size for streaming */
    void setChunkSize(int chunkSize);
    /** Set the connection timeout */
    void setConnectTimeout(int connectTimeout);
    /** Set the read timeout */
    void setReadTimeout(int readTimeout);
    
    ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException;
}

/**
 * Factory based on Apache HttpComponents HttpClient
 */
class HttpComponentsClientHttpRequestFactory implements ClientHttpRequestFactory, DisposableBean {
    HttpComponentsClientHttpRequestFactory();
    HttpComponentsClientHttpRequestFactory(HttpClient httpClient);
    
    /** Set the HttpClient instance to use */
    void setHttpClient(HttpClient httpClient);
    /** Set connection timeout */
    void setConnectTimeout(int connectTimeout);
    /** Set connection request timeout */
    void setConnectionRequestTimeout(int connectionRequestTimeout);
    /** Set socket read timeout */
    void setReadTimeout(int readTimeout);
    /** Set buffer request body */
    void setBufferRequestBody(boolean bufferRequestBody);
    
    ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException;
    void destroy() throws Exception;
}

/**
 * Factory based on OkHttp 3.x
 */
class OkHttp3ClientHttpRequestFactory implements ClientHttpRequestFactory, DisposableBean {
    OkHttp3ClientHttpRequestFactory();
    OkHttp3ClientHttpRequestFactory(OkHttpClient client);
    
    /** Set the OkHttpClient instance to use */
    void setClient(OkHttpClient client);
    /** Set connection timeout */
    void setConnectTimeout(int connectTimeout);
    /** Set read timeout */
    void setReadTimeout(int readTimeout);
    /** Set write timeout */
    void setWriteTimeout(int writeTimeout);
    
    ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException;
    void destroy() throws Exception;
}

/**
 * Factory based on JDK 11+ HTTP Client
 */
class JdkClientHttpRequestFactory implements ClientHttpRequestFactory {
    JdkClientHttpRequestFactory();
    JdkClientHttpRequestFactory(HttpClient httpClient);
    JdkClientHttpRequestFactory(HttpClient httpClient, Executor executor);
    
    /** Set the HttpClient instance to use */
    void setHttpClient(HttpClient httpClient);
    /** Set executor for async operations */
    void setExecutor(Executor executor);
    /** Set read timeout */
    void setReadTimeout(Duration readTimeout);
    
    ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException;
}

/**
 * Factory wrapper that buffers all outgoing and incoming streams
 */
class BufferingClientHttpRequestFactory extends AbstractClientHttpRequestFactoryWrapper {
    BufferingClientHttpRequestFactory(ClientHttpRequestFactory requestFactory);
    
    ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) throws IOException;
}

/**
 * Factory wrapper with support for request interceptors
 */
class InterceptingClientHttpRequestFactory extends AbstractClientHttpRequestFactoryWrapper {
    InterceptingClientHttpRequestFactory(ClientHttpRequestFactory requestFactory, 
                                       List<ClientHttpRequestInterceptor> interceptors);
    
    ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) throws IOException;
}

Usage Examples:

// Configure different HTTP client factories
SimpleClientHttpRequestFactory simpleFactory = new SimpleClientHttpRequestFactory();
simpleFactory.setConnectTimeout(5000);
simpleFactory.setReadTimeout(10000);

HttpComponentsClientHttpRequestFactory httpComponentsFactory = new HttpComponentsClientHttpRequestFactory();
httpComponentsFactory.setConnectTimeout(5000);
httpComponentsFactory.setReadTimeout(10000);

// Use with RestTemplate
RestTemplate restTemplate = new RestTemplate(simpleFactory);

// Configure with interceptors
List<ClientHttpRequestInterceptor> interceptors = Arrays.asList(
    new BasicAuthenticationInterceptor("username", "password"),
    new LoggingClientHttpRequestInterceptor()
);

restTemplate.setInterceptors(interceptors);

Request Interceptors and Authentication

Built-in interceptors for common cross-cutting concerns like authentication and logging.

/**
 * Interceptor to apply Basic Authentication headers
 */
class BasicAuthenticationInterceptor implements ClientHttpRequestInterceptor {
    BasicAuthenticationInterceptor(String username, String password);
    BasicAuthenticationInterceptor(String username, String password, Charset charset);
    
    ClientHttpResponse intercept(HttpRequest request, byte[] body, 
                               ClientHttpRequestExecution execution) throws IOException;
}

/**
 * Interceptor to apply Bearer token authentication
 */
class BearerTokenAuthenticationInterceptor implements ClientHttpRequestInterceptor {
    BearerTokenAuthenticationInterceptor(String token);
    
    ClientHttpResponse intercept(HttpRequest request, byte[] body, 
                               ClientHttpRequestExecution execution) throws IOException;
}

Usage Examples:

// Basic authentication interceptor
BasicAuthenticationInterceptor basicAuth = new BasicAuthenticationInterceptor("user", "pass");

// Bearer token interceptor  
BearerTokenAuthenticationInterceptor bearerAuth = new BearerTokenAuthenticationInterceptor("jwt-token");

// Custom interceptor
ClientHttpRequestInterceptor customInterceptor = (request, body, execution) -> {
    request.getHeaders().add("X-Custom-Header", "custom-value");
    ClientHttpResponse response = execution.execute(request, body);
    // Log response or modify headers
    return response;
};

// Apply interceptors to RestTemplate
RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(Arrays.asList(basicAuth, customInterceptor));

// Apply interceptors to RestClient
RestClient restClient = RestClient.builder()
    .requestInterceptor(bearerAuth)
    .requestInterceptor(customInterceptor)
    .build();

Error Handling

Configure custom error handling for HTTP client responses.

/**
 * Strategy interface used by RestTemplate to determine whether a response has an error
 */
interface ResponseErrorHandler {
    /** Determine if the given response has an error */
    boolean hasError(ClientHttpResponse response) throws IOException;
    /** Handle the error in the given response */
    void handleError(ClientHttpResponse response) throws IOException;
    /** Handle the error for the given request and response */
    default void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
        handleError(response);
    }
}

/**
 * Default implementation of ResponseErrorHandler
 */
class DefaultResponseErrorHandler implements ResponseErrorHandler {
    DefaultResponseErrorHandler();
    
    /** Check if response has client (4xx) or server (5xx) error */
    boolean hasError(ClientHttpResponse response) throws IOException;
    /** Throw appropriate exception based on status code */
    void handleError(ClientHttpResponse response) throws IOException;
    void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException;
    
    // Template methods for customization
    protected boolean hasError(HttpStatusCode statusCode);
    protected void handleError(ClientHttpResponse response, HttpStatusCode statusCode) throws IOException;
}

Usage Examples:

// Custom error handler
ResponseErrorHandler customErrorHandler = new ResponseErrorHandler() {
    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        return response.getStatusCode().is4xxClientError() || 
               response.getStatusCode().is5xxServerError();
    }
    
    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        HttpStatusCode statusCode = response.getStatusCode();
        if (statusCode.is4xxClientError()) {
            throw new ClientErrorException("Client error: " + statusCode);
        }
        if (statusCode.is5xxServerError()) {
            throw new ServerErrorException("Server error: " + statusCode);
        }
    }
};

// Apply to RestTemplate
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(customErrorHandler);

// Apply to RestClient
RestClient restClient = RestClient.builder()
    .defaultStatusHandler(HttpStatus::is4xxClientError, 
        (request, response) -> {
            throw new ClientErrorException(response.getStatusCode());
        })
    .build();

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework--spring-web

docs

http-abstractions.md

http-clients.md

index.md

message-conversion.md

reactive-web.md

web-binding.md

web-utilities.md

tile.json