I have multiple cases when I have to deal retrial for DB and networking operations. Everywhere I do it I have the following type of code:
for (int iteration = 1; ; iteration++) {
try {
data = doSomethingUseful(data);
break;
} catch (SomeException | AndAnotherException e) {
if (iteration == helper.getNumberOfRetries()) {
throw e;
} else {
errorReporter.reportError("Got following error for data = {}. Continue trying after delay...", data, e);
utilities.defaultDelayForIteration(iteration);
handleSpecificCase(data);
}
}
}
The issue is that this code pattern is copy-pasted all over my classes. Which is really bad. I can't figure out how to get rid of this for-break-catch copy-paste pattern, since I usually get different exception to handle, I want to log data I failed on (usually also different ways).
Is there a good way to avoid this copy-paste in Java 7?
Edit: I do use guice for dependency injection. I do have checked exceptions. There could be multiple variables instead of just one data and they are all of different type.
Edit2: AOP approach looks as the most promising for me.
Off-hand, I can think of two different approaches:
If the differences in exception handling can be expressed declaratively, you might use AOP to weave the exception handling code around your methods. Then, your business code could look like:
#Retry(times = 3, loglevel = LogLevel.INFO)
List<User> getActiveUsers() throws DatabaseException {
// talk to the database
}
The advantage is that it is really easy to add retry behaviour to a method, the disadvantage is the complexity of weaving the advice (which you only have to implement once. If you are using a dependency injection library, chances are it will offer method interception support).
The other approach is to use the command pattern:
abstract class Retrieable<I,O> {
private final LogLevel logLevel;
protected Retrieable(LogLevel loglevel) {
this.logLevel = loglevel;
}
protected abstract O call(I input);
// subclasses may override to perform custom logic.
protected void handle(RuntimeException e) {
// log the exception.
}
public O execute(I input) {
for (int iteration = 1; ; iteration++) {
try {
return call(input);
} catch (RuntimeException e) {
if (iteration == helper.getNumberOfRetries()) {
throw e;
} else {
handle();
utilities.defaultDelayForIteration(iteration);
}
}
}
}
}
The problem with the command pattern are the method arguments. You are restricted to a single parameter, and the generics are rather unwieldly for the caller. In addition, it won't work with checked exceptions. On the plus side, no fancy AOP stuff :-)
As already suggested, AOP and Java annotations is a good option. I would recommend to use a read-made mechanism from jcabi-aspects:
#RetryOnFailure(attempts = 2, delay = 10, verbose = false)
public String load(URL url) {
return url.openConnection().getContent();
}
Read also this blog post: http://www.yegor256.com/2014/08/15/retry-java-method-on-exception.html
I have implemented the RetryLogic class below which provides reusable retry logic and supports parameters because the code to be retried is in a delegate passed in.
/**
* Generic retry logic. Delegate must throw the specified exception type to trigger the retry logic.
*/
public class RetryLogic<T>
{
public static interface Delegate<T>
{
T call() throws Exception;
}
private int maxAttempts;
private int retryWaitSeconds;
#SuppressWarnings("rawtypes")
private Class retryExceptionType;
public RetryLogic(int maxAttempts, int retryWaitSeconds, #SuppressWarnings("rawtypes") Class retryExceptionType)
{
this.maxAttempts = maxAttempts;
this.retryWaitSeconds = retryWaitSeconds;
this.retryExceptionType = retryExceptionType;
}
public T getResult(Delegate<T> caller) throws Exception {
T result = null;
int remainingAttempts = maxAttempts;
do {
try {
result = caller.call();
} catch (Exception e){
if (e.getClass().equals(retryExceptionType))
{
if (--remainingAttempts == 0)
{
throw new Exception("Retries exausted.");
}
else
{
try {
Thread.sleep((1000*retryWaitSeconds));
} catch (InterruptedException ie) {
}
}
}
else
{
throw e;
}
}
} while (result == null && remainingAttempts > 0);
return result;
}
}
Below is a use example. The code to be retried is within the call method.
private MyResultType getDataWithRetry(final String parameter) throws Exception {
return new RetryLogic<MyResultType>(5, 15, Exception.class).getResult(new RetryLogic.Delegate<MyResultType> () {
public MyResultType call() throws Exception {
return dataLayer.getData(parameter);
}});
}
In case you want to retry only when a specific type of exception occurs (and fail on all other types of exceptions) the RetryLogic class supports an exception class parameter.
Make your doSomething implement an interface, e.g., Runable and create a method containing your code above with doSomething replaced with interface.run(data)
take a look at: this retry utility
this method should work for most use cases:
public static <T> T executeWithRetry(final Callable<T> what, final int nrImmediateRetries,
final int nrTotalRetries, final int retryWaitMillis, final int timeoutMillis)
you can eassily implement an aspect using this utility to do this with even less code.
Extending the approach discusssed already, how about something like this (no IDE on this netbook, so regard this as pseudocode...)
// generics left as an exercise for the reader...
public Object doWithRetry(Retryable r){
for (int iteration = 1; ; iteration++) {
try {
return r.doSomethingUseful(data);
} catch (Exception e) {
if (r.isRetryException(e)) {
if(r.tooManyRetries(i){
throw e;
}
} else {
r.handleOtherException(e);
}
}
}
One thing I would like to add. Most exceptions (99.999%) mean there is something very wrong with your code or environment that needs an admins attention. If your code can't connect to the database it's probably a misconfigured environment there is little point to retrying it just to find out it didn't work the 3rd, 4th, or 5th time either. If you're throwing an exception because the person didn't give a valid credit card number, retrying isn't going to magically fill in a credit card number.
The only situations that are remotely worth retrying is when a system is tremendously strained and things are timing out, but in this situation retry logic is probably going to cause more strain than less (3x for 3 retries on every transaction). But this is what systems do to back down demand (see the apollo lander mission story). When a system is asked to do more than it can it starts dropping jobs and timeouts are the signal the system is strained (or poorly written). You'd be in a far better situation if you just increased the capacity of your system (add more ram, bigger servers, more servers, better algorithms, scale it!).
The other situation would be if you're using optimistic locking and you can somehow recover and auto merge two versions of an object. While I have seen this before I'd caution this approach, but it could be done for simple objects that can be merged without conflicts 100% of the time.
Most exceptions logic should be catch at the appropriate level (very important), make sure your system is in a good consistent state (ie rollback transactions, close files, etc), log it, inform user it didn't work.
But I'll humor this idea and try to give a good framework (well because it's fun like crossword puzzle fun).
// client code - what you write a lot
public class SomeDao {
public SomeReturn saveObject( final SomeObject obj ) throws RetryException {
Retry<SomeReturn> retry = new Retry<SomeReturn>() {
public SomeReturn execute() throws Exception {
try {
// doSomething
return someReturn;
} catch( SomeExpectedBadExceptionNotWorthRetrying ex ) {
throw new NoRetryException( ex ); // optional exception block
}
}
}
return retry.run();
}
}
// framework - what you write once
public abstract class Retry<T> {
public static final int MAX_RETRIES = 3;
private int tries = 0;
public T execute() throws Exception;
public T run() throws RetryException {
try {
return execute();
} catch( NoRetryException ex ) {
throw ex;
} catch( Exception ex ) {
tries++;
if( MAX_RETRIES == tries ) {
throw new RetryException("Maximum retries exceeded", ex );
} else {
return run();
}
}
}
}
Related
i have the following problem:
Our java software takes incoming xml-files and parse / validate / makes some magic. Because it's a 24/7 software it's designed to resist single faults, by ignoring single files and proceeding to the next.
I want to know if there is a possible solution to test units e.g with JUnit or TestNG for already catched exceptions.
For example if have a class and function like this
public class ExceptionTest {
public static void throwEx() {
try {
int i = 1 / 0;
} catch (Exception e) {
e.printStackTrace();
}
}
}
Now i want to test if any Exception is catched. If so the test should fail. On the other hand, if i expect certain types of exceptions, the test should succeed.
public class TSTException {
#Test
public void testExceptionThrown() {
ExceptionTest.throwEx();
assert ("ExceptionsCatched.size()", 0)
}
}
I know i could edit my code to provide some kind of global variables like boolean success = true and check those but i am interested if there is another possible solution for my problem.
Thanks,
Dominik
If it is possible to modify the code You could wrap the class containing the logic and catch the exception in the wrapper class.
something like this:
public class SomeService{
public void doSomething() {
int i = 1 / 0;
}
}
public class SomeServiceCatchExceptionWrapper{
private SomeService someService;
public void doSomething() {
try {
someService.doSomething();
} catch (Exception e) {
e.printStackTrace();
}
}
}
So this way you can test both classes individually.
I have code (simplified) like this:
class A {
B b = new B();
void close() {
b.close();
}
}
class B {
Closeable mustBeClosed = new Closeable() {
{
System.out.println("create");
}
#Override
public void close() {
System.out.println("close");
}
};
int n = 0 / 0;
void close() {
mustBeClosed.close();
}
}
//code
try (A a = new A()) {
//do something
}
How to guarantee mustBeClosed is released?
This likely happens when the object hierarchy is complex. Override finalize for B might not be a perfect solution.
Any best practice or principle against this issue?
A revised version looks like:
class B {
Closeable mustBeClosed;
B() {
try {
mustBeClosed = ...
//other initialization which might raise exceptions
} catch (throwable t) {
close();
throw t;
}
}
void close() {
if (mustBeClosed != null) {
try {
mustBeClosed.close();
} catch (Throwable t) {
}
}
//all other resources that should be closed
}
}
However this takes too much code and is far from elegant. What's more, it seems that all classes in the ownership hierarchy should follow the same style, which results lots of code.
Any advice?
Your problem is that try-with-resources won't (actually can't) call close() if the constructor throws an exception.
Any object construction that allocates a resource, and has the potential to fail during construction after the resource is allocated, must release that resource before the exception is cascaded up the call stack.
Two ways to fix that:
1) Make sure the resource allocation is the last action performed. In your case, that means move field n up before field mustBeClosed.
2) Handle the resource construction in the constructor, not in a field initializer, so you can catch any subsequent exception and release the resource again before re-throwing the exception, as your alternate solution shows.
However, you don't have to null-check in the close() method, because mustBeClosed will always be non-null if the object construction succeeds, and close() cannot be called if the object construction fails.
Use a wrapper method to close all Closeable instances gracefully.
closeGraceFully(Closeable c) { // call this guy for all instances of closeable
try{
c.close();
} catch(IOException ex) {
// nothing can be done here, frankly.
}
}
Then call this wrapper method. don't call close() directly. Don't use finalizers they are evil and will slow down your app.
I have a method which is getting an exception as a parameter to a particular method. This method needs to do perform different logic based on the type of exception. Between below two ways of handling this.. what is the most efficient way (is there a third better way).. and why
public void processException(Exception ex) {
try {
throw ex;
} catch(CustomException e1) {
//do something
} catch (CustomException2 e2) {
//do something else
}
}
or
public void processException(Exception ex) {
if (ex instanceof CustomException) {
// do something
} else if (ex instanceof CustomException2) {
// do something else
}
}
Efficiency aside, the second way is preferred, because the exception is not thrown in a non-exceptional situation. The first way to "dispatch" uses exception throwing in a regular control flow, which makes it harder to read your program.
Besides, the two methods are not identical: the first program must be declared as throwing a checked exception, because not all subtypes are handled by the catch blocks.
If you are dealing with custom exceptions that your program defines, you have a way to avoid checking the subtype: since Exception objects are regular classes, you could add a package-visible method to them, and have them implement a package-visible interface holding that method. Exceptions would then be able to override that method, letting you use a regular "virtual" dispatch rather than checking for the exact class type at runtime.
Here is an illustration of this approach: let's say you want your exceptions to write themselves to a log file. You can do this as follows:
interface LoggableException {
void logToFile();
}
public class CustomExceptionOne extends Exception implements LoggableException {
...
public void logToFile() {
// Do something
}
}
public class CustomExceptionTwo extends Exception implements LoggableException {
...
public void logToFile() {
// Do something else
}
}
public void processException(Exception ex) {
if (ex instanceof LoggableException) {
LoggableException lEx = (LoggableException)ex;
lEx.logToFile();
}
}
The first one is a very bad idea. Logic should not be expressed as exception catching. They're expensive, whether you realize it or not.
I don't like the second one, either. When you see if/else logic, you should think about polymorphism.
Obviously the second option is better. All the Exceptions are eventually objects and it is better, safe and recommended to perform instance of check to determine the type of object.
Throwing and catching Exceptions are expensive operations and should only occur in exceptional circumstances. In addition, your method to handle the exception is probably being called because the exception was already thrown. I wouldn't throw it again.
Either instanceof, or overloaded processException like rgettman suggests. Another alternative is
public void processException(Exception e) {
Class eClass = e.getClass();
if (eClass == CustomeException.class) { // This exception is most likely.
// do something
} else if (eClass == CustomException2.class) {
// do something
} else if (eClass == CustomException3.class) {
// do something
} else if (eClass == CustomException4.class) {
// do something
}
}
I would suggest short circuiting the if/else if statements with the most likely exception class.
A method returns some result, making a number of "attempts" to build it. The first attempt that succeeds should return. If none of them succeed an exception should be thrown:
class Calculator {
public String calculate() throws Exception {
// how do design it?
}
private String attempt1() throws Exception {
// try to calculate and throw if fails
}
private String attempt2() throws Exception {
// try to calculate and throw if fails
}
private String attempt3() throws Exception {
// try to calculate and throw if fails
}
}
It's important to mention that the exception thrown by calculate should preserve stack traces of all other exceptions thrown by private methods. How would you recommend to design calculate() method, with extendability and maintainability in mind?
I would use Composite and Command.
interface CalculateCommand {
public void calculate(CalculateContext context);
}
Now create an implementation for each attempt you want.
Next create a CompositeCommand -- here is an outline (you will need to fill in the blanks)
public class CompositeCalculateCommand implements CalculateCommand {
CompositeCalculateCommand(List<CompositeCommand> commands) {
this.commands = commands; // define this as a field
}
public void calculate(CommandContext context) {
for (CalculateCommand command : commands) {
try {
command.calculate(context);
} catch(RuntimeException e) {
this.exceptions.add(e) // initialize a list to hold exceptions
}
if (context.hasResult) return; // break
}
// throw here. You didn't success since you never saw a success in your context. You have a list of all exceptions.
}
}
finally use it like
CalculateCommand allCommands = new CompositeCalculateCommand(someListOfCommands);
allCommands.calculate(someContextThatYouDefine);
// results now on context.
Note each command implementation is testable on its own, so this is very maintainable. If you need to add calculations, you simply define a new type of CalculateCommand, so this is extensible. It will also play well with dependency injection. Note I define a CommandContext object so different commands can take different types of stuff (put in a context).
I have a Java application that uses lots of java.sql.Connection to a database.
I want to test that, if the database is unavailable, my services return the appropriate error codes (distinguishing between temporary and permanent problems e.g. HTTP 500 and 503).
For testing, my application connects to an embedded, local, in-memory h2 database; the application is not aware of this, only my integration test is.
How can I make writes to the database fail deterministically, e.g. hook into commits and make them throw a custom SQLException? I want a global 'database is unavailable' boolean in the test code that affects all connections and makes my application exercise its reconnect logic.
(I had started by proxying Connection and putting an if(failFlag) throw new MySimulateFailureException() in commit(); but this didn't catch PreparedStatement.executeUpdate(); before I embark on proxying the PreparedStatement too - its a lot of methods! - I'd like to be taught a better way...)
I think this is a good candidate for using aspects. With eg. Spring it is supremely easy to pointcut entire packages or just certain methods that you wish to fail - specifically you could have a before advice always throwing a ConnectException or do something more advanced with the around advice.
Cheers,
I ended up making my own Java reflection wrapper that intercepts Connection.commit and the PreparedStatement.execute... methods.
My final code in my 'DBFactory' class:
#SuppressWarnings("serial")
public class MockFailureException extends SQLException {
private MockFailureException() {
super("The database has been deliberately faulted as part of a test-case");
}
}
private class MockFailureWrapper implements InvocationHandler {
final Object obj;
private MockFailureWrapper(Object obj) {
this.obj = obj;
}
#Override public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
if(dbFailure && ("commit".equals(m.getName()) || m.getName().startsWith("execute")))
throw new MockFailureException();
Object result;
try {
result = m.invoke(obj, args);
if(result instanceof PreparedStatement)
result = java.lang.reflect.Proxy.newProxyInstance(
result.getClass().getClassLoader(),
result.getClass().getInterfaces(),
new MockFailureWrapper(result));
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
}
return result;
}
}
public Connection newConnection() throws SQLException {
Connection connection = DriverManager.getConnection("jdbc:h2:mem:"+uuid+";CREATE=TRUE;DB_CLOSE_ON_EXIT=FALSE");
return (Connection)java.lang.reflect.Proxy.newProxyInstance(
connection.getClass().getClassLoader(),
connection.getClass().getInterfaces(),
new MockFailureWrapper(connection));
}