For a mysql connection I have a connection object and use a transaction mechanism connection.startTransaction(), connection.commitTransaction(), connection.rollbackTransaction().
For each startTransaction(), there must always be either a call to commitTransaction() or to rollbackTransaction(). Missing such a call or calling both would break my transaction system.
So I use them in the following way:
boolean i_am_in_a_transaction=true;
try {
connection.startTransaction();
...
i_am_in_a_transaction=false;
connection.commitTransaction();
} finally {
if(i_am_in_a_transaction) {
connection.rollbackTransaction();
}
}
This ensures the declared calling order, but it is much effort, because I have to write this lines everywhere where I use transactions.
In C++ I would use a transaction object that checks in its destructor, if the commit() function was called, and that otherwise calls rollback():
class Transaction {
public:
Transaction()
:am_in_transaction(false) {
}
~Transaction() {
if(_am_in_transaction) {
rollback();
}
}
void startTransaction() {
_am_in_transaction=true;
...start Transaction...
}
void commit() {
_am_in_transaction=false;
...commit Transaction...
}
void rollback() {
_am_in_transaction=false;
...rollback Transaction...
}
private:
bool _am_in_transaction;
}
This way I have the logic implemented at one place and can use it really simple:
Transaction my_transaction;
my_transaction.startTransaction;
...
my_transaction.commit();
This code is much simpler than the above java code with the try/finally block.
Is there a way to implement this behaviour in java without dedicating the logic to the caller and making him implement the try/finally block?
Something like a way to automatically call a function on scope exit would help me.
A couple solutions come to mind…
As @Dark Falcon points out, this would be a good use case for a try with resources call that will automatically clean up your resources at the end of the try. Unfortunately, this is only available in Java 7.
Java classes do define a
finalize()method that can get called when the object gets garbage collected, but overriding this method is almost never the right thing to do.I think your only other option if you’re hooked on this idea of “execute code on function return” is to using Aspect Oriented Programming. If you read up on some packages like AspectJ or look into use AOP with Spring, you can do some configuration magic to get code to execute when a function returns by intercepting the call. Here’s an example of using Spring AOP to execute other code when your function returns.