diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java index ea4cb1003d..0244592130 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java @@ -20,6 +20,8 @@ import java.net.Socket; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import org.springframework.context.ApplicationEventPublisher; + /** * Abstract class for client connection factories; client connection factories * establish outgoing connections. @@ -64,7 +66,7 @@ public abstract class AbstractClientConnectionFactory extends AbstractConnection @Override public TcpConnectionSupport getConnection() throws Exception { this.checkActive(); - return this.obtainConnection(); + return obtainConnection(); } protected TcpConnectionSupport obtainConnection() throws Exception { @@ -74,7 +76,7 @@ public abstract class AbstractClientConnectionFactory extends AbstractConnection return connection; } } - return this.obtainNewConnection(); + return obtainNewConnection(); } protected final TcpConnectionSupport obtainSharedConnection() throws InterruptedException { @@ -118,6 +120,13 @@ public abstract class AbstractClientConnectionFactory extends AbstractConnection connection.publishConnectionOpenEvent(); return connection; } + catch (Exception e) { + ApplicationEventPublisher applicationEventPublisher = getApplicationEventPublisher(); + if (applicationEventPublisher != null) { + applicationEventPublisher.publishEvent(new TcpConnectionFailedEvent(this, e)); + } + throw e; + } finally { if (!singleUse) { this.theConnectionLock.writeLock().unlock(); diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnectionFailedEvent.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnectionFailedEvent.java new file mode 100644 index 0000000000..e5e6710877 --- /dev/null +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnectionFailedEvent.java @@ -0,0 +1,39 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.ip.tcp.connection; + +import org.springframework.integration.ip.event.IpIntegrationEvent; + + + +/** + * An event emitted when a connection could not be established for some + * reason. + * + * @author Gary Russell + * @since 4.3.2 + * + */ +public class TcpConnectionFailedEvent extends IpIntegrationEvent { + + private static final long serialVersionUID = -7460880274740273542L; + + public TcpConnectionFailedEvent(Object source, Throwable cause) { + super(source, cause); + } + +} diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionEventTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionEventTests.java index df2e61e42a..78e012f633 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionEventTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/connection/ConnectionEventTests.java @@ -39,6 +39,7 @@ import java.io.OutputStream; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -325,4 +326,32 @@ public class ConnectionEventTests { ss.close(); } + @Test + public void testFailConnect() { + TcpNetClientConnectionFactory ccf = new TcpNetClientConnectionFactory("junkjunk", 1234); + final AtomicReference failEvent = new AtomicReference(); + ccf.setApplicationEventPublisher(new ApplicationEventPublisher() { + + @Override + public void publishEvent(Object event) { + } + + @Override + public void publishEvent(ApplicationEvent event) { + failEvent.set(event); + } + + }); + ccf.start(); + try { + ccf.getConnection(); + fail("expected exception"); + } + catch (Exception e) { + assertThat(e, instanceOf(UnknownHostException.class)); + TcpConnectionFailedEvent event = (TcpConnectionFailedEvent) failEvent.get(); + assertSame(e, event.getCause()); + } + } + } diff --git a/src/reference/asciidoc/ip.adoc b/src/reference/asciidoc/ip.adoc index 86e8548cb8..dc5330815a 100644 --- a/src/reference/asciidoc/ip.adoc +++ b/src/reference/asciidoc/ip.adoc @@ -464,6 +464,9 @@ connect to the socket. IMPORTANT: To avoid delaying the listening thread from accepting connections, the event is published on a separate thread. +Starting with _version 4.3.2_, a `TcpConnectionFailedEvent` is emitted whenever a client connection can't be created. +The source of the event is the connection factory which can be used to determine the host and port to which the connection could not be established. + [[tcp-adapters]] === TCP Adapters