0

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

VidhyaRani
  • 33
  • 5
  • Well if you really want the same for each one, which is abit redundant because you should just have specific Exceptions so you can diagnose problems, just extract the method and then call it each time instead. – OcelotcR Jan 05 '18 at 11:03
  • So i will have to pass my method's args and pass it to new method. And after some interval it will call the original method. In all the catch clause i need to add passing method name and args. Is there some way that i can do without having to do this in all catch clause – VidhyaRani Jan 05 '18 at 11:11

2 Answers2

0
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.

yılmaz
  • 1,818
  • 13
  • 15
0

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.

Malte Hartwig
  • 4,477
  • 2
  • 14
  • 30
  • This is how i am doing it. In the seperate runnable, I am running this method of tryAgain. Also I cant just use tryAndTryAgain as i need to keep chcking until i succeed. So I am using Timer's scheduleAtFixedRate with interval. But for that runnable i need to pass my method details. Which i need to do in every catch. I was wondering if there is some pattern that i can use instead of changing existing catch clause – VidhyaRani Jan 05 '18 at 13:46
  • Hmm, I see. Would you be able to fill one or two of your methods with some more detailed code? I don't quite understand what you mean by "pass my method details". – Malte Hartwig Jan 05 '18 at 22:38
  • @VidhyaRani I changed `tryAndTryAgain` to continue trying forever. About passing of parameters: It should work just fine. The advantage of using a `Runnable` here is that `tryAndTryAgain` doesn't need to know because the method logic **and** the parameters are all captured in the lambda. Copy my example, call `method2`, and throw an exception after the `sysout` . It should print the params forever. To add some delay use `Thread.sleep()` or look [at a solution that doesn't block the main thread](https://stackoverflow.com/questions/2258066/java-run-a-function-after-a-specific-number-of-seconds) – Malte Hartwig Jan 08 '18 at 10:43
  • Thanks for this code. For delay i am doing schedule for every 5 mins with this - Timer().scheduleAtFixedRate() – VidhyaRani Jan 08 '18 at 10:49
  • Perfect! I added an example with the `Timer` to my example as well. If you use `scheduleAtFixedRate`, I guess you have to stop it manually if it is succesful. Using the normal `schedule` only executes it once, leaving you in control. – Malte Hartwig Jan 08 '18 at 10:51
  • Yes I am maintaining a queue to see which all requests are pending, so after executing that method, I am removing from queue. In the example i still need to pass arguments inside tryAndTryAgain of each method right ? – VidhyaRani Jan 08 '18 at 10:53
  • 1
    No, you do not have to care about the arguments anymore inside `tryAndTryAgain`. Everything the business logic needs to know is already inside `tryThis`. It is called ["capturing of variables"](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#accessing-local-variables). I have extended my code to a full class. You can copy the code as is. It will print "no params" and "1 2" forever when you run it. – Malte Hartwig Jan 08 '18 at 10:57
  • I will try this. Thanks – VidhyaRani Jan 08 '18 at 11:04