javaintermediate

Spring Boot — RestClient HTTP Calls

Make HTTP requests with Spring RestClient (6.1+): GET, POST, error handling, interceptors, and timeouts.

java
import org.springframework.web.client.RestClient;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.List;

@Service
public class ApiClient {
    private final RestClient client;

    public ApiClient(RestClient.Builder builder) {
        this.client = builder
            .baseUrl("https://api.example.com")
            .defaultHeader("Accept", "application/json")
            .defaultHeader("User-Agent", "SnippetsLab/1.0")
            .requestInterceptor((req, body, execution) -> {
                System.out.printf("→ %s %s%n", req.getMethod(), req.getURI());
                var response = execution.execute(req, body);
                System.out.printf("← %s%n", response.getStatusCode());
                return response;
            })
            .build();
    }

    // GET request
    public record User(Long id, String name, String email) {}

    public User getUser(Long id) {
        return client.get()
            .uri("/users/{id}", id)
            .retrieve()
            .body(User.class);
    }

    // GET list
    public List<User> listUsers() {
        return client.get()
            .uri("/users")
            .retrieve()
            .body(new org.springframework.core.ParameterizedTypeReference<>() {});
    }

    // POST request
    public record CreateUser(String name, String email) {}

    public User createUser(CreateUser payload) {
        return client.post()
            .uri("/users")
            .contentType(MediaType.APPLICATION_JSON)
            .body(payload)
            .retrieve()
            .body(User.class);
    }

    // PUT with headers
    public User updateUser(Long id, CreateUser payload, String authToken) {
        return client.put()
            .uri("/users/{id}", id)
            .header("Authorization", "Bearer " + authToken)
            .body(payload)
            .retrieve()
            .body(User.class);
    }

    // Error handling
    public User getUserSafe(Long id) {
        return client.get()
            .uri("/users/{id}", id)
            .retrieve()
            .onStatus(HttpStatusCode::is4xxClientError, (req, res) -> {
                throw new RuntimeException("Client error: " + res.getStatusCode());
            })
            .onStatus(HttpStatusCode::is5xxServerError, (req, res) -> {
                throw new RuntimeException("Server error: " + res.getStatusCode());
            })
            .body(User.class);
    }

    // Response entity (includes headers and status)
    public ResponseEntity<User> getUserWithMeta(Long id) {
        return client.get()
            .uri("/users/{id}", id)
            .retrieve()
            .toEntity(User.class);
    }
}

Sponsored

Railway

Use Cases

  • REST API consumption in Spring Boot services
  • Microservice-to-microservice communication
  • External API integration with error handling

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.