Recursive call in try-catch block to retry N number of times - java

I have a regular, non-static sendMail method which may occasionally fail. I need to catch any errors and retry the method N number of times. I'm not sure I'm doing the right thing, and there's also a compilation error:
public void sendMail(List<String> params) {
try {
//...
static int retrycount = 0; // static not allowed here (but need to keep static var for recursion)
int maxretries = 3;
}
catch (Exception e) {
log.info(e);
// Recursion to retry
sendMail(params);
retrycount++;
}
}
First of all, is recursion from a try/catch block correct? Also, is there a better way to do this?
I can't make the sendMail method static, there are too many references to it in the existing code.

Your retry will never work in the first place because inside every try block you are setting retrycount to 0.
You'd probably be better off throwing the exception instead of catching it. Then using some kind of a while loop till it completes, maybe with a configurable delay between retries. Or if you're using Spring there is the Retryable annotation.
void someMethod(){
int attempts = 0;
while(attemps <= 3){
try {
sendMail(...);
break;
} catch (Exception e){
attempts++;
// Log failed to send mail or something meaningful, maybe add a delay here?
}
}
}
This solution is much cleaner than using recursion as if you wanted to retry many times, eventually you'd get a stack overflow error. It also keeps the responsbility of the sendMail function simple, and avoids adding complicated retry logic to an otherwise simple method.
Also, if you end up having to make other methods retryable in the same fashion then it would be much easier to abstract away the retry logic into some kind of executor service that handles it all.

What if you just wrapped the code in a retry loop:
public void sendMail(List<String> params) {
for (int attempt = 0; attempt < 3; attempt++)
try {
//...
if (<some success condition>)
return;
}
catch (Exception e) {
log.info(e);
}
}

The standard recursive solution would be to add retryCount as a paremeter.
public void sendMail(List<String> params) {
sendMail(params, 0);
}
private void sendMail(List<String> params, int retryCount) {
try {
//...
int maxRetries = 3;
} catch (Exception e) {
log.info(e);
// Recursion to retry
sendMail(params, retryCount+1);
}
}
A loop would be the more idiomatic way of writing this.
public void sendMail(List<String> params) {
int maxTries = 4;
for (int tryCount=0; tryCount<maxTries; ++tryCount) {
try {
//...
break;
} catch (Exception e) {
log.info(e);
// continue to retry
}
}
}
In the spirit of the original question, the retryCount can be kept as a field within an introduced object. It's easiest (if slightly obscure) to do this with an anonymous inner class.
public void sendMail(List<String> params) {
int maxTries = 4;
new Object() {
int tryCount = 0;
public void sendMail() {
try {
//...
} catch (Exception e) {
log.info(e);
// Recursion to retry
if (tryCount < maxTries) {
++tryCount;
sendMail();
}
}
}
}.sendMail();
}

Related

Execute same piece of code in catch clause for all methods in a class

I have a class that has many methods. All the methods throw one exception when data is not ready. In that case, I want to retry the method after a certain interval. So in catch, I need to add retry logic. The same logic i need to add for all methods.
Is there some way/pattern to execute same logic for all catch clause without copy paste
One way I could think of is to write my own Exception class and Throw that exception. And do this retry logic from My Exception class.
Is there any other better way to this?
class MyClass {
public void method1() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method3() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
}
EDIT:
class MyClass {
public void method1(int a, int b) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {a,b};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
Object args[] = null;
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method3(String abcd, int a) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {abcd,a};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public boolean executeLater(String methodName, Object args[]){
//Execute given method with the supplied args
return true;
}
}
Added code that shows what i would be doing in each catch clause
boolean processCompleted=false;
while(!processCompleted){
try{
doProcess();
processCompleted=true;
}catch(Exception e){
Thread.sleep(10000);
}
}
This might give you an idea. It keeps try to call doProcess until it doesn't throw exception. If any exception occurs, waits 10 seconds.
Well, you could extract the whole catch block content to a method and call that one, but this only works if your retry logic is not dependent on the specific method. And it also requires a try-catch in every method.
Instead, use functional programming to shorten it:
public class Playground
{
public static void main(String[] args)
{
new Playground().method2(1, 2);
new Playground().method1();
}
public void method1()
{
tryAndTryAgain(() -> {
// logic 1
System.out.println("no params");
throw new RuntimeException();
});
}
public void method2(int a, int b)
{
tryAndTryAgain(() -> {
// logic 2
System.out.println(a + " " + b);
throw new RuntimeException();
});
}
public static void tryAndTryAgain(Runnable tryThis)
{
try
{
tryThis.run();
}
catch (Exception e)
{
new Timer().schedule(new TimerTask()
{
#Override
public void run()
{
tryAndTryAgain(tryThis);
}
}, 1000);
// existing exception handling logic
}
}
}
The exact structure depends on your specfic implementation, but it should give you an idea how to structure it. The benefit is that all those methods can concentrate on the business logic, and the retry logic and exception handling are done in a util method. And that util method doesn't even need to know anything about parameters, methods, or anything, because all the business logic is contained in the Runnable.

Callable with while loop

I need to provide code that using ExecutorService, Callable and Future will be doing some calculations and printing the partial results until defined condition is reached. First thing that comes to my mind is using while loop. Unfortunately as I understand ExecutorService.get() waits until the task is done, so I cannot do something like (pseudo code):
public Object call() throws Exception {
try {
while(!condition) {
//perform calc
return partialCalculationResult;
}
}
catch(InterruptedException e){
}
}
Could anyone guide me what's the proper direction I should go for?
This here:
while(!condition) {
//perform calc
return partialCalculationResult;
}
indicates a "hole" in your logic. This should probably go like this instead:
while(!condition) {
// perform computation
push intermediate results somewhere
}
return finalResult;
In other words: you are talking about two different elements here. For those "progress" updates you will need some kind of shared data structure; for example a Queue.
You see, in difference to other languages, there is no built-in "generator" concept that would allow you to yield values from a loop; like you can do in python or scala for example.
The dirty option is putting a System.out.println within the while loop.
The cleaner option would be a publish/subscriber pattern, like:
interface Subscriber {
void onPartialResult(double partialResult);
}
class SystemOutSubscriber implements Subscriber{
#Override
void onPartialResult(double partialResult) {
System.out.println(partialResult);
}
}
class YourCalculatorClass {
List<Subscriber> subscribers = ...
public Object call() throws Exception {
while(!condition) {
//perform calc
for(Subscriber s : subscribers) {
s.onPartialResult(partialCalculationResult);
}
}
}
}
You can use Thread.interrupt to stop the thread inside while loop and add remaining result in list
while(!condition){ list.add(addResultHere)
Thread.interrupt(); }
Below is a small example of using an ExecutorService
to push callable tasks. I push them inside a while loop now for the ease of the example, but they can come from anywhere. The callable itself uses the most silly easy example of course where it takes in a number. If the number is below 5, all is good, and we return a text. If not, we return nothing. When the future is evaluated and the result is empty, we shut down the ExecutorService and call it a day. So, this is an example of using an ExecutorService, Callable, and Future to do something at least similar to what I could discern from your explanation.
public ExecutorServiceTest() {
ExecutorService service = Executors.newCachedThreadPool();
int num = 0;
while (true) {
Future<Optional<String>> future = service.submit(new MyCallable(num++));
try {
Optional<String> result = future.get();
if (!result.isPresent()) {
service.shutdown();
break;
}
System.out.println(result.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
service.shutdown();
}
}
}
private static class MyCallable implements Callable<Optional<String>> {
private final int num;
MyCallable(int num) {
this.num = num;
}
#Override
public Optional<String> call() throws Exception {
if (num < 5)
return Optional.of("My number is " + num);
return Optional.empty();
}
}
public static void main(String[] args) {
new ExecutorServiceTest();
}

Locking a method until another is done

I have an external API I have to call that requires a validation token. The app calling the API will be threaded. Also, only 5 concurrent connections are allowed. I'm going to use a fixed thread pool for the connections, but I'm having an issue with figuring out how to handle an expired/invalid token. What I want to do is, when one thread encounters an expired token, prevent the other threads from acquiring the token until it has been refreshed. I'm thinking of using ReentrantLock to do this, but I'm not sure if my implementation is correct.
public static void main(String[] args){
for(int i = 0; i < 100; i++){
new Thread(new LockTest()).start();
}
}
public void testLock(String message) throws InterruptedException{
try{
getToken(message);
/*
* Use token here
*/
Thread.sleep(1000);
Random r = new Random();
int num = r.nextInt((25-0) + 1);
if(num == 1){ //testing only - exception thrown randomly.
throw new Exception("Token Expired!");
}
System.out.println("Message: " + message);
}catch(Exception e){
System.err.println(e.getMessage());
awaitTokenRefresh = true;
refreshToken();
}
}
private void refreshToken() throws InterruptedException {
lock.lock();
try{
System.out.println("Refreshing token...");
Thread.sleep(2000l);
System.out.println("Refreshed!");
awaitTokenRefresh = false;
awaitRefresh.signalAll();
}
finally{
lock.unlock();
}
}
//test use case for salesforce token
private void getToken(String message) throws InterruptedException {
lock.lock();
try{
while(awaitTokenRefresh){
System.out.println(message + " waiting for token refresh...");
awaitRefresh.await();
}
}
finally{
lock.unlock();
}
}
public void run(){
try {
System.out.println("Starting thread...");
testLock(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Just for testing, I've put in some sleeps to mimic work being done. The main thing I don't know about is, when thread A unlocks inside of getToken() thread B enters, but we don't know if the token is invalid yet. So B could actually be getting a bad token that A has to find. Is there a good way to handle this? Or is the idea of using locks completely wrong?
The first thing I notice is that your code is not properly synchronized. The exception handler in testLock() modifies shared variable awaitTokenRefresh at a point where that write is not ordered relative to other threads reading its value in getToken().
The main thing I don't know about is, when thread A unlocks inside of getToken() thread B enters, but we don't know if the token is invalid yet. So B could actually be getting a bad token that A has to find. Is there a good way to handle this? Or is the idea of using locks completely wrong?
I guess what you really want to avoid is unnecessary token refreshes when the current token becomes invalid. Exactly one thread should refresh it; the others should simply wait for the refresh and then continue about their business. The problem with your approach is that the threads have no good way to determine whether they are the first to detect the expiration, and so should take responsibility for refreshing. And indeed that makes sense, because the concept of which thread does anything first is not always well defined in a multithreaded application.
Whether you use locks vs. synchronization is an implementation detail of relatively minor consequence. The key is that you must have some shared state that tells threads whether the token they propose to refresh is in fact still current at all. I might implement it something like this:
public class MyClass {
private Object token = null;
private final Object tokenMonitor = new Object();
// ...
private Object getToken() {
synchronized (tokenMonitor) {
if (token == null) {
return refreshToken(null);
} else {
return token;
}
}
}
private Object refreshToken(Object oldToken) {
synchronized (tokenMonitor) {
if (token == oldToken) { // test reference equality
token = methodToPerformARefreshAndGenerateANewToken();
}
return token;
}
}
// ...
}
The idea there is when it tries to refresh the token, each thread specifies which token it is trying to refresh. A refresh is performed only if that is in fact the current token, and either way, the current token is returned.
You could use a ReentrantLock in place of my tokenMonitor, with locking and unlocking instead of synchronized blocks, but I much prefer plain synchronization when the scope is well contained, as in this case. Among other things, it's safer -- when you leave a synchronized block, you leave it; there is no possibility of failing to release the relevant monitor. The same cannot be said for lock objects.
This actually looks a problem that can be solved with versioning:
public class LockTest {
private int currentVersion = -1;
private Object token = null;
private synchronized int refreshToken(int requestorVersion) {
if (requestorVersion == currentVersion) {
try {
//do the actual refresh
Thread.sleep(1000);
token = new Object();
currentVersion++;
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
return currentVersion;
}
public VersionedToken takeToken() {
if (currentVersion == -1) {
refreshToken(-1);
}
return new VersionedToken(currentVersion);
}
public class VersionedToken {
private int version;
public VersionedToken(int version) {
this.version = version;
}
private void refresh() {
version = refreshToken(version);
}
private Object getToken() {
return token;
}
}
public static void main(String[] args) {
LockTest t = new LockTest();
for (int i = 0; i < 5; i++) {
new Thread(() -> {
VersionedToken vtoken = t.takeToken();
Object token = vtoken.getToken();
try {
//do something with the token
}catch (Exception ex) {
//if token went bad - just refresh it and continue to work with it afterwords
vtoken.refresh();
token = vtoken.getToken();
}
}).start();
}
}
}

Optional exception catching

Is it possible to make an exception that is optional to be caught?
In other words, an exception that can either:
be caught in a try-catch block
or skipped if no try-catch block exists for it
To visualize, I have a ReportedException, which is just a plain subclass of RuntimeException, and want to be able to catch it when it's needed:
try
{
hideWindow();
}
catch (ReportedException ex)
{
// Window could not be hidden.
// Exception has already been caught and logged by parseInput(),
// and now we're going to do something more.
printAdditionalErrorMessage();
}
Note: I edited the above example to better fit my question.
or skip catching if the result is irrelevant:
hideWindow(); // We don't care if there was an error or not.
openAnotherWindow();
I know I can leave the catch block empty and have the same thing as above, but I use ReportedException very often and it would make my code highly unreadable.
If it's impossible (I suspect it is), what alternative/walkaround would you recommend?
P.S. The method names used in the examples are just foo's and bar's.
EDIT: I know I don't need to catch RuntimeExceptions. What I want is to ignore them if they occur.
Exceptions should be used for exceptional situations.
From your example, if the window not being hidden is a typical event, it shouldn't throw an exception. If that is your function, then use a return value to indicate whether it was successful instead of throwing an exception. Then you can safely ignore the return value when you don't care if it succeeded or not.
If you do not have control over that method, then you can wrap it in another method that catches the exception and turns it into a return value. E.g.
private boolean tryHideWindow() {
try {
hideWindow();
}
catch (ReportedException ex) {
return false;
}
return true;
}
If you need some parameters of the exception to determine what to do, then you could return the exception instead.
private static class MyReturnType {
private final Throwable thrown;
private final OrigRtnType returnVal;
public MyReturnType(Throwable thrown) {
this.thrown = thrown;
this.returnVal = null;
}
public MyReturnType(OrigRtnType returnVal) {
this.thrown = null;
this.returnVal = returnVal
}
public boolean wasExceptionThrown() {
return thrown != null;
}
}
private MyReturnType tryHideWindow() {
try {
OrigRtnType returnVal = hideWindow();
}
catch (ReportedException ex) {
return new MyReturnType(ex);
}
return new MyReturnType(returnVal);
}
This is an answer to your question, but it is not necessarily a good idea. As others will doubless comment, using exceptions for program flow is less than ideal.
I'm a little fuzzy on how to use ThreadLocal (and there are apt to be some other tupos), but something like this:
public class IgnorableException {
static class DontIgnoreCount {
int count;
}
// Thread local variable containing each thread's ID
private static final ThreadLocal<DontIgnoreCount> dontIgnoreCount =
new ThreadLocal<DontIgnoreCount>();
static void incrementDontIgnore() {
DontIgnoreCount counter = dontIgnoreCount.get();
if (counter == null) {
counter = new DontIgnoreCount();
dontIgnoreCount.set(counter);
}
counter.count++;
}
static void decrementDontIgnore() {
DontIgnoreCount counter = dontIgnoreCount.get();
// Must not be null here
counter.count--;
static bool shouldSignal() {
DontIgnoreCount counter = dontIgnoreCount.get();
return counter.count > 0;
}
}
To use, invoke DontIgnoreCount.incrementIgnoreCount() early in try range, and DontIgnoreCount.decrementIgnoreCount() late in finally range.
When signalling an exception that follows this protocol, only signal it if shouldSignal returns true.
void iWannaCatchException() {
try {
IgnornableException.incrementDontIgnore();
int x = someOptionallySignallingMethod();
}
catch (...) {
...
}
finally {
IgnorableException.decrementDontIgnore();
}
}
void iDontWannaCatchException() {
int x = someOptionallySignallingMethod();
}
int someOptionallySignallingMethod() {
if (somethingBad) {
if (IgnorableException.shouldSignal()) {
throw new BadException();
}
}
return 42;
}
Note that not shown above are any throws clauses you'd have to add to keep the compiler happy. This mechanism would not remove the need for those.
You could also inplement a delegate/observer scheme, replacing the simple counter with a stack of observer objects, and pass a message to the observer vs throwing the exception. But this, by itself (without coupled exceptions/try ranges) would not allow blowing away the stack to the appropriate recovery point.
It sounds like you want to use exceptions for flow control, rather than for reporting truly exceptional cases.
Using exceptions for flow control is typically frowned upon. The common approach is to return a success/failure indication as the return value of the function.
You can use something like this:
try{
hideWindow();
}catch (ReportedException ex){
// ingore
}catch (NullPointerException ex){
killWindow();
}finally {
//to do something more.
}

Continue from the next line after getting exception

I want to continue with the next line from which error generated,
try{
statement A;
statement B;
statement C;
}
catch(NullPointerException NPE){.....}
Now assume that my statement A throws exception so I want to skip that and continue with B. Don't give my suggestion to put in catch/finally block or any other solution. I just want to know is this possible to skip and continue with next statement?
Yes, it is possible without the finally block.
try{
statement A;
}
catch(NullPointerException NPE){.....}
try{
statement B;
}
catch(NullPointerException NPE){.....}
try{
statement C;
}
catch(NullPointerException NPE){.....}
On the side note, I don't really think this is nice. If you managed to come to the point where you need this kind of flow control, you need to take a step back and rethink your code design.
It is not possible to execute statement B if A throws exception. One way is seperately try/catch block and other way is put other lines into finally block.
If your statements are similar and can be paramerized, use a loop:
for (int i = 0; i < statementCount; i++) {
try {
/** do what you need */
} catch(Exception e) {
}
}
or put it in separate method if it needs more parameters:
public static void main(String[] args) {
for (int i = 0; i < statementCount; i++) {
}
execute(params);
}
public void execute(Object... objects) {
try {
doSomthing(objects[0], objects[1]);
} catch(Exception e) {
}
}
If statements are abolutely different, Java 8 provides interesting solutions: method references and lambdas. So you can play arround with somthing like this:
public static void main(String[] args) {
execute(someObject, YourClass::method);
}
public void execute(Object param, Function<Object, Void> function) {
try {
function.apply(param);
} catch(Exception e) {
}
}
Like darijan already mentioned you could put every single statement into an own try-catch. Or if you know what may cause the exception you can simply check it befor you execute your statements
try{
if(parameterForStatementA != null) {
statementA;
}
if(parameterForStatementB != null) {
statementB;
}
if(parameterForStatementC != null) {
statementC;
}
} catch(Exception e) {
// something unexpected happened
}
Verifying parameters is usually more efficient than catching thrown exceptions

Categories