Reputation: 35
I have a number of microservices which needs a retry mechanism if connection with database fails. This retry mechanism has to be triggered when SQLException and HibernateException occurs. Passing a proper interceptor in @Retryable will work but this has to be incorporated in all the microservices. Can we make a custom annotation similar to @Retryable like @DatabaseRetryable which will trigger retry on SQLException and HibernateException.
Usage of this annotation would be roughly as following
@DatabaseRetryable
void executeQuery()
{
//some code
}
Upvotes: 0
Views: 2406
Reputation: 850
You can solve this by creating a meta-annotation with your desired name:
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Retryable(
value = { SQLException.class, HibernateException.class }
)
public @interface DatabaseRetryable {
}
You can use this meta-annotation as drop-in replacement for @Retryable
. The same constraints apply - it just allows to configure some common behavior in a single place. You might also use this to use the same backOff
for all related services.
Upvotes: 1
Reputation: 453
There are several approaches for this:
My suggestion is look at your problem, is you desired solution needed for more than just these retries? Then go with a library. Is it simple one/two use case scenarios then go with a utility class/method approach.
A very crude example of this could be a util class:
import java.util.logging.Level;
import java.util.logging.Logger;
public class RetryOperation {
public static void main(String args[]) {
retryOnException(() -> {throw new Exception();} , Exception.class, 4);
}
interface CustomSupplier<T> {
T get() throws Exception;
}
static <E extends Exception, T> T retryOnException(CustomSupplier<T> method, Class<E> exceptionClass, int retries) {
if (method == null) {
throw new IllegalArgumentException("Method may not be null");
}
if (exceptionClass == null) {
throw new IllegalArgumentException("Exception type needs to be provided");
}
int retryCount = 0;
T result = null;
while (retryCount < retries) {
try {
result = method.get();
} catch (Exception exception) {
if (exceptionClass.isAssignableFrom(exception.getClass()) && retryCount < retries) {
// log the exception here
retryCount++;
Logger.getLogger(RetryOperation.class.getName()).log(Level.INFO, String.format("Failed %d time to execute method retrying", retryCount));
} else {
throw exception;
}
}
}
return result;
}
}
Note that this is a crude example and should only function to explain my thinking behind it. Look at what you exactly need and design from there.
Upvotes: 1