DEV Community

loading...

Timeouts and how to handline in Java

sanjaybsm profile image sanjay shivanna ・2 min read

In this article we will try to cover why it’s important to define timeouts for out bound rest calls.

Before configuring any timeout let’s understand below some common exceptions for http outbound calls,

Connection timeout

maximum time to wait for the other side to answer "yes, I'm here, let's talk" when creating a new connection, (ConnectTimeout eventually calls socket.connect(address, timeout), If the connection is not established within the ConnectTimeout specified by you or the library you are using then, you get an error 'connect timedout

Socket timeout

Is the timeout for waiting for data or, put differently, a maximum period inactivity between two consecutive data packets

Read timeout

Read timeout can happen when there is successful connection established between client and the server and there is an inactivity between data packets while waiting for the server response.

Write timeout

Similar to Read timeout, write timeout can happen when there is successful connection established between client and server, and there is inactivity between data packets while sending the request to the server.

The important topic to remember here is that based on the choice of library we use for outbound calls it’s very important that we configure the properties to handle the above mentioned one’s and handle the exception gracefully.

Apache Camel

If we are using Apache Camel ‘http’ component to make the outbound calls then we can configure these properties in following ways, please note that if we don’t define this properties the default values is -1! means connection will never timeout and can have advert effect on the application performance overall.

camel.property

 http.urlProxy = http4://ThirdPartyServers?throwExceptionOnFailure=false&httpClient.socketTimeout=${rest.timeout.millis}&httpClient.connectTimeout=${rest.timeout.millis}
Enter fullscreen mode Exit fullscreen mode

Route Builder Class

    @Override
    public void configure() throws Exception {

        configureTimeout();

    }

    private void configureTimeout() {
        HttpComponent httpComponent = getContext().getComponent("http4", HttpComponent.class);
        httpComponent.setConnectionTimeToLive(VALUE_IN_MILI);// for closing the idle connection - in milliseconds
        httpComponent.setSocketTimeout(VALUE_IN_MILI); //socket timeout - in milliseconds
        httpComponent.setConnectTimeout(VALUE_IN_MILI); // connection timeout - in milliseconds*/
    } 
Enter fullscreen mode Exit fullscreen mode

Rest Template

In a similar manner for rest template we could define as follows,

final RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(VALUE_IN_MILI)
                .setConnectTimeout(VALUE_IN_MILI)
                .setSocketTimeout(VALUE_IN_MILIs)
                .build();

        final HttpClient httpClient = HttpClients.custom()
                 .setConnectionTimeToLive(VALUE_IN_MILI, SECONDS)
                .setRetryHandler((IOException exception, int executionCount, HttpContext context) -> {
                    return executionCount <= 3;
                })
                .setServiceUnavailableRetryStrategy(new DefaultServiceUnavailableRetryStrategy(3, 1))
                .setDefaultRequestConfig(requestConfig)
                .build();

        final RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
Enter fullscreen mode Exit fullscreen mode

WebClient

And in a similar manner below is how we could define it in web client,

    public WebClient getWebClient()
    {
        HttpClient httpClient = HttpClient.create()
                .tcpConfiguration(client ->
                        client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, VALUE_IN_MILI)
                        .doOnConnected(conn -> conn
                                .addHandlerLast(new ReadTimeoutHandler(rest.timeout.millis))
                                .addHandlerLast(new WriteTimeoutHandler(rest.timeout.millis))));

        ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient.wiretap(true));       

        return WebClient.builder()
                .baseUrl("http://localhost:3000")
                .clientConnector(connector)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .build();
          }
Enter fullscreen mode Exit fullscreen mode

Summary

All in all it’s very important to configure these values i.e. connection timeout, read timeout, socket timeout etc so as to terminate the connections after waiting for a specific amount of time rather keeping the connection open indefinitely which can bring issues to overall application performance and stability.

References

HTTP4 :: Apache Camel

A Guide to the RestTemplate | Baeldung

Discussion (0)

pic
Editor guide