Reputation: 881
Look at this code:
IDfSessionManager manager = DfcSessionManager.getSessionManager();
try {
IDfSession session = manager.getSession(DfsUtils.getCurrentRepository());
...
return somewhat; //May be without return statement
} finally {
if (session != null) {
manager.release(session);
}
}
Such construction repeats many times and surrounds different code. This can be a method with or without return statement. I want to make something reusable of this try-finally block.
I've think out of such realization.
public abstract class ISafeExecute<T> {
private IDfSession session = null;
protected abstract T execute() throws DfException;
public T executeSafely() throws Exception {
IDfSessionManager manager = DfcSessionManager.getSessionManager();
try {
session = manager.getSession(DfsUtils.getCurrentRepository());
return execute();
} finally {
if (session != null) {
manager.release(session);
}
}
}
public IDfSession getSession() {
return session;
}
}
Session field was made with public getter.
And we can use this class like this(with returned object):
return new ISafeExecute<String>() {
@Override
public String execute() throws DfException {
return getSession().getLoginTicket();
}
}.executeSafely();
Or without return object:
new ISafeExecute() {
@Override
public Object execute() {
someMethod();
return null;
}
}.executeSafely();
Upvotes: 3
Views: 2855
Reputation: 881
I've come to such decision:
public abstract class SafeExecute<T> {
protected IDfSession session = null;
public T executeSafely() throws Exception {
IDfSessionManager manager = DfcSessionManager.getSessionManager();
try {
session = manager.getSession(DfsUtils.getCurrentRepository());
return logic();
} finally {
if (session != null) {
manager.release(session);
}
}
}
protected abstract T logic() throws Exception;
}
Then by extending this class:
public class Service extends SafeExecute<String> {
public String getLoginTicket() throws Exception {
return executeSafely();
}
@Override
protected String logic() throws Exception {
//TODO implement
}
}
Upvotes: 0
Reputation: 12523
You can use Runnable<T>
to build a mechanism to do this (sort of injecting a function into another function):
public void runInSession(Runnable<IDfSession> runnable) {
IDfSession session = null;
try {
session = manager.getSession(DfsUtils.getCurrentRepository());
runnable.run(session);
} finally {
if (session != null) {
manager.release(session);
}
}
}
You could use more generics to enable you to return values as well. I'm lacking a Java compiler here and I'm a bit unsure about the syntax though.
Edit, as I see your edits:
Using a custom ISafeExecute
interface may be even neater than using Runnable<T>
, but the idea remains the same. You can built it so that a return value (or error) can be places elegantly:
interface ISafeExecute<T> {
void execute(IDfSession session);
T getResult();
Exception getException();
}
mySafeExecute.execute(session);
if(mySafeExecute.getException() == null) {
return mySafeExecute.getResult();
} else {
// runtime exception or declaration in method
// signature
throw new RuntimeException(mySafeExecute.getException());
}
Upvotes: 5