2
votes

I would like to handle TCP connection factory exceptions.

With an abstract connection factory:

@Bean
public AbstractClientConnectionFactory clientFactory() {
    TcpNetClientConnectionFactory factory = new TcpNetClientConnectionFactory(host, Integer.parseInt(port));
    factory.setSoKeepAlive(Boolean.parseBoolean(keepAlive));
    factory.setSoTimeout(timeout);
    factory.setSoReceiveBufferSize(Integer.parseInt(bufferSize)); 
    factory.setSoSendBufferSize(Integer.parseInt(bufferSize));   
    return factory;
}

This connection is injected in both TcpSendingMessageHandler and TcpReceivingChannelAdapter separated beans.

@Bean
public TcpReceivingChannelAdapter tcpIn() {
...
receiver.setConnectionFactory(clientFactory());
...
}

@Bean
@ServiceActivator(...)
public TcpSendingMessageHandler tcpOut() {
...
sender.setConnectionFactory(clientFactory());
...
}

I have some ApplicatioListeners such as: TcpConnectionExceptionEvent, TcpConnectionCloseEvent and TcpConnectionOpenEvent.

@EventListener
public void handleTcpConnectionCloseEvent(TcpConnectionExceptionEvent event){
...
}

However, I detected when an opened connection was closed, a TcpConnectionExceptionEvent was launched but not when the connection was not even opened. How it is possible to deal with “connection refused” problems or any other TCP errors?

Is it possible to start/stop the connection using the control bus? I am sending:

Message operation = MessageBuilder.withPayload("@clientFactory.isRunning()").build();
boolean sent = operationChannel.send(operation);

This seems to be not working because no response was received and only creates “continuous” calls looking for the reference swamping the application. clientFactory beans exists (checked with context.getBeanDefinitionNames())

Additionally, could I set a max retries for trying to reconnect?

Edit (Retry Advice): I added the tcpRetryAdvice to my tcp outbound channel but I am still confused because the clientFactory() (when “connection refused”) does not follow the defined policy in the retryAdvice. How can I control the current attemps and if finally the message was delivered?

@Bean
@ServiceActivator(inputChannel = "tcpSender", adviceChain = "tcpRetryAdvice")
public TcpSendingMessageHandler tcpOut(AbstractClientConnectionFactory connectionFactory) { ... }

@Bean
public RequestHandlerRetryAdvice tcpRetryAdvice() {

SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
    retryPolicy.setMaxAttempts(2);

ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
    backOffPolicy.setInitialInterval(3000);
    backOffPolicy.setMaxInterval(10000);
    backOffPolicy.setMultiplier(2);

RetryTemplate retryTemplate = new RetryTemplate();      
    retryTemplate.setRetryPolicy(retryPolicy);
    retryTemplate.setBackOffPolicy(backOffPolicy);

RequestHandlerRetryAdvice tcpRetryAdvice = new RequestHandlerRetryAdvice();
    tcpRetryAdvice.setRetryTemplate(retryTemplate);

    // This allows fail-controlling
    tcpRetryAdvice.setRecoveryCallback(new ErrorMessageSendingRecoverer(failMessageChannel()));

    return tcpRetryAdvice;
}

Edit (ControlBus):

I am just trying to stop sending messages to TCP because I have to know when the TCP (connectionFactory) is connected in order to do not drop away JMS consumed messages.

Edit (Logging error for beans)

First of all, I have:

tcpRetryAdvice.setRecoveryCallback(new ErrorMessageSendingRecoverer(failMessageChannel()));

This is OK to trace the exception but how I could get the message not sent?

Then I have error sent to the errorChannel but I am still seeing the whole stacktrace when the clientFactory() bean raises a "connecton refused" exception. I would like to avoid this:

[ERROR][TcpSendingMessageHandler] - [TcpSendingMessageHandler.java:80] - 26/08/2016
                20:40:57.424 - Error creating connection
java.net.ConnectException: Connection refused: connect
    at java.net.TwoStacksPlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at java.net.Socket.connect(Socket.java:538)
    at java.net.Socket.<init>(Socket.java:434)
    at java.net.Socket.<init>(Socket.java:211)
    ....

I just want:

In my error channel: Message not delivered <Failed to obtain a connection; nested exception is java.net.ConnectException: Connection refused: connect>

I am sending the callback to a failChannel() and I do not want to see the stacktrace. Ideally, I want to manage the callback. Get the message not sent to save it for waiting the socket reconnection and log the error with an errorChannel.

1

1 Answers

1
votes

A new TcpConnectionFailedEvent was recently added.

4.3.2 should be released in the next week or so; you can try it out first using the 4.3.2.BUILD-SNAPSHOT version.

You can add a retry advice to the outbound adapter.

I am not sure what you're saying about the control bus.