Complete Guide to Calling External REST APIs in Spring Boot: From RestTemplate to WebClient

Nov 19, 2025 · Programming · 14 views · 7.8

Keywords: Spring Boot | REST API | HTTP Client | RestTemplate | WebClient | External Service Call

Abstract: This article provides an in-depth exploration of various methods for calling external REST APIs in Spring Boot applications. It focuses on RestTemplate usage, including basic configuration, request sending, and response handling, while also introducing modern alternatives like WebClient. Through detailed code examples and configuration explanations, it helps developers choose the appropriate HTTP client based on application requirements, covering advanced features such as SSL configuration and timeout settings.

Introduction

In modern microservices architecture, applications frequently need to communicate with other services. Spring Boot provides multiple ways to call external REST APIs, allowing developers to choose the appropriate HTTP client based on their specific application needs. This article systematically introduces various solutions, from the traditional RestTemplate to modern alternatives like WebClient.

RestTemplate: The Classic HTTP Client

RestTemplate is a long-standing HTTP client in the Spring framework, providing synchronous blocking APIs. While modern alternatives are recommended for new projects, RestTemplate remains a reliable choice for maintaining existing code or when simple synchronous calls are needed.

Spring Boot offers convenient configuration through RestTemplateBuilder:

import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class NotificationService {
    private final RestTemplate restTemplate;
    
    public NotificationService(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
    }
    
    public String callExternalAPI() {
        String apiUrl = "https://fcm.googleapis.com/fcm/send";
        return restTemplate.getForObject(apiUrl, String.class);
    }
}

The above code demonstrates the basic usage pattern of RestTemplate. By dependency injecting RestTemplateBuilder, Spring Boot automatically configures appropriate message converters and HTTP request factories.

Advanced RestTemplate Configuration

In practical applications, more granular configuration of the HTTP client is often required:

@Service
public class CustomRestTemplateService {
    private final RestTemplate restTemplate;
    
    public CustomRestTemplateService(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder
            .setConnectTimeout(Duration.ofSeconds(5))
            .setReadTimeout(Duration.ofSeconds(10))
            .basicAuthentication("username", "password")
            .build();
    }
    
    public void sendFCMNotification(String message) {
        String fcmUrl = "https://fcm.googleapis.com/fcm/send";
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "key=YOUR_SERVER_KEY");
        headers.setContentType(MediaType.APPLICATION_JSON);
        
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("to", "/topics/news");
        requestBody.put("notification", Map.of("body", message));
        
        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(fcmUrl, entity, String.class);
        
        if (response.getStatusCode().is2xxSuccessful()) {
            System.out.println("Notification sent successfully");
        }
    }
}

WebClient: The Modern Reactive HTTP Client

For applications requiring non-blocking, reactive programming, WebClient is the better choice. It provides a functional-style API and fully supports reactive programming models.

import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@Service
public class ReactiveNotificationService {
    private final WebClient webClient;
    
    public ReactiveNotificationService(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder
            .baseUrl("https://fcm.googleapis.com")
            .defaultHeader("Authorization", "key=YOUR_SERVER_KEY")
            .build();
    }
    
    public Mono<String> sendReactiveNotification(String message) {
        Map<String, Object> requestBody = Map.of(
            "to", "/topics/news",
            "notification", Map.of("body", message)
        );
        
        return webClient.post()
            .uri("/fcm/send")
            .bodyValue(requestBody)
            .retrieve()
            .bodyToMono(String.class);
    }
}

SSL Configuration and Security Considerations

In production environments, proper SSL configuration is crucial:

@Service
public class SecureRestTemplateService {
    private final RestTemplate restTemplate;
    
    public SecureRestTemplateService(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {
        this.restTemplate = restTemplateBuilder
            .sslBundle(sslBundles.getBundle("my-ssl-bundle"))
            .build();
    }
    
    public String callSecureAPI() {
        return restTemplate.getForObject("https://secure-api.example.com/data", String.class);
    }
}

Performance Optimization and Best Practices

When using HTTP clients, consider the following performance optimization measures:

@Configuration
public class HttpClientConfig {
    
    @Bean
    public RestTemplateBuilder restTemplateBuilder() {
        return new RestTemplateBuilder()
            .setConnectTimeout(Duration.ofSeconds(3))
            .setReadTimeout(Duration.ofSeconds(10))
            .requestFactory(() -> {
                HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
                factory.setConnectionRequestTimeout(5000);
                return factory;
            });
    }
}

Error Handling and Monitoring

Robust external API calls require comprehensive error handling mechanisms:

@Service
public class RobustAPIClient {
    private final RestTemplate restTemplate;
    
    public RobustAPIClient(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder
            .errorHandler(new CustomErrorHandler())
            .build();
    }
    
    public String callAPIWithErrorHandling() {
        try {
            return restTemplate.getForObject("https://api.example.com/data", String.class);
        } catch (HttpClientErrorException e) {
            // Handle 4xx errors
            logger.error("Client error occurred: " + e.getStatusCode());
            throw new BusinessException("API client error", e);
        } catch (HttpServerErrorException e) {
            // Handle 5xx errors
            logger.error("Server error occurred: " + e.getStatusCode());
            throw new BusinessException("API server error", e);
        }
    }
}

Conclusion

Spring Boot offers rich choices for calling external REST APIs. For traditional synchronous applications, RestTemplate provides a simple and reliable solution, while for applications requiring high concurrency and non-blocking processing, WebClient is the more modern choice. Developers should select the appropriate HTTP client based on specific application scenarios, performance requirements, and team technology stack. Regardless of the chosen solution, it's important to configure appropriate timeouts, implement comprehensive error handling, and consider security and performance optimization.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.