jrahme
jrahme

Reputation: 263

Loop On Exception

I have a custom built API for interacting with their messaging system. But this API doesn't give me any way to confirm that I have established a connection aside from when it is unable to connect an exception will be thrown.

When I receive a exception while connected, I have an exception listener that attempts to reconnect to the server. I'd like this to loop on exception to retry the connection. Doing an infinite loop until I am able to connect, or until the program is closed. I attempted to do this with break labels like so:

reconnect: try{
    attemptReconnection();
}catch(Exception e){
    log.error(e);
    break reconnect;
}

but that was unable to find the reconnect label for me, and is a bit to close to using a GOTO statement than I would be comfortable putting into production.

Upvotes: 1

Views: 357

Answers (4)

idipous
idipous

Reputation: 2910

I would suggest controlling the reconnection attempts not with a while loop but with a scheduled event. This you can easily initiate multiple connections and implement a back off mechanism not to over-consume resources while trying to reconnect

private ScheduledExecutorService scheduler;
...

public void connect() {

    for (int i = 0; i < numberOfConnections; i++) {
        final Runnable r = new Runnable() {
            int j = 1;

            public void run() {
                try {
                    final Connection connection = createNewConnection();

                } catch (IOException e) {
                    //here we do a back off mechanism every 1,2,4,8,16... 512 seconds
                    final long sleep = j * 1000L;
                    if (j < 512) {
                        j *= 2;
                    } else {
                        j = 1;
                    }
                    LOGGER.error("Failed connect to host:port: {}:{}. Retrying... in {} millis",
                            host, port, sleep);
                    LOGGER.debug("{}", e);
                    scheduler.schedule(this, sleep, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                    Thread.currentThread.interrupt();
                }
            }
        };
        scheduler.schedule(r, 1, TimeUnit.SECONDS);
    }
}

Do not forget to do a scheduler.shutdownNow() if you want to close the application so as to avoid the treadpool being leaking.

You can even implement a reconnect mechanism once you have been connected and you are disconnected by having the listener execute the connect method in case of a status change on the connection.

Upvotes: 1

Mohammed Aouf Zouag
Mohammed Aouf Zouag

Reputation: 17132

Proceed this way:

do { // optional loop choice
    try{
        attemptReconnection();
        break; // Connection was successful, break out of the loop
    } catch(Exception e){
        // Exception thrown, do nothing and move on to the next connection attempt (iteration)
        log.error(e);
    }
}while(true);

If the execution flow reaches the break; instruction then that means that you successfully connected. Otherwise, it will keep moving on to the next iteration. (Note that the loop choice is optional, you can use pretty much any loop you want)

Upvotes: 2

Arnaud
Arnaud

Reputation: 17534

Have attemptReconnection return true when connection succeds, false otherwise.

The method attemptReconnection should also catch and log the Exception.

Then :

while(!attemptReconnection()){

 log.error("Connection failure");

}

Upvotes: 1

Calvin P.
Calvin P.

Reputation: 1232

Can't say I have experience with APIs, but I would think something like this would achieve the result you're after.

boolean success = false;
while (!success){
    try{
        attemptReconnection();
        success = true;
    }
    catch(Exception e){
        log.error(e);
    }
}

Once attemptReconnection() executes without errors, success would be set to true and terminate the loop.

Upvotes: 1

Related Questions