1

Connect.java

public interface Connect {
void commit();
void close();
void setTransactional();
void executeCommand();
}

MainApp.java

public class MainApp {
    public static void main(String[] args) {
        Connect conn=MainApp.getTransactionalConnection();
        conn.executeCommand();
        conn.executeCommand();
        conn.executeCommand();
        conn.executeCommand();
        closeConnection(conn);      
    }
    public static Connect getNormalConnection(){
        return DriverManager.getConnection(); //returns class i have no access to , dont even know its name
    }
    public static Connect getTransactionalConnection(){
        Connect conn =  getNormalConnection();
        conn.setTransactional();
        return conn;
    }
    private static void closeConnection(Connect conn) {
        //something like if connection is transactional then conn.commit();

        conn.close();
    }

}

I got like 100 functions which look like main(). The problem is I don't want to change the code of these 100 functions and only change 1 line getNormalConnection to getTransactionalConnection . I don't have access and don't know names of classes implementing Connect interface . I want only to add commit to closeConnection() whether I created a transactional connection or not .

Nagaraj S
  • 13,316
  • 6
  • 32
  • 53
repo
  • 748
  • 1
  • 8
  • 19

2 Answers2

0

It sounds like what you want is to make implementing classes of your interface have a default implementation of certain methods?
You cannot do this with an interface, that's the purpose of an abstract class. This would of course mean you would have to extend an abstract class rather than implement an interface in each class however.

Ross Drew
  • 8,163
  • 2
  • 41
  • 53
  • 1
    Just an add-on: Before changing the interface to an abstract class you should also keep in mind that changing an interface to an abstract class is a binary incompatible change. All client code must be re-compiled. – René Link Dec 24 '13 at 10:57
0

One simple answer is to have your own implementation of Connect which either exposes an isTransactional property, or which automatically commits when it's transactional, delegating everything else to an underlying connection:

public class AutoCommitConnect implements Connect {
    private final Connect connect;
    private boolean transactional = false;
    private boolean committed = false;

    public AutoCommitConnect(Connect delegate) {
        this.delegate = delegate;
    }

    public void commit() {
        delegate.commit();
        committed = true;
    }

    public void setTransactional() {
        transactional = true;
        delegate.setTransactional();
    }

    public void close() {
        if (transactional && !committed) {
            commit();
        }
        delegate.close();
    }

    public void executeCommand() {
        delegate.executeCommand();
    }
}

Then change your connection-returning methods to use it:

public static Connect getNormalConnection() {
    // getTransactionalConnection will call setTransactional on the wrapper,
    // which will remember that it needs to commit
    return new AutoCommitConnect(DriverManager.getConnection());
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • But what when Connect contains 60 methods? Each of them we have to "wrap". The other possible solution would be to make external Map, and keep references with boolean isTransactional. It is very easy to implement, but for this simply situation isn't it recommended? – MistyK Dec 24 '13 at 11:09
  • @Zbigniew: At that points, it's a different question - and I'd be deeply suspicious of such an interface, in general. Wrapping is pretty easy though - decent IDEs can generate all that code for you, and then you just need to work out which methods you want to handle differently. – Jon Skeet Dec 24 '13 at 11:10
  • http://pastebin.com/MfMvMAmT What do you think about this in c++ ? I know it is turbo-ugly;] It's working but i think fancyPointer can sometimes be a random number, maybe even '5' so its gonna fail hard. – repo Dec 24 '13 at 11:53
  • @user3132199: It's not clear why you're bringing C++ into the picture at all, or what you're trying to achieve. I wouldn't make the code which has `getTransactionalConnect` a `Connect` implementation itself though - I see no particular reason for that. – Jon Skeet Dec 24 '13 at 11:56
  • Because i wanted to know the equivalent in Java or C# – repo Dec 24 '13 at 11:58