1

I'm plannning a class which dynamically opens a connection to a database to store some settings. The class should automatically close the connection if not used for a specific time or if the calling method ends.

Here is my solution so far, only showing the relevant parts:

public class DBSettings {
    // ...
    private int ConnectionTimeout = 5000; 
    private ExecutorService Executor;
    private long LastTimeUsed;  
    // ...

    public DBSettings(DBConnection Conn) {
        Connection = new DBConnection(); // class handles Connection to Database
        // ...
    }

    private void connect() {
        try {
            if (!Connection.isOpen()) {
                Connection.openConnection(DBUrl, DBUserName, DBPassword);
                LastTimeUsed = System.currentTimeMillis();
                Executor = Executors.newSingleThreadExecutor();

                Runnable closeRunnable = new Runnable() {
                    @Override
                    public void run() { 
                        while (System.currentTimeMillis() < (LastTimeUsed + ConnectionTimeout)) {
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) { }
                        }
                        disconnect(); 
                    }
                };

                Executor.submit(closeRunnable);
            }
        } catch (Exception e) { // ... }
    }

    private void disconnect() {
        if (Connection!=null) {
            if (Executor!=null) {
                Executor.shutdown();
            }
            Connection.closeConnection();
        }
    }

    public void setValue(String group, String key, String value) {
        // ...
        LastTimeUsed = System.currentTimeMillis();
    }
}

ExecutorService stops fine after 5 seconds and the connection closes. But unfortunately keeps running for at least 5 seconds if the caller-method ends.

My test program:

private static void testDBSettings(DBConnection Conn) {
    // using my class
    DBSettings settings = new DBSettings(Conn);
    // set first value, open connection
    settings.setValue("Groupname", "Keyname", "Value");  
    Thread.sleep(1000);
    // set second value, extend connection lifetime
    settings.setValue("otherGroupname", "otherKeyname", "otherValue");  
    Thread.sleep(1000);
    // here is the problem: after "settings" goes out of scope my class should 
    // stop or terminate the ExecutorService without the need to call an extra method.
}

I read a lot about Threads but couldn't find a solution.

tried another approach with ScheduledExecutorService - same result.

finalize() doesn't work because it is only called by garbage colletion.

Can anyone help me?

A. Rohmann
  • 91
  • 2
  • 9
  • That's not how you would do this. Scope is a compile time concept. – Sotirios Delimanolis Sep 21 '15 at 17:50
  • 1
    It is considered best practice to not capitalize your variable names (like you did with `private long LastTimeUsed;`) unless you're defining a constant in which case you would usually use all caps. It can be confusing to read. – Evan LaHurd Sep 21 '15 at 17:54
  • 1
    why even work like this and not use a connection pool ? managing connections yourself is a waste of work... – yael alfasi Sep 21 '15 at 18:09
  • You might check http://stackoverflow.com/questions/2117783/java-executing-a-method-when-objects-scope-ends – Christian Fries Sep 21 '15 at 18:57
  • There are some reasons for managing connections by myself: first I have to support multiple database systems at the same time, use different connections for readonly and readwrite, run in multithreaded envronment ... Thanks for your answers, I'm considering using connection pooling now. – A. Rohmann Sep 22 '15 at 03:27

1 Answers1

0

There is no way to track this in java.

Closest that you can do is use try-with-resource

try(MyClass myClass = new MyClass()){
    myClass.doSomething();

} // Here myClass.close(); will be called.
talex
  • 17,973
  • 3
  • 29
  • 66
  • Ok, I see that my attempt will not work. Threads started in MyClass() can only be terminated by extra code from outside of my class. So I will try to use connection pooling mentioned above. thanks. – A. Rohmann Sep 22 '15 at 03:16