try-catch-finally block in java

1.1k views Asked by At

As per my understanding, I want to follow the best practice for releasing the resources at the end to prevent any connection leaks. Here is my code in HelperClass.

public static DynamoDB getDynamoDBConnection()
{   
    try
    {
        dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
    }
    catch(AmazonServiceException ase)
    {
        //ase.printStackTrace();
        slf4jLogger.error(ase.getMessage());
        slf4jLogger.error(ase.getStackTrace());
        slf4jLogger.error(ase);
    }
    catch (Exception e)
    {
        slf4jLogger.error(e);
        slf4jLogger.error(e.getStackTrace());
        slf4jLogger.error(e.getMessage());
    }
    finally
    {
        dynamoDB.shutdown();
    }
    return dynamoDB;
}

My doubt is, since the finally block will be executed no matter what, will the dynamoDB returns empty connection because it will be closed in finally block and then execute the return statement? TIA.

4

There are 4 answers

1
aioobe On BEST ANSWER

Your understanding is correct. dynamoBD.shutdown() will always execute before return dynamoDB.

I'm not familiar with the framework you're working with, but I would probably organize the code as follows:

public static DynamoDB getDynamoDBConnection()
        throws ApplicationSpecificException {   
    try {
        return new DynamoDB(new AmazonDynamoDBClient(
                                    new ProfileCredentialsProvider()));
    } catch(AmazonServiceException ase) {
        slf4jLogger.error(ase.getMessage());
        slf4jLogger.error(ase.getStackTrace());
        slf4jLogger.error(ase);
        throw new ApplicationSpecificException("some good message", ase);
    }
}

and use it as

DynamoDB con = null;
try {
    con = getDynamoDBConnection();
    // Do whatever you need to do with con
} catch (ApplicationSpecificException e) {
    // deal with it gracefully
} finally {
    if (con != null)
        con.shutdown();
}

You could also create an AutoCloseable wrapper for your dynamoDB connection (that calls shutdown inside close) and do

try (DynamoDB con = getDynamoDBConnection()) {
    // Do whatever you need to do with con
} catch (ApplicationSpecificException e) {
    // deal with it gracefully
}
0
Rohit Kulshreshtha On

Although I am not answering your question about the finally block being executed always (there are several answers to that question already), I would like to share some information about how DynamoDB clients are expected to be used.

The DynamoDB client is a thread-safe object and is intended to be shared between multiple threads - you can create a global one for your application and re-use the object where ever you need it. Generally, the client creation is managed by some sort of IoC container (Spring IoC container for example) and then provided by the container to whatever code needs it through dependency injection.

Underneath the hood, the DynamoDB client maintains a pool of HTTP connections for communicating the DynamoDB endpoint and uses connections from within this pool. The various parameters of the pool can be configured by passing an instance of the ClientConfiguration object when constructing the client. For example, one of the parameters is the maximum number of open HTTP connections allowed.

With the above understanding, I would say that since the DynamoDB client manages the lifecycle of HTTP connections, resource leaks shouldn't really be concern of code that uses the DynamoDB client.

0
Rishi Prakash On

Yes,dynamoDB will return an empty connection as dynamoBD.shutdow() will be executed before return statement, Always.

0
Alp On

How about we "imitate" the error and see what happens ? This is what I mean:

___Case 1___

try{
  // dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
  throw new AmazonServiceException("Whatever parameters required to instantiate this exception");
}    catch(AmazonServiceException ase)
    {
        //ase.printStackTrace();
        slf4jLogger.error(ase.getMessage());
        slf4jLogger.error(ase.getStackTrace());
        slf4jLogger.error(ase);

    }
    catch (Exception e)
    {
        slf4jLogger.error(e);
        slf4jLogger.error(e.getStackTrace());
        slf4jLogger.error(e.getMessage());
    }
    finally
    {
        //dynamoDB.shutdown();
        slf4jLogger.info("Database gracefully shutdowned");
    }

___Case 2___

try{
  // dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
  throw new Exception("Whatever parameters required to instantiate this exception");
}    catch(AmazonServiceException ase)
    {
        //ase.printStackTrace();
        slf4jLogger.error(ase.getMessage());
        slf4jLogger.error(ase.getStackTrace());
        slf4jLogger.error(ase);

    }
    catch (Exception e)
    {
        slf4jLogger.error(e);
        slf4jLogger.error(e.getStackTrace());
        slf4jLogger.error(e.getMessage());
    }
    finally
    {
        //dynamoDB.shutdown();
        slf4jLogger.info("Database gracefully shutdowned");
    }

These exercise could be a perfect place to use unit tests and more specifically mock tests. I suggest you to take a close look at JMockit, which will help you write such tests much more easily.