Spring Boot REST API Timeout (with Examples)
Timeouts in REST APIs happen when an API exceeds the anticipated or permitted duration for completion within a Spring Boot application. Typically, there are two categories of timeouts: connection timeouts and read timeouts. Managing these timeouts is crucial to prevent clients from waiting indefinitely for a response. Let us delve into understanding REST API timeout in Spring Boot using practical examples.
1. Timeout a REST API with Spring MVC
Timeouts are essential for preventing long-running requests from causing performance issues or blocking server resources indefinitely.
1.1 Configure Timeout Properties
First, configure timeout properties in your Spring Boot application’s configuration file (e.g., application.properties or application.yml). You can specify the connection and read timeouts in milliseconds:
# application.properties server.connection-timeout=5000 server.read-timeout=5000
1.2 Implement REST Controller
Create a REST controller with an endpoint that performs the desired operation. For demonstration purposes, we’ll create an endpoint that simulates a time-consuming task:
package com.jcg.example;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TimeoutController {
@GetMapping("/timeout")
public String timeoutDemo() throws InterruptedException {
// Simulate a time-consuming task
Thread.sleep(7000); // Simulate 7 seconds of processing time
return "Task completed successfully!";
}
}
1.3 Handle Timeout Exceptions
Configure exception handling to catch timeouts and return an appropriate response to the client:
package com.jcg.example;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.concurrent.TimeoutException;
@ControllerAdvice
public class TimeoutExceptionHandler {
@ExceptionHandler(TimeoutException.class)
@ResponseBody
public String handleTimeoutException() {
return "Request timed out. Please try again later.";
}
}
1.4 Test the API
Test the API by requesting the endpoint and observing the behavior. If the request exceeds the configured timeout, it should return the appropriate response indicating a timeout.
2. Timeout a REST API with Resilience4j
Resilience4j provides a comprehensive set of resilience patterns, including timeout, to improve the fault tolerance of your application.
2.1 Add Resilience4j Dependencies
First, add the necessary dependencies to your project’s build configuration. For Maven, you can include the following dependencies in your pom.xml:
<dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot2</artifactId> <version>1.7.0</version> </dependency>
2.2 Configure Timeout Settings
Configure timeout settings for your REST API calls using Resilience4j. You can set the timeout duration in milliseconds:
resilience4j.timeout.instances.default.timeout-duration=5000ms
2.3 Create a CircuitBreakerRegistry Bean
In Resilience4j, a CircuitBreaker is a state machine that monitors the health of a system or a particular service by tracking the number of failures that occur within a given time frame. It’s designed to prevent an application from repeatedly trying to execute an operation that’s likely to fail, thus conserving resources and preventing further degradation of the system.
CircuitBreakerConfig is a configuration class in Resilience4j used to define the behavior and characteristics of a CircuitBreaker instance. It allows developers to fine-tune how CircuitBreaker operates based on their application’s requirements and failure-handling strategies.
Create a CircuitBreakerRegistry bean to manage circuit breakers:
package com.jcg.example;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ResilienceConfig {
@Bean
public CircuitBreakerRegistry circuitBreakerRegistry() {
return CircuitBreakerRegistry.of(
CircuitBreakerConfig.custom()
.slidingWindowSize(5)
.permittedNumberOfCallsInHalfOpenState(3)
.waitDurationInOpenState(Duration.ofMillis(1000))
.build()
);
}
}
2.4 Use the Timeout Decorator
Apply the timeout decorator to your REST API calls using Resilience4j annotations:
package com.jcg.example;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TimeoutController {
@TimeLimiter(name = "timeoutDemo")
@GetMapping("/timeout")
public String timeoutDemo() throws InterruptedException {
// Simulate a time-consuming task
Thread.sleep(7000); // Simulate 7 seconds of processing time
return "Task completed successfully!";
}
}
2.5 Test the API
Test the API by requesting the endpoint. If the request exceeds the configured timeout, Resilience4j will handle it and return an appropriate response.
3. Handling Timeouts in Java-Based REST APIs
When building Java-based REST APIs, handling timeouts is crucial to ensure the reliability and responsiveness of your application.
3.1 Timeout a Long-Running Database Operation using @Transactional Annotation
In some cases, database operations may take longer than expected, leading to performance issues or resource contention. To prevent these problems, it’s essential to set a timeout for such operations. In Java, you can achieve this using the @Transactional annotation along with specific configuration.
3.1.1 Configure Transaction Timeout
First, define the timeout value for your transactional method using the timeout attribute of the @Transactionalannotation. The timeout value is specified in seconds:
package com.jcg.example;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
@Transactional(timeout = 30) // Timeout set to 30 seconds
public void longRunningOperation() {
// Perform a long-running database operation
myRepository.doLongRunningTask();
}
}
3.1.2 Handle Timeout Exception
When the transaction exceeds the specified timeout, a TransactionTimedOutException will be thrown. You can handle this exception and take appropriate action, such as logging the timeout or rolling back the transaction:
package com.jcg.example;
import org.springframework.transaction.TransactionTimedOutException;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
@Transactional(timeout = 30) // Timeout set to 30 seconds
public void longRunningOperation() {
try {
// Perform a long-running database operation
myRepository.doLongRunningTask();
} catch (TransactionTimedOutException e) {
// Handle timeout exception
// Log the timeout
System.out.println("Database operation timed out.");
// Rollback the transaction or perform other actions as needed
}
}
}
3.2 Timeout a Remote API Call with RestTemplate or WebClient
When making remote API calls in a Java application, it’s important to handle timeouts to prevent blocking and resource contention. In this article, we’ll explore how to implement timeout functionality using both RestTemplate and WebClient, which are commonly used in Spring applications for consuming RESTful services.
3.2.1 Using RestTemplate
With RestTemplate, you can set connection and read timeouts using the ClientHttpRequestFactory. Here’s how to configure timeouts:
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
// Create RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
// Set connection and read timeouts
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(5000); // 5 seconds
factory.setReadTimeout(5000); // 5 seconds
restTemplate.setRequestFactory(factory);
// Make remote API call
String response = restTemplate.getForObject("https://example.com/api/resource", String.class);
3.2.2 Using WebClient
WebClient is a non-blocking, reactive HTTP client introduced in Spring WebFlux. To set timeouts with WebClient, you can use the timeout operator:
import org.springframework.web.reactive.function.client.WebClient;
import java.time.Duration;
// Create WebClient instance
WebClient webClient = WebClient.create();
// Make remote API call with timeout
String response = webClient.get()
.uri("https://example.com/api/resource")
.retrieve()
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(5)) // 5 seconds
.block();
3.3 Alternative Options
While Resilience4j is a popular choice for managing timeouts, there are several alternative options available, each with its strengths and use cases.

