httpexchange-spring-boot-starter

website·Indexed 30 days ago

https://danielliu1123.github.io/httpexchange-spring-boot-starter

A Spring Boot starter designed to eliminate boilerplate code for @HttpExchange clients. It provides autoconfiguration for @HttpExchange clients, support for GraalVM native images, client-side load balancing via spring-cloud-starter-loadbalancer, and integration with spring-boot-starter-validation. Features include dynamic configuration refresh, custom HttpServiceArgumentResolver, and support for contract-driven development.

Tokens
4.5K
Snippets
27
Records
33
Agent score
75%

What's inside httpexchange-spring-boot-starter

  1. Reduce boilerplate for @HttpExchange clients

    The httpexchange-spring-boot-starter library provides a Spring Cloud OpenFeign-like experience for @HttpExchange clients, eliminating the manual boilerplate code typically required to set up and use these clients in Spring Boot applications.
  2. Implement Contract-Driven Development using @HttpExchange

    Use @HttpExchange to define interface contracts that can be shared between a client (API module) and a server (Implementation module). Because @HttpExchange can be used for both client-side proxy generation and server-side endpoint definition (similar to @RequestMapping), it allows developers to maintain a single source of truth for the API contract. A common project structure involves separating the API definition into its own module (e.g., order-api) which is then depended upon by the server implementation (e.g., order-server).
    @HttpExchange("/orders")
    public interface OrderApi {
        @GetExchange("/by_user/{userId}")
        List<OrderDTO> getOrdersByUserId(@PathVariable("userId") String userId);
    }
  3. Select the compatible httpexchange-spring-boot-starter version

    The version of httpexchange-spring-boot-starter is aligned with the version of Spring Boot. To ensure compatibility, use the starter version that matches your Spring Boot major/minor version (e.g., Spring Boot 3.4.x requires httpexchange-spring-boot-starter 3.4.x).
  4. Convert Java Beans to query parameters using annotations

    If global conversion is disabled or not desired, you can use annotations to trigger the conversion of a specific Java Bean to query parameters.

    • @BeanParam: The recommended annotation (inspired by JAX-RS).
    • @SpringQueryMap: Supported for easier migration from Spring Cloud OpenFeign.
    public interface PostApi {
      @GetExchange("/posts")
      List<Post> findAll(@BeanParam Post condition);
    }
  5. Migrate to httpexchange-spring-boot-starter v3.5.0

    Version 3.5.0 drops backward compatibility with Spring Boot versions below 3.5.0 due to internal refactoring in the Spring Boot framework. If your project is using a Spring Boot version older than 3.5.0, you must remain on httpexchange-spring-boot-starter version 3.4.x.
  6. Generate server implementations from @HttpExchange interfaces

    The library can automatically generate default server implementations based on @HttpExchange interfaces. This allows developers to decouple the server-side implementation logic from the API definition, ensuring consistency between the client and server contracts.
  7. Manually configure Http client beans for deep customization

    If the autoconfigured HTTP client does not meet your requirements, you can manually define the client bean using the standard Spring Framework approach. If you manually create the HTTP client bean, the autoconfigured version will not be created.
    interface RepositoryService {
        @GetExchange("/repos/{owner}/{repo}")
        Repository getRepository(@PathVariable String owner, @PathVariable String repo);
    }
    
    @Configuration
    class RepositoryServiceConfiguration {
        @Bean
        public RepositoryService repositoryService(RestClient.Builder restClientBuilder) {
            RestClient restClient = RestClient.builder().baseUrl("https://api.github.com/").build();
            RestClientAdapter adapter = RestClientAdapter.create(restClient);
            HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
            return factory.createClient(RepositoryService.class);
        }
    }
  8. Implement a custom HttpServiceArgumentResolver

    To customize how arguments are resolved for HTTP service proxies, provide your own implementation of HttpServiceArgumentResolver as a Spring bean. The library automatically detects all HttpServiceArgumentResolver beans and applies them when building the HttpServiceProxyFactory.
    @Bean
    HttpServiceArgumentResolver yourHttpServiceArgumentResolver() {
      return new YourHttpServiceArgumentResolver();
    }
  9. Customize the underlying HTTP client using HttpClientCustomizer

    Use HttpClientCustomizer to perform low-level configuration of the underlying HTTP client, such as setting up SSL or proxies. You can target specific channels by checking channel.getName() within the customizer bean.
    // For RestClient
    @Bean
    HttpClientCustomizer.RestClientCustomizer restClientCustomizer() {
        return (restClientBuilder, channel) -> {
            if (Objects.equals(channel.getName(), "whichChannelYouWantToCustomize")) {
                var httpClient = HttpClient.newBuilder().build();
                restClientBuilder.requestFactory(new JdkClientHttpRequestFactory(httpClient));
            }
        };
    }
    
    // For WebClient
    @Bean
    HttpClientCustomizer.WebClientCustomizer webClientCustomizer() {
        return (webClientBuilder, channel) -> {
            if (Objects.equals(channel.getName(), "whichChannelYouWantToCustomize")) {
                var httpClient = HttpClient.newBuilder().build();
                webClientBuilder.clientConnector(new JdkClientHttpConnector(httpClient));
            }
        };
    }
  10. Configure refresh exchange clients in httpexchange-spring-boot-starter

    Enable the ability to refresh exchange clients by setting the http-exchange.refresh.enabled property to true.

    Requirements and Constraints:

    • Requires the spring-cloud-context dependency to be present on the classpath.
    • Native Image Support: This feature is NOT supported by native images due to limitations with Refresh Scope.
    http-exchange:
      refresh:
        enabled: true
  11. Implement request validation in HttpExchange interfaces

    To ensure consistent validation rules across both the client and server, use spring-boot-starter-validation annotations within your @HttpExchange interfaces. Annotate the interface with @Validated and apply standard JSR-303/JSR-380 validation constraints (such as @Min and @Max) to method parameters.
    @HttpExchange("${api.post.url}")
    @Validated
    public interface PostApi {
        @GetExchange("/typicode/demo/posts/{id}")
        Post getPost(@PathVariable("id") @Min(1) @Max(3) int id);
    }