javaspring-integrationspring-integration-http

How to log timeout error in HttpRequestExecutingMessageHandler


I want to be able to log the timeout error exception when using the HttpRequestExecutingMessageHandler. I have done the following:

    @Bean
    public HttpRequestExecutingMessageHandler httpRequestExecutingMessageHandler(ApplicationProperties properties){
        HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler(properties.getWebserviceAppendUrl());
        handler.setExpectedResponseType(String.class);
        handler.setHttpMethod(HttpMethod.POST);
        return handler;
    }

    @Bean
    public IntegrationFlow sendRequestFlow(HttpRequestExecutingMessageHandler httpRequestExecutingMessageHandler,
                                           RequestHandlerRetryAdvice requestHandlerRetryAdvice){
        return IntegrationFlows.from(requestChannel())
                .enrichHeaders(h-> h.header(HttpHeaders.CONTENT_TYPE, "application/json"))
                .handle(httpRequestExecutingMessageHandler, e->e.advice(requestHandlerRetryAdvice))
                .log(LoggingHandler.Level.INFO, "x.xxx.client.config.DevConfig", m-> "Webservice response status code: " + m.getHeaders().get("http_statusCode"))
                .get();
    }

    @Bean
    public RequestHandlerRetryAdvice requestHandlerRetryAdvice(RetryTemplate retryTemplate){
        RequestHandlerRetryAdvice advice = new RequestHandlerRetryAdvice();
        advice.setRetryTemplate(retryTemplate);
        ErrorMessageSendingRecoverer errorMessageSendingRecoverer = new ErrorMessageSendingRecoverer();
        errorMessageSendingRecoverer.setChannel(recoveryChannel());
        advice.setRecoveryCallback(errorMessageSendingRecoverer);
        return advice;
    }

    @Bean
    public RetryTemplate retryTemplate(){
        RetryTemplate retryTemplate = new RetryTemplate();
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        retryPolicy.setMaxAttempts(3);
        retryTemplate.setRetryPolicy(retryPolicy);
        FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
        fixedBackOffPolicy.setBackOffPeriod(60_000L);
        retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
        return retryTemplate;
    }

Currently my log is as follow when there are timeout exception:

DEBUG 2024-01-05 16:19:17,191 [scheduling-1] o.s.r.s.RetryTemplate - Retry: count=0 
DEBUG 2024-01-05 16:20:19,323 [scheduling-1] o.s.r.s.RetryTemplate - Checking for rethrow: count=1 
DEBUG 2024-01-05 16:20:19,323 [scheduling-1] o.s.r.s.RetryTemplate - Retry: count=1 
DEBUG 2024-01-05 16:21:21,340 [scheduling-1] o.s.r.s.RetryTemplate - Checking for rethrow: count=2 
DEBUG 2024-01-05 16:21:21,340 [scheduling-1] o.s.r.s.RetryTemplate - Retry: count=2 
DEBUG 2024-01-05 16:21:23,357 [scheduling-1] o.s.r.s.RetryTemplate - Checking for rethrow: count=3 
DEBUG 2024-01-05 16:21:23,358 [scheduling-1] o.s.r.s.RetryTemplate - Retry failed last attempt: count=3 
WARN 2024-01-05 16:21:23,359 [scheduling-1] o.s.i.h.LoggingHandler - Retrying failed, fallback to recovery flow

But what I want is before the retry logs, I want it to display the timeout error e.g:

ERROR 2024-01-03 13:16:14,220 [scheduling-1] i.b.i.f.c.c.MainConfig - Exception while hitting webservice: I/O error on POST request for "http://somehost/api/v1": Connection timed out: connect; nested exception is java.net.ConnectException: Connection timed out: connect org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://somehost/api/v1": Connection timed out: connect; nested exception is java.net.ConnectException: Connection timed out: connect
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:791)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:676)
Caused by: java.net.ConnectException: Connection timed out: connect
    at java.net.DualStackPlainSocketImpl.connect0(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)

I have succesfully add the timeout error with my own message handler but I want to use the HttpRequestExecutingMessageHandler. How to do it using the built in adapter? Any advice is appreciated. Thanks


Solution

  • If you'd like just to log that error, then you can look into RetryListener.onError():

    /**
     * Called after every unsuccessful attempt at a retry.
     * @param context the current {@link RetryContext}.
     * @param callback the current {@link RetryCallback}.
     * @param throwable the last exception that was thrown by the callback.
     * @param <T> the return value
     * @param <E> the exception to throw
     */
    default <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,
            Throwable throwable) {
    

    Inject that custom listener into your RetryTemplate and implement the logic to determine if that is java.net.ConnectException or not.

    This onError() is called before canRetry().