3

I have a singleton connector object that helps in connecting to a mysql database.

 public class Connector{
        private Connector(){

            }
            public static Connector getInstance(){
                if(unique == null) unique = new Connector();
                return unique;
            }

            public void connect() throws SQLException{

                conn = (Connection) DriverManager.getConnection(CONN_STRING, USERNAME, PASSWORD);
                if(conn != null) System.out.println("Connected");
            }

            public void close() throws SQLException{
                if(conn != null) conn.close();

            }
    }

But naturally I'm bubbling up the exceptions for the caller to handle. This is my calling client.

Connector connector = Connector.getInstance();
        try {
            connector.connect();
        } catch (SQLException e) {
            System.out.println("Connected now");
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            connector.close();
            System.out.println("Connection closed");
        }

Now the connector doesn't compile as it wants me to wrap the finally within a try catch since the method close() also throws an exception. This would mean I'd have to write the code like.

finally {
            try {
                connector.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("Connection closed");
        }

This somehow doesn't look right. What's the right way to deal with this situation. Thanks in anticipation.

Zeus
  • 2,213
  • 8
  • 28
  • 45
  • 2
    there is no "right" way, it all depends on your needs and requirements – Stultuske Apr 08 '16 at 13:39
  • @Stultuske so is this code ok or is there a more elegant way of handling this exception. – Zeus Apr 08 '16 at 13:40
  • You actually find finally blocks like that in a lot of libraries, sometimes with a method wrapping the inner try-catch like Apache Commons IOUtils' `closeQuietly(...)`. – Thomas Apr 08 '16 at 13:42
  • 1
    If you can use Spring, I'd suggest you look at using the JdbcTemplate API. Failing that, you might also take a look at try with resources (https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html). Many developers are loathe to bubble up checked exceptions like SQLException, BTW...you might also convert to a RuntimeException as JdbcTemplate will do. – unigeek Apr 08 '16 at 13:42
  • It's ok in Java 6. In Java 7 you may use try with resources: http://www.mastertheboss.com/jboss-server/jboss-datasource/using-try-with-resources-to-close-database-connections – Akceptor Apr 08 '16 at 13:43
  • Btw, I'd say your `System.out.println("Connected now");` is in the wrong block :) – Thomas Apr 08 '16 at 13:43
  • @Thomas just a typo. Agreed and corrected. – Zeus Apr 08 '16 at 13:44
  • It's fine, I guess the question becomes is your program going to continue to run and try to reopen the connection, do you need to deal with the situation of the close() not working? Typically I'm closing connections on the way out, so I usually wrap them like try { connector.close(); } catch (SQLException e) {} – Mike Apr 08 '16 at 13:44

3 Answers3

3

Use the decorator pattern to handle this. You can change your Connector class to implement AutoCloseable (which just has one method: public void close()) and ensure that there is no exception thrown. Then you can use a try-with-resources when working with Connector.

Community
  • 1
  • 1
callyalater
  • 3,102
  • 8
  • 20
  • 27
  • This assumes java > 6 but otherwise the solution i would suggest myself. – trappski Apr 08 '16 at 13:55
  • @trappski That's true, but I find try-with-resources to be so much more elegant than the older way and help with resource management that I just couldn't help myself. – callyalater Apr 08 '16 at 14:01
2

You can hide the exception and change it with a boolean on the close method of the Connector class

public boolean close() {
  try
  {
       if(conn != null) conn.close();
       return true;
  }
  catch (Exception ex)
  {
     return false;
  }
}
Plebios
  • 835
  • 1
  • 7
  • 17
  • 1
    I'm not sure if I understood that. Could you provide a code snippet. – Zeus Apr 08 '16 at 13:42
  • Did you mean Can't or can? – Zeus Apr 08 '16 at 13:42
  • So you're suggesting I catch the exception in the close method itself instead of pushing it back up. Is that a good way to do it. – Zeus Apr 08 '16 at 13:47
  • It 's a way to do it to avoid the try catch block inside finally. – Plebios Apr 08 '16 at 13:48
  • You can also implement [`AutoCloseable`](https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html) to use a try with resources to avoid the try-catch in the `finally` statement. – callyalater Apr 08 '16 at 13:50
1

A lot of libraries can close Closeables quietly (guava, apache).

With guava you would do something like that:

Closeables.closeQuietly(something);

It calls close() within try-catch block but just looks better. It also checks whether your Closeable is null so you don't have to worry about that.

g-t
  • 1,455
  • 12
  • 17