VOOZH about

URL: https://www.javacodegeeks.com/configuring-jersey-connection-and-read-timeouts.html

⇱ Configuring Jersey Connection and Read Timeouts - Java Code Geeks


This article will guide you through setting connection timeout and read timeout in Jersey using ClientConfig. When developing RESTful applications using Jersey, it is crucial to manage timeouts effectively. Timeouts help prevent requests from hanging indefinitely when the server is slow to respond or unreachable.

1. Understanding Connection Timeout and Read Timeout

Properly setting these timeouts (connection and read) ensures our application does not wait indefinitely for responses, improving resilience and performance.

1.1 Connection Timeout

The connection timeout defines the maximum duration, in milliseconds, that the client will wait while attempting to establish a connection with the server. If the connection is not successfully established within this specified time limit, the request is aborted, and a timeout exception is thrown. Properly configuring this timeout helps prevent indefinite waiting periods and ensures that the application can handle network delays or unresponsive servers more effectively.

1.2 Read Timeout

The read timeout specifies the maximum duration, in milliseconds, that the client will wait for a response after sending a request to the server. If the server fails to respond within the defined time limit, the request is terminated, and a timeout exception is triggered. Configuring an appropriate read timeout helps prevent prolonged waiting periods, improves application responsiveness, and ensures efficient handling of slow or unresponsive servers

2. Dependencies Required

Before implementing the solution, it is essential to include the necessary dependencies in the pom.xml file:

<dependencies>
 <!-- Jersey Core Client -->
 <dependency>
 <groupId>org.glassfish.jersey.core</groupId>
 <artifactId>jersey-client</artifactId>
 <version>3.1.9</version>
 </dependency>

 <!-- Jersey Injection for Dependency Management -->
 <dependency>
 <groupId>org.glassfish.jersey.inject</groupId>
 <artifactId>jersey-hk2</artifactId>
 <version>3.1.9</version>
 </dependency>
</dependencies>

For Gradle users, add:

dependencies {
 implementation 'org.glassfish.jersey.core:jersey-client:3.1.9'
 implementation 'org.glassfish.jersey.inject:jersey-hk2:3.1.9'
}

3. Configuring Connection Timeout and Read Timeout

To set timeouts in Jersey, we configure ClientConfig using ClientProperties. Below is a complete example demonstrating how to configure connection timeout and read timeout in Jersey.

public class JerseyTimeoutExample {
 
 private static final Logger logger = Logger.getLogger(JerseyTimeoutExample.class.getName());
 
 public static void main(String[] args) {
 
 // Create a ClientConfig instance
 ClientConfig clientConfig = new ClientConfig();
 clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 5000);
 clientConfig.property(ClientProperties.READ_TIMEOUT, 10000);

 // Create a client using the configured settings
 Client client = ClientBuilder.newClient(clientConfig);

 // Define the target URL
 WebTarget target = client.target("https://jsonplaceholder.typicode.com/posts/1");
 try (Response response = target.request().get()) {

 logger.log(Level.INFO, "Response Code: {0}", response.getStatus());
 logger.log(Level.INFO, "Response Body: {0}", response.readEntity(String.class));
 } catch (Exception e) {
 logger.log(Level.WARNING, "Request failed: {0}", e.getMessage());
 
 } finally {
 client.close();
 }
 }
}

3.1 Code Walkthrough and Analysis

Step 1: Configuring Client Timeout Settings

A ClientConfig object is created to apply custom configurations for managing timeouts. The ClientProperties.CONNECT_TIMEOUT is set to 5000 milliseconds (5 seconds), ensuring that the client does not wait indefinitely while attempting to establish a connection. Additionally, the ClientProperties.READ_TIMEOUT is set to 10000 milliseconds (10 seconds), defining the maximum duration the client will wait for a response from the server before triggering a timeout exception. These configurations help improve network efficiency and prevent long delays in request handling.

Step 2: Creating a Jersey Client

A Jersey Client instance is created using ClientBuilder.newClient(clientConfig), which applies the timeout settings.

Step 3: Defining the Target URL

The WebTarget object points to the API URL (https://jsonplaceholder.typicode.com/posts/1).

Step 4: Sending the Request and Handling the Response

A GET request is executed using target.request().get(), and if the request is successful, the response status and body are printed. In case of a timeout or failure, an error message is displayed to notify the user. To ensure proper resource management, both the response and client are closed within the finally block, preventing potential memory leaks and ensuring efficient cleanup.

3.2 Expected Output

If the request completes within the specified time, you will see:

Jan 29, 2025 4:32:09 P.M. com.jcg.examples.JerseyTimeoutExample main
INFO: Response Code: 200
Jan 29, 2025 4:32:09 P.M. com.jcg.examples.JerseyTimeoutExample main
INFO: Response Body: {
 "userId": 1,
 "id": 1,
 "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
 "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}

4. Using the client.property() Method

The client.property() method allows setting timeouts dynamically on a Jersey client instance. This approach provides flexibility by applying timeout configurations at runtime rather than during object creation.

public class JerseyClientPropertyExample {

 private static final Logger logger = Logger.getLogger(JerseyClientPropertyExample.class.getName());

 public static void main(String[] args) {
 // Create a Jersey client
 Client client = ClientBuilder.newClient();

 // Set connection and read timeouts using client.property()
 client.property(ClientProperties.CONNECT_TIMEOUT, 5000); // 5 seconds
 client.property(ClientProperties.READ_TIMEOUT, 10000); // 10 seconds

 WebTarget target = client.target("https://jsonplaceholder.typicode.com/posts/5");

 Response response = null;
 try {
 response = target.request().get();
 logger.log(Level.INFO, "Response Code: {0}", response.getStatus());
 logger.log(Level.INFO, "Response Body: {0}", response.readEntity(String.class));
 } catch (Exception e) {
 logger.log(Level.WARNING, "Request failed: {0}", e.getMessage());
 } finally {
 if (response != null) {
 response.close();
 }
 client.close();
 }
 }
}

In this example, a Jersey client is created using ClientBuilder.newClient(). The client.property() method is then used to set connection and read timeouts dynamically. The connection timeout is set to 5000 milliseconds (5 seconds) and the read timeout is set to 10000 milliseconds (10 seconds). The client then sends a GET request to a valid API endpoint, and if successful, the response status and body are printed.

5. Using the ClientBuilder API

Instead of setting properties dynamically, timeouts can be configured during client creation using the ClientBuilder API. This method is preferred for defining timeout settings at the time of client instantiation.

public class JerseyClientBuilderMain {
 
private static final int TIMEOUT = 5000; // 5 seconds
private static final Logger logger = Logger.getLogger(JerseyClientBuilderMain.class.getName());

 public static void main(String[] args) {
 JerseyClientBuilderMain clientExample = new JerseyClientBuilderMain();
 String response = clientExample.viaClientBuilder();
 logger.log(Level.INFO, "Response: {0}", response);
 }

 public String viaClientBuilder() {
 // Create a ClientBuilder instance and configure timeouts
 ClientBuilder builder = ClientBuilder.newBuilder()
 .connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
 .readTimeout(TIMEOUT, TimeUnit.MILLISECONDS);

 // Build the client and execute the request
 return get(builder.build());
 }

 private String get(Client client) {
 WebTarget target = client.target("https://jsonplaceholder.typicode.com/posts/6");
 Response response = null;
 try {
 response = target.request().get();
 return response.readEntity(String.class);
 } catch (Exception e) {
 return "Request failed: " + e.getMessage();
 } finally {
 if (response != null) {
 response.close();
 }
 client.close();
 }
 }
}

This implementation defines a main class called JerseyClientBuilderMain, where a Jersey client is created using ClientBuilder.newBuilder(). Timeouts are set using connectTimeout() and readTimeout(), both configured to 5000 milliseconds (5 seconds). The viaClientBuilder() method initializes the client with these timeout settings and then calls the get() method to send an HTTP request.

6. Implementing a Retry Mechanism

Timeouts and temporary network failures are common, so implementing a retry mechanism improves reliability. The example below retries failed requests up to 3 times before giving up.

public class JerseyRetryExample {

 private static final Logger logger = Logger.getLogger(JerseyRetryExample.class.getName());
 private static final int MAX_RETRIES = 3; // Maximum retry attempts
 private static final int CONNECT_TIMEOUT = 5000; // 5 seconds
 private static final int READ_TIMEOUT = 10000; // 10 seconds

 public static void main(String[] args) {

 ClientConfig clientConfig = new ClientConfig();
 clientConfig.property(ClientProperties.CONNECT_TIMEOUT, CONNECT_TIMEOUT);
 clientConfig.property(ClientProperties.READ_TIMEOUT, READ_TIMEOUT);

 Client client = ClientBuilder.newClient(clientConfig);
 WebTarget target = client.target("https://jsonplaceholder.typicode.com/posts/1");

 Response response = null;
 int attempt = 0;

 while (attempt < MAX_RETRIES) {
 try {
 attempt++;
 logger.log(Level.INFO, "Attempt {0}", attempt + " to send request...");

 response = target.request().get();

 // If request is successful, print response and break retry loop
 if (response.getStatus() == 200) {
 logger.log(Level.INFO, "Response Code: {0}", response.getStatus());
 logger.log(Level.INFO, "Response Body: {0}", response.readEntity(String.class));
 break;
 } else {
 logger.log(Level.WARNING, "Request failed with status: {0}", response.getStatus());
 }
 } catch (Exception e) {
 logger.log(Level.WARNING, "Attempt {0}", attempt + " " + e.getMessage());
 }

 // Small delay before retrying
 try {
 Thread.sleep(2000); // Wait 2 seconds before retrying
 } catch (InterruptedException e) {
 Thread.currentThread().interrupt();
 }
 }

 // Close resources
 if (response != null) {
 response.close();
 }
 client.close();
 }
}

The retry logic is implemented using a while loop, allowing the request to be attempted up to MAX_RETRIES times. If a request fails, an error message is printed, and the system waits for a short delay before retrying. When a successful response (HTTP 200) is received, the loop terminates, preventing unnecessary retries. In case of failures, such as timeouts or server errors, exceptions are caught, and another attempt is initiated. To prevent overwhelming the server, a Thread.sleep(2000); introduces a 2-second delay between retries, ensuring a controlled retry mechanism.

Expected Output

If the request succeeds on the first attempt:

INFO: Attempt 1 to send request...
Jan 29, 2025 9:04:04 P.M. 
Jan 29, 2025 9:04:08 P.M. com.jcg.examples.JerseyRetryExample main
INFO: Response Code: 200
Jan 29, 2025 9:04:08 P.M. com.jcg.examples.JerseyRetryExample main
INFO: Response Body: {
 "userId": 1,
 "id": 1,
 "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
 "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}

To test the retry mechanism using an unreachable API endpoint, we can use a valid domain with a non-existent path, such as https://jsonplaceholder.typicode.com/nonexistent. This endpoint will return an HTTP 404 (Not Found) error, simulating a failed request that triggers the retry logic.

Since the /nonexistent path does not exist, the server will respond with HTTP 404 (Not Found). The client will retry the request three times before stopping:

7. Conclusion

This article explored multiple ways to configure Jersey connection and read timeouts to prevent excessive waiting periods when interacting with external APIs. We demonstrated how to set timeouts dynamically using the client.property() method and configure them during client creation using the ClientBuilder API. We also implemented a retry mechanism to automatically reattempt failed requests, ensuring improved reliability in network communication.

By configuring connection and read timeouts in Jersey, we can prevent long waits and improve application responsiveness. This ensures that our client handles network latency efficiently, leading to better performance and user experience.

8. Download the Source Code

This article covered configuring connection and read timeouts in Jersey.

Download
You can download the full source code of this example here: jersey connection read timeouts
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Thank you!

We will contact you soon.

👁 Photo of Omozegie Aziegbe
Omozegie Aziegbe
February 6th, 2025Last Updated: February 5th, 2025
0 1,302 6 minutes read

Omozegie Aziegbe

Omos Aziegbe is a technical writer and web/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.
Subscribe

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button
Close
wpDiscuz