In the org.springframework.boot.actuate.jms.JmsHealthIndicator

its inner class MonitoredConnection

void start() throws JMSException {
    new Thread(() -> {
                try {
                    if (!this.latch.await(5, TimeUnit.SECONDS)) {
                        JmsHealthIndicator.this.logger
                                .warn("Connection failed to start within 5 seconds and will be closed.");
                        -- closeConnection();
                    }
                }
                catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }finally{
                    ++ closeConnection();
                }
            }, "jms-health-indicator").start();
    this.connection.start();
    this.latch.countDown();

Comment From: philwebb

I'm not sure I understand the issue as described, could you please paste the suggested changes in this issue? I believe that the thread in MonitoredConnection should close if connection.start does not respond within 5 seconds.

Comment From: cuixiaoyiyi

Sorry, my redundant presentation is misleading.

current:

void start() throws JMSException {
    new Thread(() -> {
                try {
                    if (!this.latch.await(5, TimeUnit.SECONDS)) {
                        JmsHealthIndicator.this.logger
                                .warn("Connection failed to start within 5 seconds and will be closed.");
                        closeConnection();  // be moved into finally block?
                    }
                }
                catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
            }, "jms-health-indicator").start();
    this.connection.start();
    this.latch.countDown();

suggested changes:

void start() throws JMSException {
    new Thread(() -> {
                try {
                    if (!this.latch.await(5, TimeUnit.SECONDS)) {
                        JmsHealthIndicator.this.logger
                                .warn("Connection failed to start within 5 seconds and will be closed.");
                    }
                }
                catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }finally{
                       closeConnection();  // be moved into here?
                }

            }, "jms-health-indicator").start();
    this.connection.start();
    this.latch.countDown();

Comment From: bclozel

@cuixiaoyiyi I don't understand the suggested change either. This closeConnection call is meant to try to use close the connection in case it couldn't be started. The connection itself is always closed here in case things work properly.

Could you explain in which case the connection would not be closed properly with the current implementation?

Comment From: cuixiaoyiyi

The suggested changes before may be inappropriate. I mean that if the InterruptedException happens, then the connection will never be closed, and ​the connection resource leak will happen.

The "closeConnection()" should be added in the catch block.

Updated suggested changes:

void start() throws JMSException {
    new Thread(() -> {
                try {
                    if (!this.latch.await(5, TimeUnit.SECONDS)) {
                        JmsHealthIndicator.this.logger
                                .warn("Connection failed to start within 5 seconds and will be closed.");
                        closeConnection(); 
                    }
                }
                catch (InterruptedException ex) {
                    closeConnection();  // be added here?
                    Thread.currentThread().interrupt();
                }

            }, "jms-health-indicator").start();
    this.connection.start();
    this.latch.countDown();

Comment From: bclozel

We're using a try with resources block here - shouldn't that close the connection in all cases?

Comment From: cuixiaoyiyi

I do not think so. The try-with-resources statement works for local variables as a syntactic sugar with format try(local variable){}catch{}.

But it does not work with fields.
Why doesn't try-with-resources work with field variables?

Comment From: bclozel

But it does not work with fields.

This is a local variable, not a field.

try (Connection connection = this.connectionFactory.createConnection()) {
    new MonitoredConnection(connection).start();
    builder.up().withDetail("provider", connection.getMetaData().getJMSProviderName());
}

The link you've shared would apply here if the code looked like

Connection connection = null
try (connection = this.connectionFactory.createConnection()) {
    new MonitoredConnection(connection).start();
    builder.up().withDetail("provider", connection.getMetaData().getJMSProviderName());
}

Comment From: cuixiaoyiyi

The object connection here

try (connection = this.connectionFactory.createConnection()) {
}

will be closed in any case in current thread. If it is necessary to be closed in another thread, I think the closeConnection(); should also be invoked in the catch block for the InterruptedException. If you mean if the InterruptedException happens, then the closeConnection(); needs not to be invoked again, I agree.

Btw, is there a problem with closing the same connection asynchronously in different threads?

Comment From: bclozel

I'm closing this issue as we're entering a theoretical debate. Please reopen this issue if you manage to find cases where we're leaking connections, providing a sample application showing the problem.