Using Spring Boot 3 Declarative HTTP Client with HttpServiceProxyFactory

This article explains how Spring Boot 3 introduces a native declarative HTTP client via HttpServiceProxyFactory, showing required dependencies, supported annotations, interface definition, and complete code examples for building, configuring, and invoking remote HTTP services without third‑party libraries.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Using Spring Boot 3 Declarative HTTP Client with HttpServiceProxyFactory

In modern Java development, remote HTTP calls are common, and frameworks such as OpenFeign, Retrofit, or Hutool HttpUtil have been widely used. Spring Boot 3 adds native support for declarative HTTP clients through HttpServiceProxyFactory, reducing the need for external libraries.

The declarative HTTP interface works like a regular Java interface annotated with @HttpExchange and related method‑level annotations ( @GetExchange, @PostExchange, @PutExchange, @DeleteExchange, @PatchExchange) to specify HTTP verbs and endpoints.

To enable this feature, add the Spring Web (or WebFlux for reactive support) starter dependency:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- For reactive support -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

Define a HTTP service interface with @HttpExchange and method annotations, for example:

@HttpExchange(url = "/users", accept = "application/json", contentType = "application/json")
public interface UserClient {
  @GetExchange("/")
  Flux<User> getAll();

  @GetExchange("/{id}")
  Mono<User> getById(@PathVariable("id") Long id);

  @PostExchange("/")
  Mono<ResponseEntity<Void>> save(@RequestBody User user);

  @PutExchange("/{id}")
  Mono<ResponseEntity<Void>> update(@PathVariable Long id, @RequestBody User user);

  @DeleteExchange("/{id}")
  Mono<ResponseEntity<Void>> delete(@PathVariable Long id);
}

Configure a WebClient and create the proxy factory:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.howtodoinjava.app.web.UserClient;
import lombok.SneakyThrows;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.support.WebClientAdapter;
import org.springframework.web.service.invoker.HttpServiceProxyFactory;

@Configuration
public class WebConfig {
  @Bean
  WebClient webClient(ObjectMapper objectMapper) {
    return WebClient.builder()
        .baseUrl("https://jsonplaceholder.typicode.com/")
        .build();
  }

  @SneakyThrows
  @Bean
  UserClient userClient(WebClient webClient) {
    HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient)).build();
    return factory.createClient(UserClient.class);
  }
}

Define a simple User entity class (omitting getters/setters for brevity) and inject UserClient to perform CRUD operations:

@Autowired
UserClient userClient;

// Get all users
userClient.getAll().subscribe(data -> log.info("User: {}", data));

// Get user by ID
userClient.getById(1L).subscribe(data -> log.info("User: {}", data));

// Create a new user
userClient.save(new User(null, "Lokesh", "lokesh", "[email protected]"))
    .subscribe(data -> log.info("User: {}", data));

// Delete a user
userClient.delete(1L).subscribe(data -> log.info("User: {}", data));

With this approach, developers can call remote HTTP services using a type‑safe, annotation‑driven interface without writing implementation code, leveraging Spring’s native support introduced in Spring Boot 3.

Additional resources include the Spring Boot 3 release notes, the GitHub repository containing the demo code, and the official Spring Framework documentation on declarative HTTP interfaces.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBackend DevelopmentSpring BootDeclarative HTTP clientHttpServiceProxyFactory
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.