WelcomeTo
WelcomeTo

Reputation: 20591

AspectJ - Exclude try-finally block into aspect

I have many methods like this:

    Connection connection = null;
    try {
        connection = new Connection();
        connection.connect();
        .... // method body

    } finally {
        if (connection != null) {
            connection.disconnect();
        }
    }

Can I exclude this part into apects (AspectJ)?

Upvotes: 0

Views: 542

Answers (2)

Marko Topolnik
Marko Topolnik

Reputation: 200246

You can extract your connection management into an around-advice and make the contextual Connection available to the business code by exposing it in a ThreadLocal. Define a public class with a static property:

public class ConnectionHolder {
  public static final ThreadLocal<Connection> connection = new ThreadLocal<>();
}

In the around advice you must set the ThreadLocal to the open connection and make very sure you unconditionally clear it afterwards. This is the greatest pitfall with ThreadLocals: leaking objects into unrelated contexts. Also beware of child thread inheriting the ThreadLocal (there was an issue with this in WebSphere once).

All in all, ThreadLocals are quite a dirty solution, but anything else will require you to go for a dependency-injection framework like Spring, configure request-scoped beans, etc., which would be a good idea, but will take more research on your part.

Upvotes: 2

matsev
matsev

Reputation: 33779

Alternatively, you can extract the connection plumbing using the template pattern to avoid copy / paste. The basic idea is something like:

abstract ConnectionTemplate {
    private Connection connection = // ...

    /**
     * Method to be implementad by child classes
     */
    public abstract void businessLogicCallback(); 

    /**
     * Template method that ensure that mandatory plumbing is executed
     */
    public void doBusinessLogic() {
        try {
            openConnection();
            // fetch single result, iterate across resultset, etc
            businessLogicCallback();
        finally {
            closeConnection();
        }
    }

    void openConnection() {
        connection.open();
    }

    void closeConnection() {
        if (connection != null) {
            connection.close();
        }
    }
}

Now, implementing classes can be as simple as

class ImportantBusinessClass extends ConnectionTemplate {

    @Override
    public void businessLogicCallback() {
        // do something important
    }
}

And you use it like

ImportantBusinessClass importantClass = new ImportantBusinessClass();
importantClass.doBusinessLogic();      // opens connection, execute callback and closes connection

Spring framework uses this technique in some places, notably the JdbcTemplate deals with SQL, connections, mapping between rows and domain objects, etc. Please refer to the source code in GitHub for implementation details.

Upvotes: 0

Related Questions