### Start Local Development Server Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/README.md Starts a local development server for live preview and hot-reloading. Changes are reflected without a server restart. ```bash yarn start ``` -------------------------------- ### Install Dependencies Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/README.md Installs project dependencies using Yarn. Run this command before starting local development or building the project. ```bash yarn ``` -------------------------------- ### Spring Boot Application Setup Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/01-intro.mdx A basic Spring Boot application structure. The ApplicationRunner bean demonstrates how to use the created PostApi client to fetch a post. ```java @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } // highlight-start @Bean PostApi postApi(RestClient.Builder builder) { HttpServiceProxyFactory factory = HttpServiceProxyFactory .builderFor(RestClientAdapter.create(builder.build())) .build(); return factory.createClient(PostApi.class); } // highlight-end // Imagine there are 100 HttpExchange clients 😇 @Bean ApplicationRunner runner(PostApi api) { return args -> api.getPost(1); } } ``` -------------------------------- ### Generate Interface Server Implementation Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/20-generate-server-implementation.mdx This example demonstrates generating a default interface implementation. The generated interface includes default methods that throw `NOT_IMPLEMENTED` exceptions. You implement this generated interface in your concrete service class. ```java // source code @HttpExchange("/user") public interface UserApi { @GetExchange("/{id}") UserDTO getUser(@PathVariable("id") String id); } // generated code @HttpExchange("/user") public interface UserApiBase { @GetExchange("/{id}") default UserDTO getUser(@PathVariable("id") String id) { throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED); } } // use generated code @RestController public class UserApiImpl implements UserApiBase { @Override public UserDTO getUser(String id) { return new UserDTO(id, "Foo"); } } ``` -------------------------------- ### Generate Abstract Class Server Implementation Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/20-generate-server-implementation.mdx This example shows how to generate an abstract class implementation for a server interface. The generated class provides default implementations that throw `NOT_IMPLEMENTED` exceptions, which you then override in your concrete implementation. ```java // source code @HttpExchange("/user") public interface UserApi { @GetExchange("/{id}") UserDTO getUser(@PathVariable("id") String id); } // generated code public abstract class UserApiBase implements UserApi { @Override public UserDTO getUser(String id) { throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED); } } // use generated code @RestController public class UserApiImpl extends UserApiBase { @Override public UserDTO getUser(String id) { return new UserDTO(id, "Foo"); } } ``` -------------------------------- ### Define and Enable HttpExchange Interface Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/README.md Define your API interface using the @HttpExchange annotation and enable the starter in your Spring Boot application. This example shows how to fetch a post by its ID. ```java @HttpExchange("https://my-json-server.typicode.com") interface PostApi { @GetExchange("/typicode/demo/posts/{id}") Post getPost(@PathVariable("id") int id); } ``` ```java @SpringBootApplication @EnableExchangeClients public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } @Bean ApplicationRunner runner(PostApi api) { return args -> api.getPost(1); } } ``` -------------------------------- ### Enable HttpExchange Clients with @EnableExchangeClients Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/01-intro.mdx Annotate your main application class with @EnableExchangeClients to enable the discovery and creation of HttpExchange client beans. This example also shows the PostApi interface and an ApplicationRunner to use the client. ```java @HttpExchange("https://my-json-server.typicode.com") interface PostApi { @GetExchange("/typicode/demo/posts/{id}") Post getPost(@PathVariable("id") int id); } @SpringBootApplication // highlight-next-line-as-added @EnableExchangeClients public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } @Bean ApplicationRunner runner(PostApi api) { return args -> api.getPost(1); } } ``` -------------------------------- ### Custom WebClient HttpClientCustomizer Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/80-customization.mdx Implement HttpClientCustomizer.WebClientCustomizer to customize the underlying WebClient's HTTP client. This enables advanced configurations such as proxy or SSL setup, particularly for specific channels. ```java // 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)); } }; } ``` -------------------------------- ### HttpExchange with Validation Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/40-validation.mdx Example of an HttpExchange interface with validation annotations applied to method parameters. ```APIDOC ## GET /typicode/demo/posts/{id} ### Description Retrieves a specific post by its ID, with validation applied to the ID parameter. ### Method GET ### Endpoint /typicode/demo/posts/{id} ### Parameters #### Path Parameters - **id** (int) - Required - The ID of the post to retrieve. Must be between 1 and 3 (inclusive). ### Request Example (No request body for this GET request) ### Response #### Success Response (200) - **Post** (object) - The post object matching the provided ID. #### Response Example (Example response structure for a Post object would go here if provided in source) ``` -------------------------------- ### Define an HTTP Interface with @HttpExchange Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/01-intro.mdx Define an interface annotated with @HttpExchange to declare HTTP endpoints. Use annotations like @GetExchange and @PathVariable to map methods to HTTP requests. This example shows how to fetch a post by its ID. ```java @HttpExchange("https://my-json-server.typicode.com") interface PostApi { @GetExchange("/typicode/demo/posts/{id}") Post getPost(@PathVariable("id") int id); } ``` -------------------------------- ### Generate Server Implementation with Gradle Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/20-generate-server-implementation.mdx Run the Gradle clean compileJava task to trigger the annotation processor and generate the server implementation code. ```shell ./gradlew clean compileJava ``` -------------------------------- ### Apply Code Formatting Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/CONTRIBUTING.md Run this command to apply the project's code formatter. Ensure your code adheres to the established style guidelines. ```shell ./gradlew spotlessApply ``` -------------------------------- ### Generate Server Implementation with Maven Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/20-generate-server-implementation.mdx Execute the Maven clean compile command to invoke the annotation processor and generate the server implementation code. ```shell ./mvnw clean compile ``` -------------------------------- ### Build Static Website Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/README.md Generates the static content for the website into the 'build' directory. This output can be hosted on any static hosting service. ```bash yarn build ``` -------------------------------- ### Full application.yml Reference for HttpExchange Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt This configuration shows all available http-exchange properties for enabling autoconfiguration, setting base packages, default base URLs, client types, and load balancing. It also details channel-specific configurations for routing, timeouts, headers, and client matching. ```yaml spring: http: client: settings: read-timeout: 10s connect-timeout: 1s http-exchange: enabled: true # enable/disable the autoconfiguration base-packages: [com.example.api] # packages to scan for @HttpExchange interfaces base-url: http://api-gateway # global default base-url client-type: rest_client # REST_CLIENT or WEB_CLIENT (auto-detected by default) bean-to-query-enabled: false # auto-convert beans to query params loadbalancer-enabled: true # use Spring Cloud LoadBalancer if on classpath warn-unused-config-enabled: true # warn when a channel config matches no clients http-client-reuse-enabled: true # share underlying HTTP client across same-config channels headers: - key: X-App-Name values: ${spring.application.name} refresh: enabled: false # dynamic config refresh (needs spring-cloud-context) channels: - base-url: http://user-service read-timeout: 3000 connect-timeout: 500 loadbalancer-enabled: true headers: - key: X-Service-Token values: [secret] clients: - com.example.api.user.*Api classes: # use 'classes' for exact type-safe matching - com.example.api.user.UserApi - base-url: https://external.api.com read-timeout: 10000 loadbalancer-enabled: false client-type: rest_client clients: - external-api # kebab-case simple name ``` -------------------------------- ### Implement User API with HttpExchange Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/45-best-practice.mdx Provides a basic implementation for the User API. This serves as a placeholder for the actual user data retrieval logic. ```java @RestController public class UserApiImpl implements UserApi { @Override public UserDTO getById(String id) { // Ignore the implementation } } ``` -------------------------------- ### Configure HttpExchange Clients via application.yml Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/10-autoconfiguration.mdx Configure HttpExchange clients by specifying base packages and a list of client classes in the application.yml file. This approach is an alternative to using annotations. ```yaml http-exchange: base-packages: [ com.example ] clients: - com.foo.PostApi - com.bar.UserApi ``` -------------------------------- ### Reactive Client with WebClient Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt When an interface method returns a Reactor type (Mono/Flux), the starter automatically uses WebClient. No explicit client-type configuration is typically needed. ```java @HttpExchange("/user/reactive") public interface UserReactiveApi { @GetExchange("/{id}") Mono get(@PathVariable("id") String id); @GetExchange Flux list(); } // Usage in a reactive service @Service public class ReactiveUserService { private final UserReactiveApi userReactiveApi; public ReactiveUserService(UserReactiveApi userReactiveApi) { this.userReactiveApi = userReactiveApi; } public Mono findUser(String id) { return userReactiveApi.get(id) .onErrorResume(e -> Mono.error(new RuntimeException("User not found: " + id, e))); } public Flux allUsers() { return userReactiveApi.list() .filter(u -> u.status().equals("ACTIVE")); } } ``` -------------------------------- ### Deploy Website (SSH) Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/README.md Deploys the website using SSH. This command builds the static content and pushes it to the 'gh-pages' branch, suitable for GitHub Pages hosting. ```bash USE_SSH=true yarn deploy ``` -------------------------------- ### Configure Annotation Processor for Server Generation Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Configure the httpexchange-processor in build.gradle and define properties in httpexchange-processor.properties to enable server implementation generation. ```groovy // build.gradle dependencies { annotationProcessor("io.github.danielliu1123:httpexchange-processor:") } compileJava { options.compilerArgs.add("-AhttpExchangeConfig=${projectDir}/httpexchange-processor.properties") } ``` ```properties # httpexchange-processor.properties enabled=true suffix=Base generatedType=ABSTRACT_CLASS # or INTERFACE packages=com.example.api outputSubpackage=generated ``` -------------------------------- ### Enable Exchange Clients with Base Packages and Specific Clients Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/10-autoconfiguration.mdx Combine basePackages and clients attributes in the @EnableExchangeClients annotation to specify both a package to scan and a list of explicit client interfaces. Settings from the annotation take precedence over configuration file settings. ```java @EnableExchangeClients(basePackages = "com.example", clients = {PostApi.class, UserApi.class}) ``` -------------------------------- ### Configure HttpExchange Clients via application.yml Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Alternatively, configure HttpExchange clients entirely via application.yml. Annotation settings take precedence when both annotations and YAML configurations are present. ```yaml http-exchange: base-packages: [com.example.api] clients: - com.example.internal.InternalApi ``` -------------------------------- ### Add HttpExchange Spring Boot Starter Dependency Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/README.md Include this dependency in your Spring Boot project to enable the HttpExchange starter. Choose the appropriate starter based on your underlying HTTP client (RestClient or WebClient). ```groovy implementation("org.springframework.boot:spring-boot-starter-restclient") // use RestClient as underlying http client // implementation("org.springframework.boot:spring-boot-starter-webclient") // use WebClient as underlying http client implementation("io.github.danielliu1123:httpexchange-spring-boot-starter:") ``` ```groovy implementation("io.github.danielliu1123:httpexchange-spring-boot-starter:3.5.5") ``` -------------------------------- ### Custom Configuration Properties Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/20-generate-server-implementation.mdx Use this properties file to configure the generation of server implementations. Specify options like enabled status, class name suffixes and prefixes, generated code type, packages to scan, and output subpackages. ```properties enabled=true suffix=Base prefix= generatedType=INTERFACE packages=com.example.api outputSubpackage=generated ``` -------------------------------- ### Configure HTTP Client Settings Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/30-configuration.mdx Set global read timeouts and define channel-specific base URLs and timeouts. This configuration applies to multiple clients within a channel. ```yaml spring: http: client: settings: read-timeout: 5s http-exchange: channels: - base-url: http://user read-timeout: 3000 # Channel-level timeout (in milliseconds) clients: - com.example.user.api.*Api - base-url: http://order clients: - com.example.order.api.*Api ``` -------------------------------- ### Gradle Dependencies for HttpExchange Starter Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Add the starter to your Gradle build. For Spring Boot versions 4.0.0 and above, you must also include a HTTP client starter like spring-boot-starter-restclient or spring-boot-starter-webclient. For older versions, use the last compatible version of the starter. ```groovy // Gradle – Spring Boot >= 4.0.0 implementation("org.springframework.boot:spring-boot-starter-restclient") // or spring-boot-starter-webclient implementation("io.github.danielliu1123:httpexchange-spring-boot-starter:") // Spring Boot < 4.0.0 (last compatible version) implementation("io.github.danielliu1123:httpexchange-spring-boot-starter:3.5.5") ``` -------------------------------- ### Define @HttpExchange Client Interface Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Annotate a plain Java interface with @HttpExchange for the base URL and content type, along with HTTP method annotations. The starter registers this interface as a bean that can be injected and used directly. ```java @HttpExchange("https://my-json-server.typicode.com") public interface PostApi { @GetExchange("/typicode/demo/posts/{id}") Post getPost(@PathVariable("id") int id); @GetExchange("/typicode/demo/posts") List listPosts(); @PostExchange("/typicode/demo/posts") Post createPost(@RequestBody Post post); @DeleteExchange("/typicode/demo/posts/{id}") void deletePost(@PathVariable("id") int id); } ``` -------------------------------- ### Deploy Website (No SSH) Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/README.md Deploys the website without using SSH. Requires specifying your GitHub username. This command builds the static content and pushes it to the 'gh-pages' branch. ```bash GIT_USER= yarn deploy ``` -------------------------------- ### Configure Base URL and Timeouts for HttpExchange Channels Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/10-autoconfiguration.mdx Configure different base URLs, read timeouts, and client patterns for various HttpExchange channels in application.yaml. Ant-style patterns can be used to match client interfaces within a channel. ```yaml http-exchange: base-packages: [ com.example ] channels: - base-url: http://user read-timeout: 3000 clients: - com.example.user.api.*Api # Ant-style pattern - base-url: http://order read-timeout: 5000 clients: - com.example.order.api.*Api ``` -------------------------------- ### Implement Order API with HttpExchange Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/45-best-practice.mdx Provides an implementation for the Order API, interacting with the User API. It includes logic to check user status before returning orders. ```java @RestController public class OrderApiImpl implements OrderApi { @Autowired private UserApi userApi; @Override public List getOrdersByUserId(String userId) { UserDTO user = userApi.getUser(userId); if (user.getStatus() == INACTIVE) { throw new UserInactiveException(); } // Ignore the implementation } } ``` -------------------------------- ### Maven Dependencies for HttpExchange Starter Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Add the starter to your Maven build. For Spring Boot versions 4.0.0 and above, you must also include a HTTP client starter like spring-boot-starter-restclient. For older versions, use the last compatible version of the starter. ```xml org.springframework.boot spring-boot-starter-restclient io.github.danielliu1123 httpexchange-spring-boot-starter ${latest} ``` -------------------------------- ### HTTP Exchange Configuration Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Configure base packages, default headers, and client channel settings in application.yml. Channels define base URLs, timeouts, and specific client patterns. ```yaml http-exchange: base-packages: [com.example.api] headers: - key: X-App-Name values: ${spring.application.name} channels: - base-url: http://user-service # service name or full URL read-timeout: 3000 # milliseconds connect-timeout: 1000 headers: - key: X-Tenant values: acme clients: - com.example.api.user.*Api # Ant-style pattern - base-url: http://order-service read-timeout: 5000 clients: - com.example.api.order.*Api - com.example.api.OrderApi # exact class name also works - base-url: https://payments.example.com client-type: rest_client clients: - payment-api # kebab-case simple name ``` -------------------------------- ### Load Balancer Integration Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Add spring-cloud-starter-loadbalancer to enable client-side load balancing. Use service names as base-urls for integration. Load balancing can be disabled per channel or globally. ```groovy implementation("org.springframework.cloud:spring-cloud-starter-loadbalancer") ``` ```yaml http-exchange: channels: - base-url: user-service # service ID — resolved via load balancer clients: - com.example.api.user.*Api - base-url: http://external.api # full URL — load balancer skipped loadbalancer-enabled: false clients: - com.example.api.ExternalApi # Disable load balancer globally # http-exchange: # loadbalancer-enabled: false ``` -------------------------------- ### Add Maven Dependency for Server Implementation Generation Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/20-generate-server-implementation.mdx Configure the maven-compiler-plugin in your pom.xml to include the annotation processor and specify the configuration properties file. ```xml maven-compiler-plugin io.github.danielliu1123 httpexchange-processor latest -AhttpExchangeConfig=${project.basedir}/httpexchange-processor.properties ``` -------------------------------- ### Enable Exchange Clients with Base Packages Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/10-autoconfiguration.mdx Use the @EnableExchangeClients annotation with the basePackages attribute to specify the packages where HttpExchange clients should be scanned. If basePackages is specified, it overrides the default behavior of scanning the annotated class's package. ```java @EnableExchangeClients(basePackages = "com.example") ``` -------------------------------- ### Identify HTTP Clients by Class Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/30-configuration.mdx Configure channels to identify clients using their canonical class names, simple names (Pascal-case or Kebab-case), or Ant-style patterns. The `classes` property takes precedence over `clients` if both are configured. ```yaml http-exchange: channels: - base-url: http://service clients: [com.example.PostApi] # Class canonical name # clients: [post-api] Class simple name (Kebab-case) # clients: [PostApi] Class simple name (Pascal-case) # clients: [com.**.*Api] (Ant-style pattern) classes: [com.example.PostApi] # Class canonical name ``` -------------------------------- ### Configure Base URL in application.yml Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/50-url-variables.mdx Set the base URL for the HttpExchange client in your `application.yml` file using property placeholders. ```yaml api: post: url: https://jsonplaceholder.typicode.com ``` -------------------------------- ### Custom RestClient HttpClientCustomizer Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/80-customization.mdx Implement HttpClientCustomizer.RestClientCustomizer to customize the underlying RestClient's HTTP client. This allows for configurations like setting up proxies or SSL, especially useful when targeting specific channels. ```java // 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)); } }; } ``` -------------------------------- ### Instantiate HttpExchange Client Bean Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/01-intro.mdx Configure a Spring bean to create an instance of your HTTP interface. This involves using RestClient.Builder and HttpServiceProxyFactory to create a client proxy for the interface. This is necessary for managing multiple clients. ```java @Bean PostApi postApi(RestClient.Builder builder) { HttpServiceProxyFactory factory = HttpServiceProxyFactory .builderFor(RestClientAdapter.create(builder.build())) .build(); return factory.createClient(PostApi.class); } ``` -------------------------------- ### Customize RestClient with SSL and Connection Timeout Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Implement HttpClientCustomizer.RestClientCustomizer to configure SSL context and connection timeouts for a named RestClient channel. ```java @Configuration public class HttpClientConfig { // Customize RestClient for a named channel @Bean HttpClientCustomizer.RestClientCustomizer sslRestClientCustomizer() { return (restClientBuilder, channel) -> { if ("secure-channel".equals(channel.getName())) { HttpClient httpClient = HttpClient.newBuilder() .sslContext(customSslContext()) .connectTimeout(Duration.ofSeconds(5)) .build(); restClientBuilder.requestFactory(new JdkClientHttpRequestFactory(httpClient)); } }; } // Customize WebClient for reactive channels @Bean HttpClientCustomizer.WebClientCustomizer proxyWebClientCustomizer() { return (webClientBuilder, channel) -> { if ("external-channel".equals(channel.getName())) { HttpClient httpClient = HttpClient.newBuilder().build(); webClientBuilder.clientConnector(new JdkClientHttpConnector(httpClient)); } }; } private SSLContext customSslContext() { // ... build SSLContext return null; } } ``` -------------------------------- ### Enable LoadBalancer with Gradle Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/20-loadbalancer.mdx Add the Spring Cloud LoadBalancer starter dependency to your Gradle project to automatically enable the load balancer. ```groovy implementation("org.springframework.cloud:spring-cloud-starter-loadbalancer") ``` -------------------------------- ### Enable LoadBalancer with Maven Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/20-loadbalancer.mdx Add the Spring Cloud LoadBalancer starter dependency to your Maven project to automatically enable the load balancer. ```xml org.springframework.cloud spring-cloud-starter-loadbalancer ``` -------------------------------- ### Maven Dependencies for Spring Boot 3 Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/01-intro.mdx Include the httpexchange spring boot starter in your Maven pom.xml for Spring Boot versions prior to 4.0.0. ```xml io.github.danielliu1123 httpexchange-spring-boot-starter latest ``` -------------------------------- ### Enable Dynamic Refresh Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/40-dynamic-refresh.mdx Configure `application.yml` to enable the dynamic refresh feature. This setting is disabled by default. ```yaml http-exchange: refresh: enabled: true # default is false ``` -------------------------------- ### Enable Exchange Clients with Specific Clients Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/10-autoconfiguration.mdx Use the @EnableExchangeClients annotation with the clients attribute to explicitly list the HttpExchange client interfaces to be registered. This method is faster than classpath scanning as it directly specifies the classes. ```java @EnableExchangeClients(clients = {PostApi.class, UserApi.class}) ``` -------------------------------- ### Manually Configure RepositoryService with RestClient Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/80-customization.mdx Configure a RepositoryService bean manually by creating a RestClient and HttpServiceProxyFactory. This approach bypasses the autoconfigured HTTP client bean and is useful for deep customization or when integrating with existing RestClient configurations. ```java 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); } } ``` -------------------------------- ### Maven Dependencies for Spring Boot 4+ Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/01-intro.mdx Configure your Maven pom.xml with the required dependencies for Spring Boot 4.0.0 and later. This includes the starter for REST clients and the httpexchange starter. ```xml org.springframework.boot spring-boot-starter-restclient io.github.danielliu1123 httpexchange-spring-boot-starter latest ``` -------------------------------- ### Add Gradle Dependency for Server Implementation Generation Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/20-generate-server-implementation.mdx Add the annotation processor dependency to your Gradle build file. Configure the compiler arguments to specify the properties file for processor configuration. ```groovy dependencies { annotationProcessor("io.github.danielliu1123:httpexchange-processor:latest") } compileJava { options.compilerArgs.add("-AhttpExchangeConfig=${projectDir}/httpexchange-processor.properties") } ``` -------------------------------- ### Define HttpExchange Interface with URL Variable Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/50-url-variables.mdx Use the `@HttpExchange` annotation with a placeholder for the base URL, which will be resolved from configuration properties. ```java import org.springframework.web.service.annotation.GetExchange; import org.springframework.web.service.annotation.HttpExchange; import org.springframework.web.service.annotation.PathVariable; @HttpExchange("${api.post.url}") public interface PostApi { @GetExchange("/typicode/demo/posts/{id}") Post getPost(@PathVariable("id") int id); } ``` -------------------------------- ### Gradle Dependencies for Spring Boot 4+ Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/01-intro.mdx Add the necessary dependencies to your Gradle build file for Spring Boot version 4.0.0 and above. This includes the starter for REST clients and the httpexchange starter. ```groovy // swap to spring-boot-starter-webclient if you use WebClient implementation("org.springframework.boot:spring-boot-starter-restclient") implementation("io.github.danielliu1123:httpexchange-spring-boot-starter:") ``` -------------------------------- ### Generated Server Implementation Base Class Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt An abstract base class generated by httpexchange-processor for @HttpExchange interfaces. Servers extend this class and override methods. ```java // Source interface (in shared api module) @HttpExchange("/users") public interface UserApi { @GetExchange("/{id}") UserDTO getUser(@PathVariable("id") String id); @PostExchange UserDTO createUser(@RequestBody UserDTO user); } // Auto-generated by the processor public abstract class UserApiBase implements UserApi { @Override public UserDTO getUser(String id) { throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED); } @Override public UserDTO createUser(UserDTO user) { throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED); } } // Server implementation — just override what you need @RestController public class UserController extends UserApiBase { private final UserRepository userRepository; public UserController(UserRepository userRepository) { this.userRepository = userRepository; } @Override public UserDTO getUser(String id) { return userRepository.findById(id) .map(u -> new UserDTO(u.getId(), u.getName())) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); } @Override public UserDTO createUser(UserDTO user) { return userRepository.save(user); } } ``` -------------------------------- ### Configure Client Type in application.yml Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/80-customization.mdx Set the http-exchange.client-type property in application.yml to specify whether to use REST_CLIENT or WEB_CLIENT. The framework automatically selects the client based on reactive return types, so explicit configuration is often unnecessary. ```yaml http-exchange: client-type: REST_CLIENT ``` -------------------------------- ### Gradle Dependencies for Spring Boot 3 Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/01-intro.mdx Add the httpexchange spring boot starter dependency to your Gradle build file for Spring Boot versions below 4.0.0. ```groovy implementation("io.github.danielliu1123:httpexchange-spring-boot-starter:") ``` -------------------------------- ### Trigger HTTP Client Refresh Programmatically Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Programmatically trigger a refresh event to update HTTP client configurations. This is normally handled by a configuration center. ```java // Trigger a refresh programmatically (normally fired by the config center) @Autowired private ApplicationEventPublisher publisher; public void triggerRefresh() { publisher.publishEvent(new RefreshEvent(this, null, "config updated")); // All @HttpExchange clients now use the refreshed base-url / timeout values } ``` -------------------------------- ### Enable Dynamic Refresh Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Enable dynamic refresh of HTTP clients when a RefreshEvent is published. Requires spring-cloud-context on the classpath. ```yaml http-exchange: refresh: enabled: true # default: false ``` -------------------------------- ### Convert Bean to Query Parameters with @HttpExchange Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/30-bean-to-query.mdx Use this when you need to pass a Java Bean as query parameters to an @HttpExchange endpoint. Ensure 'http-exchange.bean-to-query-enabled=true' is set in your application properties to enable this feature globally. Otherwise, use @BeanParam. ```java public interface PostApi { @GetExchange("/posts") List findAll(Post condition); } ``` -------------------------------- ### Enable HttpExchange Autoconfiguration with @EnableExchangeClients Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Use @EnableExchangeClients on your @SpringBootApplication class to trigger classpath scanning for @HttpExchange interfaces and register them as Spring beans. It supports scanning default, specific, or explicit client packages. ```java // 1. Scan the package of the annotated class (default) @SpringBootApplication @EnableExchangeClients public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } } // 2. Scan a specific package @EnableExchangeClients(basePackages = "com.example.api") // 3. Register only explicit interfaces (fastest startup – no classpath scan) @EnableExchangeClients(clients = {UserApi.class, OrderApi.class}) // 4. Combine both @EnableExchangeClients(basePackages = "com.example.api", clients = {InternalApi.class}) ``` -------------------------------- ### Contract-Driven Development with @HttpExchange Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Define a shared API interface using @HttpExchange, implement it on the server as a REST controller, and inject it as an HTTP client in consumer modules. This enforces a consistent contract between services. ```java // shared api module: order-api @HttpExchange("/orders") public interface OrderApi { @GetExchange("/by_user/{userId}") List getOrdersByUserId(@PathVariable("userId") String userId); @PostExchange OrderDTO placeOrder(@RequestBody PlaceOrderRequest request); } // order-server module: implements the interface as a REST controller @RestController public class OrderController implements OrderApi { @Autowired private UserApi userApi; // injected HTTP client from user-service @Override public List getOrdersByUserId(String userId) { UserDTO user = userApi.getUser(userId); if (user.status() == UserStatus.INACTIVE) { throw new ResponseStatusException(HttpStatus.FORBIDDEN, "User inactive"); } return orderRepository.findByUserId(userId); } @Override public OrderDTO placeOrder(PlaceOrderRequest request) { // ... } } // any consumer module: injects OrderApi as an HTTP client @Service public class ReportService { private final OrderApi orderApi; public ReportService(OrderApi orderApi) { this.orderApi = orderApi; } public List getReport(String userId) { return orderApi.getOrdersByUserId(userId); } } ``` -------------------------------- ### Validation Support with @Validated Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Enable JSR-303 validation by adding spring-boot-starter-validation and annotating interfaces with @Validated. Validation is enforced client-side before the HTTP call. ```java @Validated @HttpExchange("${api.post.url}") public interface PostApi { @GetExchange("/posts/{id}") Post getPost( @PathVariable("id") @Min(1) @Max(100) int id ); @PostExchange("/posts") Post createPost( @RequestBody @Valid Post post ); } // Violation throws ConstraintViolationException before the HTTP call is made try { postApi.getPost(0); // id < 1 → validation fails } catch (ConstraintViolationException e) { // handle validation error } ``` -------------------------------- ### Define Order API Contract with HttpExchange Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/45-best-practice.mdx Defines the contract for the order service API using @HttpExchange. This interface specifies endpoints for retrieving orders by user ID. ```java @HttpExchange("/orders") public interface OrderApi { @GetExchange("/by_user/{userId}") List getOrdersByUserId(@PathVariable("userId") String userId); } ``` -------------------------------- ### Define User API Contract with HttpExchange Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/45-best-practice.mdx Defines the contract for the user service API using @HttpExchange. This interface specifies endpoints for retrieving user data by ID. ```java @HttpExchange("/users") public interface UserApi { @GetExchange("/{id}") UserDTO getUser(@PathVariable("id") String id); } ``` -------------------------------- ### Disable LoadBalancer Globally Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/20-loadbalancer.mdx Set `http-exchange.loadbalancer-enabled` to `false` in your `application.yml` to disable the load balancer for all HttpExchange clients. ```yaml http-exchange: loadbalancer-enabled: false ``` -------------------------------- ### Disable LoadBalancer for Specific Channel Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/20-loadbalancer.mdx Disable the load balancer for a specific channel by setting `loadbalancer-enabled` to `false` within the channel configuration in `application.yml`. ```yaml http-exchange: channels: - base-url: user # highlight-next-line-as-added loadbalancer-enabled: false clients: - com.example.user.api.*Api ``` -------------------------------- ### Interface with Validation Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/10-core/40-validation.mdx Use the @Validated annotation on an HttpExchange interface to enable validation. Constraints like @Min and @Max can be applied to method parameters. ```java @HttpExchange("${api.post.url}") @Validated public interface PostApi { @GetExchange("/typicode/demo/posts/{id}") Post getPost(@PathVariable("id") @Min(1) @Max(3) int id); } ``` -------------------------------- ### Inject and Use @HttpExchange Client Interface Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Inject the defined @HttpExchange client interface directly into your Spring services. No boilerplate factory code is needed for instantiation. ```java // Inject and use directly — no boilerplate factory code needed @Service public class PostService { private final PostApi postApi; public PostService(PostApi postApi) { this.postApi = postApi; } public Post findPost(int id) { return postApi.getPost(id); } } ``` -------------------------------- ### @BeanParam for Query Parameter Conversion Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Use @BeanParam to convert a Java bean's fields into query parameters. Null fields are ignored, and non-null fields are included in the URL. This can also be enabled globally. ```java // API definition public interface UserApi { // Using @BeanParam on a specific parameter (selective) @GetExchange("/users") List search(@BeanParam UserSearchCondition condition); // Alternatively, enable globally via http-exchange.bean-to-query-enabled=true @GetExchange("/users/all") List findAll(UserSearchCondition condition); } public class UserSearchCondition { private String name; private Integer age; private String status; // getters/setters ... } // Usage — null fields are ignored, non-null fields become ?name=Alice&age=30 UserSearchCondition condition = new UserSearchCondition(); condition.setName("Alice"); condition.setAge(30); // Results in GET /users?name=Alice&age=30 List users = userApi.search(condition); ``` ```yaml # Enable globally (applies to all clients without needing @BeanParam) http-exchange: bean-to-query-enabled: true ``` -------------------------------- ### Custom HttpServiceArgumentResolver Bean Source: https://github.com/danielliu1123/httpexchange-spring-boot-starter/blob/main/website/docs/20-extensions/80-customization.mdx Provide a custom HttpServiceArgumentResolver bean to alter how arguments are resolved for HTTP service interfaces. The framework will auto-detect and apply these resolvers. ```java @Bean HttpServiceArgumentResolver yourHttpServiceArgumentResolver() { return new YourHttpServiceArgumentResolver(); } ``` -------------------------------- ### URL Variables in @HttpExchange Source: https://context7.com/danielliu1123/httpexchange-spring-boot-starter/llms.txt Use Spring property placeholders in the @HttpExchange annotation to externalize base URLs. This keeps URLs out of your Java code. ```java @HttpExchange("${api.user.url}") public interface UserApi { @GetExchange("/users/{id}") UserDTO getUser(@PathVariable("id") String id); } ``` ```yaml # application.yml api: user: url: https://api.example.com ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.