I'm using a third party Java library to interact with a REST API. The REST API can sometimes take a long time to respond, eventually resulting in a java.net.ConnectException being thrown.
I'd like to shorten the timeout period but have no means of modifying the third party library.
I'd like to apply some form of timeout control around the calling of a Java method so that I can determine at what point to give up waiting.
This doesn't relate directly to network timeouts. I'd like to be able to try and perform an operation and be able to give up after a specified wait time.
The following is by no means valid Java but does conceptually demonstrate what I'd like to achieve:
try {
Entity entity = new Entity();
entity.methodThatMakesUseOfRestApi();
} catch (<it's been ages now, I don't want to wait any longer>) {
throw TimeoutException();
}
I recommend TimeLimiter from Google Guava library.
This is probably the current way how this should be done with plain Java:
public String getResult(final RESTService restService, String url) throws TimeoutException {
// should be a field, not a local variable
ExecutorService threadPool = Executors.newCachedThreadPool();
// Java 8:
Callable<String> callable = () -> restService.getResult(url);
// Java 7:
// Callable<String> callable = new Callable<String>() {
// #Override
// public String call() throws Exception {
// return restService.getResult(url);
// }
// };
Future<String> future = threadPool.submit(callable);
try {
// throws a TimeoutException after 1000 ms
return future.get(1000, TimeUnit.MILLISECONDS);
} catch (ExecutionException e) {
throw new RuntimeException(e.getCause());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new TimeoutException();
}
}
There is no general timeout mechanism valid for arbitrary operations.
While... there is one... by using Thread.stop(Throwable). It works and it's thread safe, but your personal safety is in danger when the angry mob confronts you.
// realizable
try
{
setTimeout(1s); // 1
... any code // 2
cancelTimeout(); // 3
}
catch(TimeoutException te)
{
// if (3) isn't executed within 1s after (1)
// we'll get this exception
}
Now we have our nice CompletableFuture , here an application to achieve what was asked.
CompletableFuture.supplyAsync(this::foo).get(15, TimeUnit.SECONDS)
You could use a Timer and a TimerTask.
Here's a utility class I wrote, which should do the trick unless I've missed something. Unfortunately it can only return generic Objects and throw generic Exceptions. Others may have better ideas on how to achieve this.
public abstract class TimeoutOperation {
long timeOut = -1;
String name = "Timeout Operation";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getTimeOut() {
return timeOut;
}
public void setTimeOut(long timeOut) {
this.timeOut = timeOut;
}
public TimeoutOperation (String name, long timeout) {
this.timeOut = timeout;
}
private Throwable throwable;
private Object result;
private long startTime;
public Object run () throws TimeoutException, Exception {
Thread operationThread = new Thread (getName()) {
public void run () {
try {
result = doOperation();
} catch (Exception ex) {
throwable = ex;
} catch (Throwable uncaught) {
throwable = uncaught;
}
synchronized (TimeoutOperation.this) {
TimeoutOperation.this.notifyAll();
}
}
public synchronized void start() {
super.start();
}
};
operationThread.start();
startTime = System.currentTimeMillis();
synchronized (this) {
while (operationThread.isAlive() && (getTimeOut() == -1 || System.currentTimeMillis() < startTime + getTimeOut())) {
try {
wait (1000L);
} catch (InterruptedException ex) {}
}
}
if (throwable != null) {
if (throwable instanceof Exception) {
throw (Exception) throwable;
} else if (throwable instanceof Error) {
throw (Error) throwable;
}
}
if (result != null) {
return result;
}
if (System.currentTimeMillis() > startTime + getTimeOut()) {
throw new TimeoutException("Operation '"+getName()+"' timed out after "+getTimeOut()+" ms");
} else {
throw new Exception ("No result, no exception, and no timeout!");
}
}
public abstract Object doOperation () throws Exception;
public static void main (String [] args) throws Throwable {
Object o = new TimeoutOperation("Test timeout", 4900) {
public Object doOperation() throws Exception {
try {
Thread.sleep (5000L);
} catch (InterruptedException ex) {}
return "OK";
}
}.run();
System.out.println(o);
}
}
static final int NUM_TRIES =4;
int tried =0;
boolean result =false;
while (tried < NUM_TRIES && !result)
{
try {
Entity entity = new Entity();
result = entity.methodThatMakesUseOfRestApi();
}
catch (<it's been ages now, I don't want to wait any longer>) {
if ( tried == NUM_TRIES)
{
throw new TimeoutException();
}
}
tried++;
Thread.sleep(4000);
}
Related
I am trying to write a simple function that long-polls multiple messages tothe downstream dependency without exhausting it and only exist when all messages succeeded.
I came up with a way to wrap each message polling into a callable and use a ExecutorService to submit a list of callables.
public void poll(final List<Long> messageIdList) {
ExecutorService executorService = Executors.newFixedThreadPool(messageIdList.size());
List<MessageStatusCallable> callables = messageIdList.stream()
.map(messageId -> new MessageStatusCallable(messageId)).collect(Collectors.toList());
boolean allSuccess = false;
try {
allSuccess = executorService.invokeAll(callables).stream().allMatch(success -> {
try {
return success.get().equals(Boolean.TRUE);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
} catch (ExecutionException e) {
e.printStackTrace();
return false;
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class MessageStatusCallable implements Callable<Boolean> {
private Long messageId;
public MessageStatusCallable(Long messageId) {
this.messageId = messageId;
}
/**
* Computes a result, or throws an exception if unable to do so.
*
* #return computed result
* #throws Exception if unable to compute a result
*/
#Override
public Boolean call() throws Exception {
String messageStatus = downstreamService.getMessageStatus(messageId);
while(messageStatus == null || !messageStatus.equals( STATUS_VALUE_SUCCEEDED) {
messageStatus = messageLogToControlServer.getMessageStatus(messageId);
Thread.sleep(TimeUnit.MICROSECONDS.toMillis(100));
}
LOG.info("Message: " + messageId + " Succeded");
return true;
}
}
I wonder if there is a better way to achieve this since Thread.sleep is blocking and ugly.
I'm not sure this is the best solution but it occurred to me you could use a CountDownLatch and ScheduledExecutorService.
public void poll(final List<Long> messageIdList) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(messageIdList.size());
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(POOL_SIZE);
try {
for (Long messageId : messageIdList) {
MessageStatusCallable callable = new MessageStatusCallable(messageId, latch);
executorService.scheduleWithFixedDelay(
() -> {
String messageStatus = downstreamService.getMessageStatus(messageId);
if (STATUS_VALUE_SUCCEEDED.equals(messageStatus)) {
latch.countDown();
throw new CompletionException("Success - killing the task", null);
}
},
0, 100, TimeUnit.MILLISECONDS);
}
latch.await();
} finally {
executorService.shutdown();
}
}
I probably also wouldn't have the Runnable as a lambda other than for brevity in the answer.
I'm trying to use Java's ThreadPoolExecutor class to run a large number of heavy weight tasks with a fixed number of threads. Each of the tasks has many places during which it may fail due to exceptions.
I've subclassed ThreadPoolExecutor and I've overridden the afterExecute method which is supposed to provide any uncaught exceptions encountered while running a task. However, I can't seem to make it work.
For example:
public class ThreadPoolErrors extends ThreadPoolExecutor {
public ThreadPoolErrors() {
super( 1, // core threads
1, // max threads
1, // timeout
TimeUnit.MINUTES, // timeout units
new LinkedBlockingQueue<Runnable>() // work queue
);
}
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if(t != null) {
System.out.println("Got an error: " + t);
} else {
System.out.println("Everything's fine--situation normal!");
}
}
public static void main( String [] args) {
ThreadPoolErrors threadPool = new ThreadPoolErrors();
threadPool.submit(
new Runnable() {
public void run() {
throw new RuntimeException("Ouch! Got an error.");
}
}
);
threadPool.shutdown();
}
}
The output from this program is "Everything's fine--situation normal!" even though the only Runnable submitted to the thread pool throws an exception. Any clue to what's going on here?
Thanks!
WARNING: It should be noted that this solution will block the calling thread in future.get().
If you want to process exceptions thrown by the task, then it is generally better to use Callable rather than Runnable.
Callable.call() is permitted to throw checked exceptions, and these get propagated back to the calling thread:
Callable task = ...
Future future = executor.submit(task);
// do something else in the meantime, and then...
try {
future.get();
} catch (ExecutionException ex) {
ex.getCause().printStackTrace();
}
If Callable.call() throws an exception, this will be wrapped in an ExecutionException and thrown by Future.get().
This is likely to be much preferable to subclassing ThreadPoolExecutor. It also gives you the opportunity to re-submit the task if the exception is a recoverable one.
From the docs:
Note: When actions are enclosed in
tasks (such as FutureTask) either
explicitly or via methods such as
submit, these task objects catch and
maintain computational exceptions, and
so they do not cause abrupt
termination, and the internal
exceptions are not passed to this
method.
When you submit a Runnable, it'll get wrapped in a Future.
Your afterExecute should be something like this:
public final class ExtendedExecutor extends ThreadPoolExecutor {
// ...
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Future<?> future = (Future<?>) r;
if (future.isDone()) {
future.get();
}
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
if (t != null) {
System.out.println(t);
}
}
}
The explanation for this behavior is right in the javadoc for afterExecute:
Note: When actions are enclosed in
tasks (such as FutureTask) either
explicitly or via methods such as
submit, these task objects catch and
maintain computational exceptions, and
so they do not cause abrupt
termination, and the internal
exceptions are not passed to this
method.
I got around it by wrapping the supplied runnable submitted to the executor.
CompletableFuture.runAsync(() -> {
try {
runnable.run();
} catch (Throwable e) {
Log.info(Concurrency.class, "runAsync", e);
}
}, executorService);
I'm using VerboseRunnable class from jcabi-log, which swallows all exceptions and logs them. Very convenient, for example:
import com.jcabi.log.VerboseRunnable;
scheduler.scheduleWithFixedDelay(
new VerboseRunnable(
Runnable() {
public void run() {
// the code, which may throw
}
},
true // it means that all exceptions will be swallowed and logged
),
1, 1, TimeUnit.MILLISECONDS
);
Another solution would be to use the ManagedTask and ManagedTaskListener.
You need a Callable or Runnable which implements the interface ManagedTask.
The method getManagedTaskListener returns the instance you want.
public ManagedTaskListener getManagedTaskListener() {
And you implement in ManagedTaskListener the taskDone method:
#Override
public void taskDone(Future<?> future, ManagedExecutorService executor, Object task, Throwable exception) {
if (exception != null) {
LOGGER.log(Level.SEVERE, exception.getMessage());
}
}
More details about managed task lifecycle and listener.
This works
It is derived from SingleThreadExecutor, but you can adapt it easily
Java 8 lamdas code, but easy to fix
It will create a Executor with a single thread, that can get a lot of tasks; and will wait for the current one to end execution to begin with the next
In case of uncaugth error or exception the uncaughtExceptionHandler will catch it
public final class SingleThreadExecutorWithExceptions {
public static ExecutorService newSingleThreadExecutorWithExceptions(final Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
ThreadFactory factory = (Runnable runnable) -> {
final Thread newThread = new Thread(runnable, "SingleThreadExecutorWithExceptions");
newThread.setUncaughtExceptionHandler( (final Thread caugthThread,final Throwable throwable) -> {
uncaughtExceptionHandler.uncaughtException(caugthThread, throwable);
});
return newThread;
};
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(),
factory){
protected void afterExecute(Runnable runnable, Throwable throwable) {
super.afterExecute(runnable, throwable);
if (throwable == null && runnable instanceof Future) {
try {
Future future = (Future) runnable;
if (future.isDone()) {
future.get();
}
} catch (CancellationException ce) {
throwable = ce;
} catch (ExecutionException ee) {
throwable = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (throwable != null) {
uncaughtExceptionHandler.uncaughtException(Thread.currentThread(),throwable);
}
}
});
}
private static class FinalizableDelegatedExecutorService
extends DelegatedExecutorService {
FinalizableDelegatedExecutorService(ExecutorService executor) {
super(executor);
}
protected void finalize() {
super.shutdown();
}
}
/**
* A wrapper class that exposes only the ExecutorService methods
* of an ExecutorService implementation.
*/
private static class DelegatedExecutorService extends AbstractExecutorService {
private final ExecutorService e;
DelegatedExecutorService(ExecutorService executor) { e = executor; }
public void execute(Runnable command) { e.execute(command); }
public void shutdown() { e.shutdown(); }
public List shutdownNow() { return e.shutdownNow(); }
public boolean isShutdown() { return e.isShutdown(); }
public boolean isTerminated() { return e.isTerminated(); }
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
return e.awaitTermination(timeout, unit);
}
public Future submit(Runnable task) {
return e.submit(task);
}
public Future submit(Callable task) {
return e.submit(task);
}
public Future submit(Runnable task, T result) {
return e.submit(task, result);
}
public List> invokeAll(Collection> tasks)
throws InterruptedException {
return e.invokeAll(tasks);
}
public List> invokeAll(Collection> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
return e.invokeAll(tasks, timeout, unit);
}
public T invokeAny(Collection> tasks)
throws InterruptedException, ExecutionException {
return e.invokeAny(tasks);
}
public T invokeAny(Collection> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return e.invokeAny(tasks, timeout, unit);
}
}
private SingleThreadExecutorWithExceptions() {}
}
This is because of AbstractExecutorService :: submit is wrapping your runnable into RunnableFuture (nothing but FutureTask) like below
AbstractExecutorService.java
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null); /////////HERE////////
execute(ftask);
return ftask;
}
Then execute will pass it to Worker and Worker.run() will call the below.
ThreadPoolExecutor.java
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run(); /////////HERE////////
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
Finally task.run(); in the above code call will call
FutureTask.run(). Here is the exception handler code, because of
this you are NOT getting the expected exception.
class FutureTask<V> implements RunnableFuture<V>
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) { /////////HERE////////
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
If you want to monitor the execution of task, you could spin 1 or 2 threads (maybe more depending on the load) and use them to take tasks from an ExecutionCompletionService wrapper.
The doc's example wasn't giving me the results I wanted.
When a Thread process was abandoned (with explicit interput();s) Exceptions were appearing.
Also I wanted to keep the "System.exit" functionality that a normal main thread has with a typical throw, I wanted this so that the programmer was not forced to work on the code having to worry on it's context (... a thread), If any error appears, it must either be a programming error, or the case must be solved in place with a manual catch... no need for overcomplexities really.
So I changed the code to match my needs.
#Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
Future<?> future = (Future<?>) r;
boolean terminate = false;
try {
future.get();
} catch (ExecutionException e) {
terminate = true;
e.printStackTrace();
} catch (InterruptedException | CancellationException ie) {// ignore/reset
Thread.currentThread().interrupt();
} finally {
if (terminate) System.exit(0);
}
}
}
Be cautious though, this code basically transforms your threads into a main thread Exception-wise, while keeping all it's parallel properties... But let's be real, designing architectures in function of the system's parallel mechanism (extends Thread) is the wrong approach IMHO... unless an event driven design is strictly required....but then... if that is the requirement the question is: Is the ExecutorService even needed in this case?... maybe not.
If your ExecutorService comes from an external source (i. e. it's not possible to subclass ThreadPoolExecutor and override afterExecute()), you can use a dynamic proxy to achieve the desired behavior:
public static ExecutorService errorAware(final ExecutorService executor) {
return (ExecutorService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[] {ExecutorService.class},
(proxy, method, args) -> {
if (method.getName().equals("submit")) {
final Object arg0 = args[0];
if (arg0 instanceof Runnable) {
args[0] = new Runnable() {
#Override
public void run() {
final Runnable task = (Runnable) arg0;
try {
task.run();
if (task instanceof Future<?>) {
final Future<?> future = (Future<?>) task;
if (future.isDone()) {
try {
future.get();
} catch (final CancellationException ce) {
// Your error-handling code here
ce.printStackTrace();
} catch (final ExecutionException ee) {
// Your error-handling code here
ee.getCause().printStackTrace();
} catch (final InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
} catch (final RuntimeException re) {
// Your error-handling code here
re.printStackTrace();
throw re;
} catch (final Error e) {
// Your error-handling code here
e.printStackTrace();
throw e;
}
}
};
} else if (arg0 instanceof Callable<?>) {
args[0] = new Callable<Object>() {
#Override
public Object call() throws Exception {
final Callable<?> task = (Callable<?>) arg0;
try {
return task.call();
} catch (final Exception e) {
// Your error-handling code here
e.printStackTrace();
throw e;
} catch (final Error e) {
// Your error-handling code here
e.printStackTrace();
throw e;
}
}
};
}
}
return method.invoke(executor, args);
});
}
This is similar to mmm's solution, but a bit more understandable. Have your tasks extend an abstract class that wraps the run() method.
public abstract Task implements Runnable {
public abstract void execute();
public void run() {
try {
execute();
} catch (Throwable t) {
// handle it
}
}
}
public MySampleTask extends Task {
public void execute() {
// heavy, error-prone code here
}
}
Instead of subclassing ThreadPoolExecutor, I would provide it with a ThreadFactory instance that creates new Threads and provides them with an UncaughtExceptionHandler
I have made this abstract class to automatically retry network calls if some exception is thrown.
I take care to not retry after InterruptedException &
UnknownHostException.
I retry 5 times. After each failure
I perform an exponential back off, starting from 300ms going upto
1500ms.
public abstract class AutoRetry {
private Object dataToReturn = null;
public Object getDataToReturn() {
return this.dataToReturn;
}
public AutoRetry() {
short retry = -1;
while (retry++ < StaticData.NETWORK_RETRY) {
try {
Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
this.dataToReturn = doWork();
break;
} catch (InterruptedException | UnknownHostException e) {
e.printStackTrace();
this.dataToReturn = null;
return;
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected abstract Object doWork() throws IOException;
}
I use it as follows :
final Object dataAfterWork = new AutoRetry() {
#Override
protected Object doWork() throws IOException {
return; //a network call which returns something
}
}.getDataToReturn();
So is this implementation good/correct ?
EDIT
moved to https://codereview.stackexchange.com/questions/87686
This looks pretty good, but I would split the running task from the retry. Also use generics, don't just throw Object about.
Use a Java 8 lambda and the return of the method:
public static <T> Optional<T> doWithRetry(final Supplier<T> t) {
for (int retry = 0; retry <= StaticData.NETWORK_RETRY; ++retry) {
try {
Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
return Optional.of(t.get());
} catch (InterruptedException | UnknownHostException e) {
LOGGER.log(Level.SEVERE, "Call failed.", e);
return Optional.empty();
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Call failed. Retry.", e);
}
}
LOGGER.log(Level.SEVERE, "Call failed. Retries exceeded.");
return Optional.empty();
}
Also, use a real logger, not printStackTrace...
Usage:
final String data = doWithRetry(() -> {
//do stuff
});
If your lambda needs to throw an exception, you'll need to define your own #FunctionalInterface:
#FunctionalInterface
interface StuffDoer<T> {
T doStuff() throws Exception;
}
And use that in the method signature, you'll need to handle generic Exception.
Pre-Java 8 usage:
final String data = doWithRetry(new StuffDoer<T>() {
#Override
public T get() throws Exception {
return null;
}
});
I'm writing some reconnect logic to periodically attempt to establish a connection to a remote endpoint which went down. Essentially, the code looks like this:
public void establishConnection() {
try {
this.connection = newConnection();
} catch (IOException e) {
// connection failed, try again.
try { Thread.sleep(1000); } catch (InterruptedException e) {};
establishConnection();
}
}
I've solved this general problem with code similar to the above on many occasions, but I feel largely unsatisfied with the result. Is there a design pattern designed for dealing with this issue?
Shameless plug: I have implemented some classes to allow retrying operations. The library is not made available yet, but you may fork it on github.
And a fork exists.
It allows building a Retryer with various flexible strategies. For example:
Retryer retryer =
RetryerBuilder.newBuilder()
.withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECOND))
.withStopStrategy(StopStrategies.stopAfterAttempt(3))
.retryIfExceptionOfType(IOException.class)
.build();
And you can then execute a callable (or several ones) with the Retryer:
retryer.call(new Callable<Void>() {
public Void call() throws IOException {
connection = newConnection();
return null;
}
}
You could try the Idempotent Retry Pattern.
I really like this Java 8 code from this blog and you don't need any extra library on your classpath.
You only need to pass a function to the retry class.
#Slf4j
public class RetryCommand<T> {
private int maxRetries;
RetryCommand(int maxRetries)
{
this.maxRetries = maxRetries;
}
// Takes a function and executes it, if fails, passes the function to the retry command
public T run(Supplier<T> function) {
try {
return function.get();
} catch (Exception e) {
log.error("FAILED - Command failed, will be retried " + maxRetries + " times.");
return retry(function);
}
}
private T retry(Supplier<T> function) throws RuntimeException {
int retryCounter = 0;
while (retryCounter < maxRetries) {
try {
return function.get();
} catch (Exception ex) {
retryCounter++;
log.error("FAILED - Command failed on retry " + retryCounter + " of " + maxRetries, ex);
if (retryCounter >= maxRetries) {
log.error("Max retries exceeded.");
break;
}
}
}
throw new RuntimeException("Command failed on all of " + maxRetries + " retries");
}
}
And to use it:
new RetryCommand<>(5).run(() -> client.getThatThing(id));
Using Failsafe (author here):
RetryPolicy retryPolicy = new RetryPolicy()
.retryOn(IOException.class)
.withMaxRetries(5)
.withDelay(1, TimeUnit.SECONDS);
Failsafe.with(retryPolicy).run(() -> newConnection());
No annotations, no magic, doesn't need to be a Spring app, etc. Just straightforward and simple.
I'm using AOP and Java annotations. There is a ready-made mechanism in jcabi-aspects (I'm a developer):
#RetryOnFailure(attempts = 3, delay = 1, unit = TimeUnit.SECONDS)
public void establishConnection() {
this.connection = newConnection();
}
ps. You can also try RetryScalar from Cactoos.
You can try spring-retry, it has a clean interface and it's easy to use.
Example:
#Retryable(maxAttempts = 4, backoff = #Backoff(delay = 500))
public void establishConnection() {
this.connection = newConnection();
}
In case of exception, it will retry (call) up to 4 times the method establishConnection() with a backoff policy of 500ms
You can also create a wrapper function that just does a loop over the intended operation and when is done just break out of the loop.
public static void main(String[] args) {
retryMySpecialOperation(7);
}
private static void retryMySpecialOperation(int retries) {
for (int i = 1; i <= retries; i++) {
try {
specialOperation();
break;
}
catch (Exception e) {
System.out.println(String.format("Failed operation. Retry %d", i));
}
}
}
private static void specialOperation() throws Exception {
if ((int) (Math.random()*100) % 2 == 0) {
throw new Exception("Operation failed");
}
System.out.println("Operation successful");
}
If you are using java 8, this may helps.
import java.util.function.Supplier;
public class Retrier {
public static <T> Object retry(Supplier<T> function, int retryCount) throws Exception {
while (0<retryCount) {
try {
return function.get();
} catch (Exception e) {
retryCount--;
if(retryCount == 0) {
throw e;
}
}
}
return null;
}
public static void main(String[] args) {
try {
retry(()-> {
System.out.println(5/0);
return null;
}, 5);
} catch (Exception e) {
System.out.println("Exception : " + e.getMessage());
}
}
}
Thanks,
Praveen R.
I'm using retry4j library. Test code example:
public static void main(String[] args) {
Callable<Object> callable = () -> {
doSomething();
return null;
};
RetryConfig config = new RetryConfigBuilder()
.retryOnAnyException()
.withMaxNumberOfTries(3)
.withDelayBetweenTries(5, ChronoUnit.SECONDS)
.withExponentialBackoff()
.build();
new CallExecutorBuilder<>().config(config).build().execute(callable);
}
public static void doSomething() {
System.out.println("Trying to connect");
// some logic
throw new RuntimeException("Disconnected"); // init error
// some logic
}
Here's a another approach to perform the retry. No libraries, no annotations, no extra implementations. Import java.util.concurrent.TimeUnit;
public static void myTestFunc() {
boolean retry = true;
int maxRetries = 5; //max no. of retries to be made
int retries = 1;
int delayBetweenRetries = 5; // duration between each retry (in seconds)
int wait = 1;
do {
try {
this.connection = newConnection();
break;
}
catch (Exception e) {
wait = retries * delayBetweenRetries;
pause(wait);
retries += 1;
if (retries > maxRetries) {
retry = false;
log.error("Task failed on all of " + maxRetries + " retries");
}
}
} while (retry);
}
public static void pause(int seconds) {
long secondsVal = TimeUnit.MILLISECONDS.toMillis(seconds);
try {
Thread.sleep(secondsVal);
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
there is nothing special in retrying at all - take this class as example http://www.docjar.com/html/api/org/springframework/jms/listener/DefaultMessageListenerContainer.java.html
As you can see even spring developers still writing code for retry-ing - line 791...
there is no such special pattern AFAIK..
What i can advice to deal with resources is to take apache commons pool library - check this http://commons.apache.org/pool/apidocs/org/apache/commons/pool/impl/GenericObjectPool.html and visit http://commons.apache.org/pool
I have wrote my custom annotation. Maybe you can use this annotation.
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface RetryOperation {
int retryCount();
int waitSeconds();
}
#Slf4j
#Aspect
#Component
public class RetryOperationAspect {
#Around(value = "#annotation(com.demo.infra.annotation.RetryOperation)")
public Object retryOperation(ProceedingJoinPoint joinPoint) throws Throwable {
Object response = null;
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
RetryOperation annotation = method.getAnnotation(RetryOperation.class);
int retryCount = annotation.retryCount();
int waitSeconds = annotation.waitSeconds();
boolean successful = false;
do {
try {
response = joinPoint.proceed();
successful = true;
} catch (Exception e) {
log.error("Operation failed, retries remaining: {}", retryCount);
retryCount--;
if (retryCount < 0) {
throw e;
}
if (waitSeconds > 0) {
log.warn("Waiting for {} second(s) before next retry", waitSeconds);
Thread.sleep(waitSeconds * 1000L);
}
}
} while (!successful);
return response;
}
}
#RetryOperation(retryCount = 5, waitSeconds = 1)
public void method() {
}
In a java class I have a method that sometimes takes a long time for execution. Maybe it hangs in that method flow. What I want is if the method doesn't complete in specific time, the program should exit from that method and continue with the rest of flow.
Please let me know is there any way to handle this situation.
You must use threads in order to achieve this. Threads are not harmful :) Example below run a piece of code for 10 seconds and then ends it.
public class Test {
public static void main(String args[])
throws InterruptedException {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("0");
method();
}
});
thread.start();
long endTimeMillis = System.currentTimeMillis() + 10000;
while (thread.isAlive()) {
if (System.currentTimeMillis() > endTimeMillis) {
System.out.println("1");
break;
}
try {
System.out.println("2");
Thread.sleep(500);
}
catch (InterruptedException t) {}
}
}
static void method() {
long endTimeMillis = System.currentTimeMillis() + 10000;
while (true) {
// method logic
System.out.println("3");
if (System.currentTimeMillis() > endTimeMillis) {
// do some clean-up
System.out.println("4");
return;
}
}
}
}
Execute the method in a different thread, you can end a thread at anytime.
Based on the above snipplet, I tried creating a glorified spring bean.
Such executor runs the passed limitedRuntimeTask in limited runtimeInMs.
If the task finishes within its time limits, the caller continues normally in execution.
If the limitedRuntimeTask fails to finish in the defined runtimeInMs,
the caller will receive the thread execution back. If a timeBreachedTask was defined,
it will be executed before returning to caller.
public class LimitedRuntimeExecutorImpl {
public void runTaskInLessThanGivenMs(int runtimeInMs, final Callable limitedRuntimeTask, final Callable timeBreachedTask) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
LOGGER.info("Started limitedRuntimeTask");
limitedRuntimeTask.call();
LOGGER.info("Finished limitedRuntimeTask in time");
} catch (Exception e) {
LOGGER.error("LimitedRuntimeTask exception", e);
}
}
});
thread.start();
long endTimeMillis = System.currentTimeMillis() + runtimeInMs;
while (thread.isAlive()) {
if (System.currentTimeMillis() > endTimeMillis) {
LOGGER.warn("LmitedRuntimeTask did not finish in time (" + runtimeInMs + ")ms. It will run in vain.");
if(timeBreachedTask != null ){
try {
LOGGER.info("Executing timeBreachedTask");
timeBreachedTask.call();
LOGGER.info("Finished timeBreachedTask");
} catch (Exception e) {
LOGGER.error("timeBreachedTask exception", e);
}
}
return;
}
try {
Thread.sleep(10);
}
catch (InterruptedException t) {}
}
}
}
I feel the approach in accepted answer is a bit outdated. With Java8, it can be done much simpler.
Say, you have a method
MyResult conjureResult(String param) throws MyException { ... }
then you can do this (keep reading, this is just to show the approach):
private final ExecutorService timeoutExecutorService = Executors.newSingleThreadExecutor();
MyResult conjureResultWithTimeout(String param, int timeoutMs) throws Exception {
Future<MyResult> future = timeoutExecutorService.submit(() -> conjureResult(param));
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
}
of course, throwing Exception is bad, here is the correct extended version with proper error processing, but I suggest you examine it carefully, your may want to do some things differently (logging, returning timeout in extended result etc.):
private final ExecutorService timeoutExecutorService = Executors.newSingleThreadExecutor();
MyResult conjureResultWithTimeout(String param, int timeoutMs) throws MyException {
Future<MyResult> future = timeoutExecutorService.submit(() -> conjureResult(param));
try {
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
//something interrupted, probably your service is shutting down
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} catch (ExecutionException e) {
//error happened while executing conjureResult() - handle it
if (e.getCause() instanceof MyException) {
throw (MyException)e.getCause();
} else {
throw new RuntimeException(e);
}
} catch (TimeoutException e) {
//timeout expired, you may want to do something else here
throw new RuntimeException(e);
}
}