Since I badly needed to be able to detected connect failures without
having to wait for a ConnectFuture I added support for it. See the
attached patch. Basically what I've done is to add an extra callback to
IoHandler:

void connectFailed( Throwable cause, Object mark ) throws Exception;

Then there is an extra connect-method in IoConnector:

ConnectFuture connect( SocketAddress address, SocketAddress localAddress,
                           IoHandler handler, Object mark ) throws
IOException;

When connect fails for any of the IoConnector implementations they will
notify the IoHandler specified in the call to connect() and pass along
the mark Object. That's it.

NOTE: I had to move the call to sessionCreated in
DatagramConnectorDelegate.regsiterNew() down a bit to make it less
likely that sessionCreated() is called even if connect fails.

Is this something that could be considered for inclusion in Mina?

/Niklas

Niklas Therning wrote:

>Forgot the [mina] prefix. Sorry.
>
>Hi,
>
>Is there any way I can detect if a connect operation fails without
>having to join or poll the ConnectFuture returned by connect()?
>
>/Niklas
>
>
>  
>

Index: src/java/org/apache/mina/common/IoHandler.java
===================================================================
--- src/java/org/apache/mina/common/IoHandler.java	(revision 332465)
+++ src/java/org/apache/mina/common/IoHandler.java	(working copy)
@@ -68,6 +68,17 @@
     void exceptionCaught( IoSession session, Throwable cause ) throws Exception;
 
     /**
+     * Invoked when a connect operation fails for some reason.
+     * 
+     * @param cause the Exception thrown by the connect operation if any.
+     * @param mark the same Object passed to the connect method.
+     * @see IoConnector#connect(SocketAddress, IoHandler)
+     * @see IoConnector#connect(SocketAddress, SocketAddress, IoHandler)
+     * @see IoConnector#connect(SocketAddress, SocketAddress, IoHandler, Object)
+     */
+    void connectFailed( Throwable cause, Object mark ) throws Exception;
+    
+    /**
      * Invoked when protocol message is received.  Implement your protocol flow
      * here.
      */
Index: src/java/org/apache/mina/common/IoHandlerAdapter.java
===================================================================
--- src/java/org/apache/mina/common/IoHandlerAdapter.java	(revision 332465)
+++ src/java/org/apache/mina/common/IoHandlerAdapter.java	(working copy)
@@ -51,6 +51,10 @@
     {
     }
 
+    public void connectFailed( Throwable cause, Object mark ) throws Exception
+    {
+    }
+
     public void messageReceived( IoSession session, Object message ) throws Exception
     {
     }
Index: src/java/org/apache/mina/common/IoConnector.java
===================================================================
--- src/java/org/apache/mina/common/IoConnector.java	(revision 332465)
+++ src/java/org/apache/mina/common/IoConnector.java	(working copy)
@@ -64,6 +64,17 @@
                            IoHandler handler ) throws IOException;
 
     /**
+     * Connects to the specified <code>address</code>.  If communication starts
+     * successfully, events are fired to the specified
+     * <code>handler</code>.
+     * 
+     * @param localAddress the local address the channel is bound to
+     * @throws IOException if failed to connect
+     */
+    ConnectFuture connect( SocketAddress address, SocketAddress localAddress,
+                           IoHandler handler, Object mark ) throws IOException;
+    
+    /**
      * Returns the connect timeout in seconds.
      */
     int getConnectTimeout();
Index: src/java/org/apache/mina/common/support/DelegatedIoConnector.java
===================================================================
--- src/java/org/apache/mina/common/support/DelegatedIoConnector.java	(revision 332465)
+++ src/java/org/apache/mina/common/support/DelegatedIoConnector.java	(working copy)
@@ -56,6 +56,12 @@
         return delegate.connect( address, localAddress, handler );
     }
 
+    public ConnectFuture connect( SocketAddress address, SocketAddress localAddress,
+                              IoHandler handler, Object mark ) throws IOException
+    {
+        return delegate.connect( address, localAddress, handler, mark );
+    }
+    
     public IoFilterChain getFilterChain()
     {
         return delegate.getFilterChain();
Index: src/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java
===================================================================
--- src/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java	(revision 332465)
+++ src/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java	(working copy)
@@ -51,11 +51,16 @@
 
     public ConnectFuture connect( SocketAddress address, IoHandler handler ) throws IOException 
     {
-        return connect( address, null, handler );
+        return connect( address, null, handler, null );
     }
 
     public ConnectFuture connect( SocketAddress address, SocketAddress localAddress, IoHandler handler ) throws IOException
     {
+        return connect( address, localAddress, handler, null );
+    }
+    
+    public ConnectFuture connect( SocketAddress address, SocketAddress localAddress, IoHandler handler, Object mark ) throws IOException
+    {
         if( address == null )
             throw new NullPointerException( "address" );
         if( handler == null )
Index: src/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java
===================================================================
--- src/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java	(revision 332465)
+++ src/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java	(working copy)
@@ -77,6 +77,12 @@
     public ConnectFuture connect( SocketAddress address, SocketAddress localAddress,
                               IoHandler handler ) throws IOException
     {
+        return connect( address, localAddress, handler, null );
+    }
+    
+    public ConnectFuture connect( SocketAddress address, SocketAddress localAddress,
+                              IoHandler handler, Object mark ) throws IOException
+    {
         if( address == null )
             throw new NullPointerException( "address" );
         if( handler == null )
@@ -113,7 +119,7 @@
             }
         }
 
-        RegistrationRequest request = new RegistrationRequest( ch, handler );
+        RegistrationRequest request = new RegistrationRequest( ch, handler, mark );
         synchronized( this )
         {
             synchronized( registerQueue )
@@ -177,7 +183,7 @@
             flushingSessions.push( session );
         }
     }
-
+    
     private class Worker extends Thread
     {
         public Worker()
@@ -416,18 +422,20 @@
             boolean success = false;
             try
             {
-                session.getManagerFilterChain().sessionCreated( session );
 
                 SelectionKey key = req.channel.register( selector,
                         SelectionKey.OP_READ, session );
     
                 session.setSelectionKey( key );
 
+                session.getManagerFilterChain().sessionCreated( session );
+                
                 req.setSession( session );
                 success = true;
             }
             catch( Throwable t )
             {
+                callConnectFailed( t, req );
                 req.setException( t );
             }
             finally 
@@ -447,6 +455,18 @@
         }
     }
 
+    private void callConnectFailed( Throwable cause, RegistrationRequest req )
+    {
+        try
+        {
+            req.handler.connectFailed( cause, req.mark );
+        }
+        catch ( Exception e )
+        {
+            exceptionMonitor.exceptionCaught( this, e );          
+        }
+    }    
+    
     private void cancelKeys()
     {
         if( cancelQueue.isEmpty() )
@@ -491,12 +511,15 @@
         private final DatagramChannel channel;
 
         private final IoHandler handler;
-
+        
+        private Object mark;
+        
         private RegistrationRequest( DatagramChannel channel,
-                                     IoHandler handler )
+                                     IoHandler handler, Object mark )
         {
             this.channel = channel;
             this.handler = handler;
+            this.mark = mark;
         }
     }
 }
Index: src/java/org/apache/mina/transport/socket/nio/support/SocketConnectorDelegate.java
===================================================================
--- src/java/org/apache/mina/transport/socket/nio/support/SocketConnectorDelegate.java	(revision 332465)
+++ src/java/org/apache/mina/transport/socket/nio/support/SocketConnectorDelegate.java	(working copy)
@@ -34,9 +34,6 @@
 import org.apache.mina.common.IoHandler;
 import org.apache.mina.common.support.BaseIoConnector;
 import org.apache.mina.common.support.IoSessionManagerFilterChain;
-import org.apache.mina.transport.socket.nio.support.SocketIoProcessor;
-import org.apache.mina.transport.socket.nio.support.SocketSessionImpl;
-import org.apache.mina.transport.socket.nio.support.SocketSessionManagerFilterChain;
 import org.apache.mina.util.ExceptionUtil;
 import org.apache.mina.util.Queue;
 
@@ -69,12 +66,18 @@
 
     public ConnectFuture connect( SocketAddress address, IoHandler handler ) throws IOException
     {
-        return connect( address, null, handler);
+        return connect( address, null, handler, null );
     }
 
     public ConnectFuture connect( SocketAddress address, SocketAddress localAddress,
                                   IoHandler handler ) throws IOException
     {
+        return connect( address, localAddress, handler, null );
+    }
+    
+    public ConnectFuture connect( SocketAddress address, SocketAddress localAddress,
+                                  IoHandler handler, Object mark ) throws IOException
+    {
         if( address == null )
             throw new NullPointerException( "address" );
         if( handler == null )
@@ -119,7 +122,7 @@
             }
         }
         
-        ConnectionRequest request = new ConnectionRequest( ch, getConnectTimeout(), handler );
+        ConnectionRequest request = new ConnectionRequest( ch, getConnectTimeout(), handler, mark );
         synchronized( this )
         {
             synchronized( connectQueue )
@@ -166,6 +169,7 @@
             }
             catch( IOException e )
             {
+                callConnectFailed( e, req );
                 req.setException( e );
             }
         }
@@ -195,6 +199,7 @@
             }
             catch( Throwable e )
             {
+                callConnectFailed( e, entry );
                 entry.setException( e );
             }
             finally
@@ -233,12 +238,14 @@
 
             if( currentTime >= entry.deadline )
             {
-                entry.setException( new ConnectException() );
+                ConnectException e = new ConnectException();
+                callConnectFailed( e, entry );
+                entry.setException( e );
                 key.cancel();
             }
         }
     }
-
+    
     private SocketSessionImpl newSession( SocketChannel ch, IoHandler handler ) throws IOException
     {
         SocketSessionImpl session = new SocketSessionImpl( filters, ch, handler );
@@ -254,6 +261,18 @@
         return session;
     }
 
+    private void callConnectFailed( Throwable cause, ConnectionRequest req )
+    {
+        try
+        {
+            req.handler.connectFailed( cause, req.mark );
+        }
+        catch ( Exception e )
+        {
+            exceptionMonitor.exceptionCaught( this, e );          
+        }
+    }
+    
     private class Worker extends Thread
     {
         public Worker()
@@ -326,12 +345,15 @@
         private final long deadline;
 
         private final IoHandler handler;
+        
+        private final Object mark;
 
-        private ConnectionRequest( SocketChannel channel, int timeout, IoHandler handler )
+        private ConnectionRequest( SocketChannel channel, int timeout, IoHandler handler, Object mark )
         {
             this.channel = channel;
             this.deadline = System.currentTimeMillis() + timeout * 1000L;
             this.handler = handler;
+            this.mark = mark;
         }
     }
 

Reply via email to