public class BusyBodyService
{
public Object fetch() throws Exception
{
// trace entry
log("Entered BusyBody");
// start profiler
startStopWatch();
// check cache
if (isCached())
{
return fetchFromCache();
}
// fetch from database - loop until connection made or bail out
int numAttempts = 0;
int maxRetries = 5;
Exception t = null;
Object retval = null;
do
{
numAttempts++;
// set isolation level
setRepeatableRead();
// start transaction
startTransaction();
try
{
// -------------- pure business logic starts here --------------
retval = getFromDatabase();
// -------------- pure business logic ends here --------------
// commit transaction
commit();
// deal with various exceptions
} catch (DatabaseDownException ex)
{
log("Database is down");
// email administrator
emailDBA("Database is down; you're working all weekend");
} catch (NetworkDownException ex)
{
log("Network is down");
// email administrator
emailNetworkAdmin("Network is down; you're fired");
} catch (Exception ex)
{
// rollback transaction
rollback();
System.out.println("Caught exception; retry attempt #" +
numAttempts);
t = ex;
} finally
{
// close database connection
closeConnection();
}
} while (numAttempts <= maxRetries);
if (retval == null)
{
throw t;
}
// save in cache
cache(retval);
// stop profiler
stopStopWatch();
// trace exit
log("Exit BusyBody");
return retval;
}
}
Although I knew better, I didn't have the tools to factor out all the orthogonal concerns:
- tracing
- profiling
- caching
- retry strategy
- transaction isolation levels
- transactional wrapping
- dealing with specialized exceptions
- cleaning up connections and other resources
public class CleanAndElegantService
{
public Object fetch() throws Exception
{
return getFromDatabase();
}
}
...I'm thinking you might care about this also (I'm assuming there's no need to elaborate on this - the difference should speak for itself). In subsequent posts I'll explore Spring 3.x AOP to see if we can't factor out all the aspects and move from busy-body to clean-and-elegant.
