java - issue with exceptions - java

I'm having some trouble getting my code to compile.
This is a method that uses the class Value to save text to a file
public void saveEventsToFile() throws Exception {
String tmp = getEventsAsString();
value = Value.makeString(tmp);
Value.saveFile(value, "\\events" + "\\" + "YEAR" + "\\" + months[MONTH] + "\\" + DAY);
}
and this is part of a constructor of another object. I've got an actionlistener on a button (OK) and when that button is pressed, I want to call the saveEventsToFile method.
OK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int h, m;
h = (Integer) hourSpinner.getValue();
m = (Integer) minuteSpinner.getValue();
parentPanel.createNewEvent(parentPanel.selectedBox, parentWindow, textPane.getText(), h, m);
parentPanel.selectedBox.saveEventsToFile();
dispose();
}
});
If I add throws Exception on actionPerformed my code does not compile, and without it I get "Unhandled exception" error on the arentPanel.selectedBox.saveEventsToFile(); line
How could I get this to compile? I've not had much experience with exceptions.

As donfuxx said:
OK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int h, m;
h = (Integer) hourSpinner.getValue();
m = (Integer) minuteSpinner.getValue();
parentPanel.createNewEvent(parentPanel.selectedBox, parentWindow, textPane.getText(), h, m);
try {
parentPanel.selectedBox.saveEventsToFile();
} catch (ExeptionThaIsThrownBySaveEventsMethod e) {
// display error
}
dispose();
}
});

First of all if you do not use any particular element of ActionEvent, move logic of the method in the body of class you have.
OK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Integer h = (Integer) hourSpinner.getValue());
Integer m = (Integer) minuteSpinner.getValue();
saveEventsToFile(h,m)
dispose();
}
});
private void saveEventsToFile(Integer hour, Integer minute) {
if(hour == null || minute == null) {
throw new IllegalArgumentException("The parameters must not be null.")
}
parentPanel.createNewEvent(parentPanel.selectedBox, parentWindow, textPane.getText(), h,m);
try {
parentPanel.selectedBox.saveEventsToFile();
}catch(ExeptionThaIsThrownBySaveEventsMethod e) {
throw new IllegalStateException(e);
}
}
The things to remember here is that you should avoid to catch Exception as you may catch more than expected. This is important because after some exceptions application can proceed in other just need to be closed. In case the save cased an exception is might be possible that user can do something to retry the operation. In case the application must be close as can not longer operate you change use an unchecked (Runtime) Exception.

Related

Pause in Java + end method

I wanted to say for a school project in Greenfoot, that if a rover encounters a system error, it should output this and then wait a short time and then terminate the current method. However, the pause is marked with the following error code: unreported exception java. lang. InterupptedException; must be cought or declared to be thrown, as I am very new to Java I have no idea what to change. Besides, he should then end the method, but with the current command the whole scenario is ended.
"
public Rover (String pname, char pfrequenz, int penergie)
{
energie = penergie;
name = pname;
temp = 15 ;
distance = 0;
systemcheck = true;
frequenz = pfrequenz ;
}
public void check()
{
if (markeVorhanden())
{
energie = energie + 100;
}
if (energie == 0){
systemcheck = false;
}
if (systemcheck = false){
nachricht("System Failure");
java.util.concurrent.TimeUnit.SECONDS.sleep(2);
System.exit(0);
}
if (distance > 100){
nachricht("Congrats you have passed 100");
}
anzeige.anzeigen("Akku: "+energie+ " %");
}
Try this
import java.io.*;
public class Yourclass{
public void Rover (String pname, char pfrequenz, int penergie)
{
Integer energie = penergie;
String name = pname;
Integer temp = 15 ;
Integer distance = 0;
boolean systemcheck = true;
char frequenz = pfrequenz ;
}
public void check() throws IOException
{
if (markeVorhanden())
{
energie = energie + 100;
}
if (energie == 0){
systemcheck = false;
}
if (systemcheck = false){
nachricht("System Failure");
throw new IOException("sorry device error");
}
if (distance > 100){
nachricht("Congrats you have passed 100");
}
anzeige.anzeigen("Akku: "+energie+ " %");
}
public static void main(String []args) throws InterruptedException
{
Yourclass demo= new Yourclass();
System.out.println("Hello World");
try{
demo.check();
}
catch(Exception e)
{
Thread.sleep(2000);
System.out.println("function stopped");
}
}
}
You will have to read up on exception handling in Java. The sleep method may get interrupted and may thus raise an InterruptedException. You can either forward this exception or ignore it.
To forward the exception, declare the function a
public void check() throws InterruptedException
but then callers of this function will have to deal with that potential exception. Since interrupted does not look a severe problem here (the sleep is just a bit shorter than the two seconds), it may be fine to ignore the exception:
try { java.util.concurrent.TimeUnit.SECONDS.sleep(2); }
catch (InterruptedException ignored) {}
In order to just return from the current method use return instead of System.exit()

JTextfield - String split and intparse

I am working on a turtle graphics project and I'm attempting to retrieve a user input from a jtextfield (commField) which should be like: ' forward 100 ' I've attempted to do a string split and intparse however when the program is run, even when a correct command is entered it will go to the message error dialogue. After a few hours of turning the cogs in my brain I'm struggling to figure out why and so am asking for any help. If more of my code is needed for an answer that is fine, perhaps I'm focusing on the wrong thing.
commField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
else if(commField.getText().contains("forward")) {
String cForward = commField.toString();
String[] cForwardArray = cForward.split("\\s+");
try {
int distance = Integer.parseInt(cForwardArray[1]);
graphicsPanel.forward(distance);
}
catch (Exception ev) {
JOptionPane.showMessageDialog(textArea,
"Invaild or missing parameter, check the help section\n"
+ "for more information on Commands");
}
}
else if(commField.getText().contains("backward")) {
String cBackward = commField.toString();
String[] cBackwardArray = cBackward.split("\\s+");
try {
int distance = Integer.parseInt(cBackwardArray[1]);
graphicsPanel.backward(distance);
graphicsPanel.repaint();
}
catch (Exception ev) {
JOptionPane.showMessageDialog(textArea,
"Invaild or missing parameter, check the help section\n"
+ "for more information on Commands");
}
}
}
});
Below is the full code block for those who want it:
commField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(commField.getText().contains("penup")) {
graphicsPanel.penUp();
}
else if(commField.getText().contains("pendown")) {
graphicsPanel.penDown();
}
else if(commField.getText().contains("turnright")) {
graphicsPanel.turnRight();
}
else if(commField.getText().contains("turnleft")) {
graphicsPanel.turnLeft();
}
else if(commField.getText().contains("forward")) {
String cForward = commField.toString();
String[] cForwardArray = cForward.split("\\s+");
try {
int distance = Integer.parseInt(cForwardArray[1]);
graphicsPanel.forward(distance);
System.out.println(commField);
}
catch (Exception ev) {
JOptionPane.showMessageDialog(textArea,
"Invaild or missing parameter, check the help section\n"
+ "for more information on Commands");
}
}
else if(commField.getText().contains("backward")) {
String cBackward = commField.toString();
String[] cBackwardArray = cBackward.split("\\s+");
try {
int distance = Integer.parseInt(cBackwardArray[1]);
graphicsPanel.backward(distance);
graphicsPanel.repaint();
}
catch (Exception ev) {
JOptionPane.showMessageDialog(textArea,
"Invaild or missing parameter, check the help section\n"
+ "for more information on Commands");
}
}
else if(commField.getText().contains("black")) {
graphicsPanel.black(Color.black);
}
else if(commField.getText().contains("green")) {
graphicsPanel.green(Color.green);
}
else if(commField.getText().contains("red")) {
graphicsPanel.red(Color.red);
}
else if(commField.getText().contains("reset")) {
graphicsPanel.clear();
}
else {
JOptionPane.showMessageDialog(textArea, "Invalid command, try again");
}
commField.setText("");
graphicsPanel.repaint();
}
});
Line of interest:
String cForward = commField.toString();
JTextField.toString() does not return the content of the JTextField.
I checked my java 8 sources and found the following:
public String toString() {
return getClass().getName() + '[' + paramString() + ']';
}
However, the toString() method is intended to be a debugging utility. Unless its behavior is explicitly documented it is not recommended to rely on it programmatically.
For retrieving its text content, JTextField provides a separate method: JTextComponent#getText(). The line should therefore be changed to:
String cForward = commField.getText();

Java: try-catch error, must be caught to be thrown

I have tried to create a method to load files but it is not working the way it should. Why do I get this error? Is there a problem with my try-catch block?
NamnMetod.java:157: error: unreported exception InterruptedException; must be caught or declared to be thrown
EventQueue.invokeAndWait(new Runnable() {
This is my code:
public static void hämtaFrånText() {
EventQueue.invokeAndWait(new Runnable() {
#Override
public void run() {
try {
String aktuellMapp = System.getProperty("user.dir");
JFileChooser fc = new JFileChooser(aktuellMapp);
int resultat = fc.showOpenDialog(null);
if (resultat != JFileChooser.APPROVE_OPTION) {
JOptionPane.showMessageDialog(null, "Ingen fil valdes!");
System.exit(0);
}
String fil = fc.getSelectedFile().getAbsolutePath();
String[] namn = new String[3];
String output ="";
BufferedReader inFil = new BufferedReader(new FileReader(fil));
String rad = inFil.readLine();
int antal = 0;
while(rad != null) {
namn[antal] = rad;
rad = inFil.readLine();
antal++;
}
inFil.close();
}catch(FileNotFoundException e1) {
JOptionPane.showMessageDialog(null,"Filen hittades inte!");
}
catch(IOException e2) {
JOptionPane.showMessageDialog(null,"Det misslyckades");
}
}
});
}
It's got nothing to do with the try/catch block in the run() method. The problem is with the method that calls invokeAndWait... EventQueue.invokeAndWait() is declared to throw InterruptedException, which is a checked exception... so either you need another try/catch block (around the call) or your hämtaFrånText method should declare that it can throw InterruptedException too.
As per the JavaDoc (emphasis my own):
public static void invokeAndWait(Runnable runnable)
throws InterruptedException,
InvocationTargetException
The invokeAndWait can throw two types of exception. In your method, you do not have a try-catch segment to cater with these errors, thus your method must specify that it can potentially throw these exceptions itself because they are not handled internally.
You would need to either:
Add throws InterruptedException to your method signature OR
Have a try-catch block which envelopes EventQueue.invokeAndWait(new Runnable() {... so that any exceptions can be dealt with.
Defining an anonymous class:
new Runnable() {
#Override public void run() { ... }
};
is basically a shorthand for defining a local class:
class MyAnonymousRunnable implements Runnable {
#Override public void run() { ... }
}
and then creating an instance of that class:
new MyAnonymousRunnable();
As such, your code could be written as:
EventQueue.invokeAndWait(new MyAnonymousRunnable());
provided you have a suitable definition of MyAnonymousRunnable.
If you did this, you'd get exactly the same compilation error on that line. However, you know how to catch an exception in code without an anonymous class:
try {
EventQueue.invokeAndWait(new MyAnonymousRunnable());
} catch (InterruptedException e) {
Thread.currentThread().interrrupt();
// Do whatever to handle the exception.
}
So there is no real difference if you define the class anonymously:
try {
EventQueue.invokeAndWait(new Runnable() {
#Override public void run() { ... }
});
} catch (InterruptedException e) {
Thread.currentThread().interrrupt();
// Do whatever to handle the exception.
}
You could envelope your entire EventQueue.invokeAndWait(new Runnable(){...}); code inside another try-catch block like so:
public static void hämtaFrånText() {
try {
EventQueue.invokeAndWait(new Runnable() {
#Override
public void run() {
try {
String aktuellMapp = System.getProperty("user.dir");
JFileChooser fc = new JFileChooser(aktuellMapp);
int resultat = fc.showOpenDialog(null);
if (resultat != JFileChooser.APPROVE_OPTION) {
JOptionPane.showMessageDialog(null, "Ingen fil valdes!");
System.exit(0);
}
String fil = fc.getSelectedFile().getAbsolutePath();
String[] namn = new String[3];
String output = "";
BufferedReader inFil = new BufferedReader(new FileReader(fil));
String rad = inFil.readLine();
int antal = 0;
while(rad != null) {
namn[antal] = rad;
rad = inFil.readLine();
antal++;
}
inFil.close();
} catch(FileNotFoundException e1) {
JOptionPane.showMessageDialog(null, "Filen hittades inte!");
} catch(IOException e2) {
JOptionPane.showMessageDialog(null, "Det misslyckades");
}
}
});
} catch(InterruptedException e3) {
// your catch code here
}
}

How to convert this run time exception into checked exception?

Hi how to convert this run time exception into checked exception this method has to force the class user to handle the exception specified in the method signature. This exceptions are unchecked exception.
public class Exception {
int a, b, c;
void set(String data[]) throws NumberFormatException, ArrayIndexOutOfBoundsException {
a = Integer.parseInt(data[0]);//convert the string into int. eg1.("12" ---> 12) eg2.("df23" ---> fail)
b = Integer.parseInt(data[1]);
c = 0;
}
void divide() throws ArithmeticException {
c = a / b;
}
void disp() {
System.out.println(a + " / " + b + " = " + c);
}
}
Just wrap it into an checked exception applicable in your context
throw new Exception(runtimeException);
I have used Exception but you can use your own CustomException which extends Exception and wrap the RuntimeException into it.
TIP:
Also make sure you want to use checked exception for similar scenarios. Runtime exceptions are kept runtime for a reason that the situation cannot be recovered from. So make sure that the runtime exception that you are wrapping will be helpful as a checked exception. Caller should be able to derive some value from it.
Secondly as I told in the TIP that caller will in no way be able to recover from ArrayIndexOutOfBoundsException, it will not serve any purpose to the caller.
EDIT:
I am showing you the demo but I am no way in favor of doing so. Firstly the ArrayIndexOutOfBoundsException should never be thrown, you should take care that array does not go out of index in your code.
void set(String data[]) throws Exception{
try{
}catch(NumberFormatException ex){
throw new Exception(ex);
}catch(ArrayIndexOutOfBoundsException aiobe){
throw new Exception(aiobe);
}
}
Make your Exception class extend a checked exception.
You can catch exception in block rather than let it throw up:
public class Exception
{
int a, b, c;
void set(String data[])
{
try
{
a = Integer.parseInt(data[0]);
b = Integer.parseInt(data[1]);
c = 0;
}
catch(NumberFormatException nfe)
{}
catch(ArrayIndexOutOfBoundsException aiofbe)
{}
catch(Exception e)
{}
}
void divide()
{
try
{
c = a / b;
}
catch(NumberFormatException nfe)
{}
catch(Exception e)
{}
}
void disp()
{
System.out.println(a + " / " + b + " = " + c);
}
}
What do you mean? You want extends your class from RuntimeException, or what?
If you want catch RuntimeException in this block:
void set(String data[]) throws NumberFormatException, ArrayIndexOutOfBoundsException {
a = Integer.parseInt(data[0]);//convert the string into int. eg1.("12" ---> 12) eg2.("df23" ---> fail)
b = Integer.parseInt(data[1]);
c = 0;
}
so use try/catch construction, like that
try{
a = Integer.parseInt(data[0]);//convert the string into int. eg1.("12" ---> 12) eg2.("df23" ---> fail)
b = Integer.parseInt(data[1]);
c = 0;
} catch (RuntimeException e) {
throw MyCoolCheckedExceptin(e.getMessage, e);
}
You can catch the RunTime exception if you want to convert it into Checked exception. In the following code snippet if set() is being used, then it will forced user to do checked exception.
void set(String data[]) throws Exception {
try {
a = Integer.parseInt(data[0]);//convert the string into int. eg1.("12" ---> 12) eg2.("df23" ---> fail)
b = Integer.parseInt(data[1]);
c = 0;
} catch (NumberFormatException e) {
throw new Exception();
}
}
Wrap it in your own defined Exception
class MyOwnArithmeticException extends Exception {
public MyOwnArithmeticException(Throwable cause) {
super(cause);
}
//implement other constructors too
}
Then change your method to
void divide() throws MyOwnArithmeticException {
try {
c = a / b;
} catch (ArithmeticException e) {
throw new MyOwnArithmeticException(e);
}
}

How do you implement a re-try-catch?

Try-catch is meant to help in the exception handling. This means somehow that it will help our system to be more robust: try to recover from an unexpected event.
We suspect something might happen when executing and instruction (sending a message), so it gets enclosed in the try. If that something nearly unexpected happens, we can do something: we write the catch. I don't think we called to just log the exception. I thing the catch block is meant to give us the opportunity of recovering from the error.
Now, let's say we recover from the error because we could fix what was wrong. It could be super nice to do a re-try:
try{ some_instruction(); }
catch (NearlyUnexpectedException e){
fix_the_problem();
retry;
}
This would quickly fall in the eternal loop, but let's say that the fix_the_problem returns true, then we retry. Given that there is no such thing in Java, how would YOU solve this problem? What would be your best design code for solving this?
This is like a philosophical question, given that I already know what I'm asking for is not directly supported by Java.
You need to enclose your try-catch inside a while loop like this: -
int count = 0;
int maxTries = 3;
while(true) {
try {
// Some Code
// break out of loop, or return, on success
} catch (SomeException e) {
// handle exception
if (++count == maxTries) throw e;
}
}
I have taken count and maxTries to avoid running into an infinite loop, in case the exception keeps on occurring in your try block.
Obligatory "enterprisy" solution:
public abstract class Operation {
abstract public void doIt();
public void handleException(Exception cause) {
//default impl: do nothing, log the exception, etc.
}
}
public class OperationHelper {
public static void doWithRetry(int maxAttempts, Operation operation) {
for (int count = 0; count < maxAttempts; count++) {
try {
operation.doIt();
count = maxAttempts; //don't retry
} catch (Exception e) {
operation.handleException(e);
}
}
}
}
And to call:
OperationHelper.doWithRetry(5, new Operation() {
#Override public void doIt() {
//do some stuff
}
#Override public void handleException(Exception cause) {
//recover from the Exception
}
});
As usual, the best design depends on the particular circumstances. Usually though, I write something like:
for (int retries = 0;; retries++) {
try {
return doSomething();
} catch (SomeException e) {
if (retries < 6) {
continue;
} else {
throw e;
}
}
}
You can use AOP and Java annotations from jcabi-aspects (I'm a developer):
#RetryOnFailure(attempts = 3, delay = 5)
public String load(URL url) {
return url.openConnection().getContent();
}
You could also use #Loggable and #LogException annotations.
Although try/catch into while is well-known and good strategy I want to suggest you recursive call:
void retry(int i, int limit) {
try {
} catch (SomeException e) {
// handle exception
if (i >= limit) {
throw e; // variant: wrap the exception, e.g. throw new RuntimeException(e);
}
retry(i++, limit);
}
}
Spring AOP and annotation based solution:
Usage (#RetryOperation is our custom annotation for the job):
#RetryOperation(retryCount = 1, waitSeconds = 10)
boolean someMethod() throws Exception {
}
We'll need two things to accomplish this: 1. an annotation interface, and 2. a spring aspect. Here's one way to implement these:
The Annotation Interface:
import java.lang.annotation.*;
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface RetryOperation {
int retryCount();
int waitSeconds();
}
The Spring Aspect:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
#Aspect #Component
public class RetryAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(RetryAspect.class);
#Around(value = "#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 ex) {
LOGGER.info("Operation failed, retries remaining: {}", retryCount);
retryCount--;
if (retryCount < 0) {
throw ex;
}
if (waitSeconds > 0) {
LOGGER.info("Waiting for {} second(s) before next retry", waitSeconds);
Thread.sleep(waitSeconds * 1000l);
}
}
} while (!successful);
return response;
}
}
Most of these answers are essentially the same. Mine is also, but this is the form I like
boolean completed = false;
Throwable lastException = null;
for (int tryCount=0; tryCount < config.MAX_SOME_OPERATION_RETRIES; tryCount++)
{
try {
completed = some_operation();
break;
}
catch (UnlikelyException e) {
lastException = e;
fix_the_problem();
}
}
if (!completed) {
reportError(lastException);
}
Use a while loop with local status flag. Initialize the flag as false and set it to true when operation is successful e.g. below:
boolean success = false;
while(!success){
try{
some_instruction();
success = true;
} catch (NearlyUnexpectedException e){
fix_the_problem();
}
}
This will keep retrying until its successful.
If you want to retry only certain number of times then use a counter as well:
boolean success = false;
int count = 0, MAX_TRIES = 10;
while(!success && count++ < MAX_TRIES){
try{
some_instruction();
success = true;
} catch (NearlyUnexpectedException e){
fix_the_problem();
}
}
if(!success){
//It wasn't successful after 10 retries
}
This will try max 10 times if not successful until then an will exit if its successful before hand.
This is an old question but a solution is still relevant. Here is my generic solution in Java 8 without using any third party library:
public interface RetryConsumer<T> {
T evaluate() throws Throwable;
}
public interface RetryPredicate<T> {
boolean shouldRetry(T t);
}
public class RetryOperation<T> {
private RetryConsumer<T> retryConsumer;
private int noOfRetry;
private int delayInterval;
private TimeUnit timeUnit;
private RetryPredicate<T> retryPredicate;
private List<Class<? extends Throwable>> exceptionList;
public static class OperationBuilder<T> {
private RetryConsumer<T> iRetryConsumer;
private int iNoOfRetry;
private int iDelayInterval;
private TimeUnit iTimeUnit;
private RetryPredicate<T> iRetryPredicate;
private Class<? extends Throwable>[] exceptionClasses;
private OperationBuilder() {
}
public OperationBuilder<T> retryConsumer(final RetryConsumer<T> retryConsumer) {
this.iRetryConsumer = retryConsumer;
return this;
}
public OperationBuilder<T> noOfRetry(final int noOfRetry) {
this.iNoOfRetry = noOfRetry;
return this;
}
public OperationBuilder<T> delayInterval(final int delayInterval, final TimeUnit timeUnit) {
this.iDelayInterval = delayInterval;
this.iTimeUnit = timeUnit;
return this;
}
public OperationBuilder<T> retryPredicate(final RetryPredicate<T> retryPredicate) {
this.iRetryPredicate = retryPredicate;
return this;
}
#SafeVarargs
public final OperationBuilder<T> retryOn(final Class<? extends Throwable>... exceptionClasses) {
this.exceptionClasses = exceptionClasses;
return this;
}
public RetryOperation<T> build() {
if (Objects.isNull(iRetryConsumer)) {
throw new RuntimeException("'#retryConsumer:RetryConsumer<T>' not set");
}
List<Class<? extends Throwable>> exceptionList = new ArrayList<>();
if (Objects.nonNull(exceptionClasses) && exceptionClasses.length > 0) {
exceptionList = Arrays.asList(exceptionClasses);
}
iNoOfRetry = iNoOfRetry == 0 ? 1 : 0;
iTimeUnit = Objects.isNull(iTimeUnit) ? TimeUnit.MILLISECONDS : iTimeUnit;
return new RetryOperation<>(iRetryConsumer, iNoOfRetry, iDelayInterval, iTimeUnit, iRetryPredicate, exceptionList);
}
}
public static <T> OperationBuilder<T> newBuilder() {
return new OperationBuilder<>();
}
private RetryOperation(RetryConsumer<T> retryConsumer, int noOfRetry, int delayInterval, TimeUnit timeUnit,
RetryPredicate<T> retryPredicate, List<Class<? extends Throwable>> exceptionList) {
this.retryConsumer = retryConsumer;
this.noOfRetry = noOfRetry;
this.delayInterval = delayInterval;
this.timeUnit = timeUnit;
this.retryPredicate = retryPredicate;
this.exceptionList = exceptionList;
}
public T retry() throws Throwable {
T result = null;
int retries = 0;
while (retries < noOfRetry) {
try {
result = retryConsumer.evaluate();
if (Objects.nonNull(retryPredicate)) {
boolean shouldItRetry = retryPredicate.shouldRetry(result);
if (shouldItRetry) {
retries = increaseRetryCountAndSleep(retries);
} else {
return result;
}
} else {
// no retry condition defined, no exception thrown. This is the desired result.
return result;
}
} catch (Throwable e) {
retries = handleException(retries, e);
}
}
return result;
}
private int handleException(int retries, Throwable e) throws Throwable {
if (exceptionList.contains(e.getClass()) || (exceptionList.isEmpty())) {
// exception is excepted, continue retry.
retries = increaseRetryCountAndSleep(retries);
if (retries == noOfRetry) {
// evaluation is throwing exception, no more retry left. Throw it.
throw e;
}
} else {
// unexpected exception, no retry required. Throw it.
throw e;
}
return retries;
}
private int increaseRetryCountAndSleep(int retries) {
retries++;
if (retries < noOfRetry && delayInterval > 0) {
try {
timeUnit.sleep(delayInterval);
} catch (InterruptedException ignore) {
Thread.currentThread().interrupt();
}
}
return retries;
}
}
Let's have a test case like:
#Test
public void withPredicateAndException() {
AtomicInteger integer = new AtomicInteger();
try {
Integer result = RetryOperation.<Integer>newBuilder()
.retryConsumer(() -> {
int i = integer.incrementAndGet();
if (i % 2 == 1) {
throw new NumberFormatException("Very odd exception");
} else {
return i;
}
})
.noOfRetry(10)
.delayInterval(10, TimeUnit.MILLISECONDS)
.retryPredicate(value -> value <= 6)
.retryOn(NumberFormatException.class, EOFException.class)
.build()
.retry();
Assert.assertEquals(8, result.intValue());
} catch (Throwable throwable) {
Assert.fail();
}
}
A simple way to solve the issue would be to wrap the try/catch in a while loop and maintain a count. This way you could prevent an infinite loop by checking a count against some other variable while maintaining a log of your failures. It isn't the most exquisite solution, but it would work.
In case it's useful, a couple more options to consider, all thrown together (stopfile instead of retries, sleep, continue larger loop) all possibly helpful.
bigLoop:
while(!stopFileExists()) {
try {
// do work
break;
}
catch (ExpectedExceptionType e) {
// could sleep in here, too.
// another option would be to "restart" some bigger loop, like
continue bigLoop;
}
// ... more work
}
If not all exceptions warrant a retry, only some. And if at least one try has to be made, Here is an alternative utility method:
void runWithRetry(Runnable runnable, Class<Exception> exClass, int maxRetries) {
Exception err = null;
do {
maxRetries--;
try {
runnable.run();
err = null;
} catch (Exception e) {
if(exClass.isAssignableFrom(e.getClass())){
err = e;
}else {
throw e;
}
}
} while (err != null && maxRetries > 0);
if (err != null) {
throw err;
}
}
Usage:
runWithRetry(() -> {
// do something
}, TimeoutException.class, 5)
All a Try-Catch does is allow your program to fail gracefully. In a catch statement, you generally try to log the error, and maybe roll back changes if you need to.
bool finished = false;
while(finished == false)
{
try
{
//your code here
finished = true
}
catch(exception ex)
{
log.error("there was an error, ex");
}
}
Use a do-while to design re-try block.
boolean successful = false;
int maxTries = 3;
do{
try {
something();
success = true;
} catch(Me ifUCan) {
maxTries--;
}
} while (!successful || maxTries > 0)
Here a reusable and more generic approach for Java 8+ that does not require external libraries:
public interface IUnreliable<T extends Exception>
{
void tryRun ( ) throws T;
}
public static <T extends Exception> void retry (int retryCount, IUnreliable<T> runnable) throws T {
for (int retries = 0;; retries++) {
try {
runnable.tryRun();
return;
} catch (Exception e) {
if (retries < retryCount) {
continue;
} else {
throw e;
}
}
}
}
Usage:
#Test
public void demo() throws IOException {
retry(3, () -> {
new File("/tmp/test.txt").createNewFile();
});
}
You can use https://github.com/bnsd55/RetryCatch
Example:
RetryCatch retryCatchSyncRunnable = new RetryCatch();
retryCatchSyncRunnable
// For infinite retry times, just remove this row
.retryCount(3)
// For retrying on all exceptions, just remove this row
.retryOn(ArithmeticException.class, IndexOutOfBoundsException.class)
.onSuccess(() -> System.out.println("Success, There is no result because this is a runnable."))
.onRetry((retryCount, e) -> System.out.println("Retry count: " + retryCount + ", Exception message: " + e.getMessage()))
.onFailure(e -> System.out.println("Failure: Exception message: " + e.getMessage()))
.run(new ExampleRunnable());
Instead of new ExampleRunnable() you can pass your own anonymous function.
Simplifying #ach's previous solution into one file and using functional interfaces.
public class OperationHelper {
public static void doWithRetry(int maxAttempts, Runnable operation, Consumer<Exception> handle) {
for (int count = 0; count < maxAttempts; count++) {
try {
operation.run();
count = maxAttempts; //don't retry
} catch (Exception e) {
handle.accept(e);
}
}
}
}
simple
int MAX = 3;
int count = 0;
while (true) {
try {
...
break;
} catch (Exception e) {
if (count++ < MAX) {
continue;
}
...
break;
}
}
https://onlinegdb.com/a-7RsL1Gh
public void doSomething() throws Exception{
final int MAX_TRIES = 10;
int count = 0;
while(count++ < MAX_TRIES){
try{
System.out.println("trying");
causeIssue(count); // throws error/exception till count 2
System.out.println("trying successful");
break; // break on success
} catch (Exception e){
System.out.println("caught, logging Exception:" + count);
} catch (Error e){
System.out.println("caught, logging Error:" + count);
}
}
}
Output:
trying
caught, logging Error:1
trying
caught, logging Error:2
trying
trying successful
I know there are already many similar answers here, and mine is not much different, but I will post it anyway because it deals with a specific case/issue.
When dealing with the facebook Graph API in PHP you sometimes get an error, but immediately re-trying the same thing will give a positive result (for various magical Internet reasons that are beyond the scope of this question). In this case there is no need to fix any error, but to simply try again because there was some kind of "facebook error".
This code is used immediately after creating a facebook session:
//try more than once because sometimes "facebook error"
$attempt = 3;
while($attempt-- > 0)
{
// To validate the session:
try
{
$facebook_session->validate();
$attempt = 0;
}
catch (Facebook\FacebookRequestException $ex)
{
// Session not valid, Graph API returned an exception with the reason.
if($attempt <= 0){ echo $ex->getMessage(); }
}
catch (\Exception $ex)
{
// Graph API returned info, but it may mismatch the current app or have expired.
if($attempt <= 0){ echo $ex->getMessage(); }
}
}
Also, by having the for loop count down to zero ($attempt--) it makes it pretty easy to change the number of attempts in the future.
following is my solution with very simple approach!
while (true) {
try {
/// Statement what may cause an error;
break;
} catch (Exception e) {
}
}
Im not sure if this is the "Professional" way to do it and i'm not entirely sure if it works for everything.
boolean gotError = false;
do {
try {
// Code You're Trying
} catch ( FileNotFoundException ex ) {
// Exception
gotError = true;
}
} while ( gotError = true );
https://github.com/tusharmndr/retry-function-wrapper/tree/master/src/main/java/io
int MAX_RETRY = 3;
RetryUtil.<Boolean>retry(MAX_RETRY,() -> {
//Function to retry
return true;
});
The issue with the remaining solutions is that, the correspondent function tries continuously without a time interval in-between, thus over flooding the stack.
Why not just trying only every second and ad eternum?
Here a solution using setTimeout and a recursive function:
(function(){
try{
Run(); //tries for the 1st time, but Run() as function is not yet defined
}
catch(e){
(function retry(){
setTimeout(function(){
try{
console.log("trying...");
Run();
console.log("success!");
}
catch(e){
retry(); //calls recursively
}
}, 1000); //tries every second
}());
}
})();
//after 5 seconds, defines Run as a global function
var Run;
setTimeout(function(){
Run = function(){};
}, 5000);
Replace the function Run() by the function or code that you'd like to retry every second.
Give it a try using springs #Retryable annotation , the below method will retry for 3 attempts when RuntimeException occurs
#Retryable(maxAttempts=3,value= {RuntimeException.class},backoff = #Backoff(delay = 500))
public void checkSpringRetry(String str) {
if(StringUtils.equalsIgnoreCase(str, "R")) {
LOGGER.info("Inside retry.....!!");
throw new RuntimeException();
}
}
Below snippet execute some code snippet. If you got any error while executing the code snippet, sleep for M milliseconds and retry. Reference link.
public void retryAndExecuteErrorProneCode(int noOfTimesToRetry, CodeSnippet codeSnippet, int sleepTimeInMillis)
throws InterruptedException {
int currentExecutionCount = 0;
boolean codeExecuted = false;
while (currentExecutionCount < noOfTimesToRetry) {
try {
codeSnippet.errorProneCode();
System.out.println("Code executed successfully!!!!");
codeExecuted = true;
break;
} catch (Exception e) {
// Retry after 100 milliseconds
TimeUnit.MILLISECONDS.sleep(sleepTimeInMillis);
System.out.println(e.getMessage());
} finally {
currentExecutionCount++;
}
}
if (!codeExecuted)
throw new RuntimeException("Can't execute the code within given retries : " + noOfTimesToRetry);
}
Here is my solution similar to some others can wrap a function, but allows you to get the functions return value, if it suceeds.
/**
* Wraps a function with retry logic allowing exceptions to be caught and retires made.
*
* #param function the function to retry
* #param maxRetries maximum number of retires before failing
* #param delay time to wait between each retry
* #param allowedExceptionTypes exception types where if caught a retry will be performed
* #param <V> return type of the function
* #return the value returned by the function if successful
* #throws Exception Either an unexpected exception from the function or a {#link RuntimeException} if maxRetries is exceeded
*/
#SafeVarargs
public static <V> V runWithRetriesAndDelay(Callable<V> function, int maxRetries, Duration delay, Class<? extends Exception>... allowedExceptionTypes) throws Exception {
final Set<Class<? extends Exception>> exceptions = new HashSet<>(Arrays.asList(allowedExceptionTypes));
for(int i = 1; i <= maxRetries; i++) {
try {
return function.call();
} catch (Exception e) {
if(exceptions.contains(e.getClass())){
// An exception of an expected type
System.out.println("Attempt [" + i + "/" + maxRetries + "] Caught exception [" + e.getClass() + "]");
// Pause for the delay time
Thread.sleep(delay.toMillis());
}else {
// An unexpected exception type
throw e;
}
}
}
throw new RuntimeException(maxRetries + " retries exceeded");
}
This Solution allows you to configure a reusable functionality for retrying based on certain exception without using any external libraries
// Create a Function that suits your need .
#FunctionalInterface
public interface ThrowableBiFunction<U,T,R> {
R apply(U u ,T t) throws Exception;
}
//Here's the crux of the solution
public interface ExceptionRetryable<T, U, R> {
int getRetries();
List<Class<? extends Exception>> getRetryableExceptions();
default R execute(ThrowableBiFunction<T, U, R> function, T t, U u) throws Exception {
int numberOfRetries = getRetries();
return execute(function, t, u, numberOfRetries);
}
default R execute(ThrowableBiFunction<T, U, R> function, T t, U u, int retryCount) throws Exception {
try {
log.info(" Attempting to execute ExceptionRetryable#execute ,Number of remaining retries {} ",retryCount);
return function.apply(t, u);
} catch (Exception e) {
log.info(" error occurred in ExceptionRetryable#execute",e);
if (retryCount == 0)
throw e;
for (Class exp : getRetryableExceptions()) {
if (e.getClass() == exp) {
return execute(function, t, u, retryCount - 1);
}
}
throw e;
}
}
}
// create an implementation for exception retryable
public class TestRetryable implements ExceptionRetryable<String, String, List<String>> {
#Override
public int getRetries() {
return 10;
}
#Override
public List<Class<? extends Exception>> getRetryableExceptions() {
return Arrays.asList(new Exception1().getClass(), new Exception2().getClass());
;
}
}
// Finally create a ThrowableBiFunction that encapsulates that piece of code that needs to be retried on exception and an instance of ExceptionRetryable
TestRetryable retryable = new TestRetryable();
ThrowableBiFunction<Integer,Long, String> testRetrablefcn = { i, l ->
// your code goes here
};
Integer i = 0;
Long l = 1l;
String output = testRetrablefcn.execute(testRetrablefcn,i,l);
Production ready code:
#FunctionalInterface
public interface Operation {
void doCall() throws IOException;
default void handleException(Exception e) {
//Your custom default implementation
}
public class OperationHelper {
public static void doWithRetry(int maxAttempts, Operation operation) {
for (int count = 0; count <= maxAttempts; count++) {
try {
operation.doCall();
return;
} catch (Exception e) {
if (count == maxAttempts) {
e.printStackTrace();
return;
} else {
operation.handleException(e);
}
}
}
}
}
Usage with default implementation in code:
OperationHelper.doWithRetry(10,
() -> //do your job );
Usage when custom exception handle is needed:
OperationHelper.doWithRetry(10, new Operation() {
#Override public void doIt() {
//do some stuff
}
#Override public void handleException(Exception cause) {
//recover from the Exception
}
});

Categories