This question already has answers here:
How do you implement a re-try-catch?
(29 answers)
Closed 4 years ago.
Is there any way to do this?
//Example function taking in first and last name and returning the last name.
public void lastNameGenerator() throws Exception{
try {
String fullName = JOptionPane.showInputDialog("Enter your full name");
String lastName = fullName.split("\\s+")[1];
catch (IOException e) {
System.out.println("Sorry, please enter your full name separated by a space.")
//Repeat try statement. ie. Ask user for a new string?
}
System.out.println(lastName);
I think I can use scanner for this instead, but I was just curious about if there was a way to repeat the try statement after catching an exception.
Something like this ?
while(condition){
try{
} catch(Exception e) { // or your specific exception
}
}
One way is to use a while loop and exit when the name has been set properly.
boolean success = false;
while (!success) {
try {
// do stuff
success = true;
} catch (IOException e) {
}
}
There is no "re-try" in the language, like others suggested already: create an outer while loop and set a flag in the "catch" block that triggers the retry (and a clear the flag after a successful try)
Would it be ok to use external lib?
If so, check out Failsafe.
First, you define a RetryPolicy that expresses when retries should be performed:
RetryPolicy retryPolicy = new RetryPolicy()
.retryOn(IOException.class)
.withMaxRetries(5)
.withMaxDuration(pollDurationSec, TimeUnit.SECONDS);
Then, you use your RetryPolicy to execute a Runnable or Callable with retries:
Failsafe.with(retryPolicy)
.onRetry((r, f) -> fixScannerIssue())
.run(() -> scannerStatement());
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.
You need a recursion
public void lastNameGenerator(){
try {
String fullName = JOptionPane.showInputDialog("Enter your full name");
String lastName = fullname.split("\\s+")[1];
catch (IOException e) {
System.out.println("Sorry, please enter your full name separated by a space.")
lastNameGenerator();
}
System.out.println(lastName);
}
Just put try..catch inside while loop.
Signature of showInputDialog() is
public static java.lang.String showInputDialog(java.lang.Object message)
throws java.awt.HeadlessException
and that of split() is
public java.lang.String[] split(java.lang.String regex)
None of then throw IOException. Then how are you catching it?
Anyway possible solution to your problem would be
public void lastNameGenerator(){
String fullName = null;
while((fullName = JOptionPane.showInputDialog("Enter your full name")).split("\\s+").length<2) {
}
String lastName = fullName.split("\\s+")[1];
System.out.println(lastName);
}
No need of try-catch. tried it myself. It works fine.
This sure is a simplified code fragment because in this case I'd simply remove the try/catch altogether - IOException is never thrown. You could get an IndexOutOfBoundsException, but in your example it really shouldn't be handled with exceptions.
public void lastNameGenerator(){
String[] nameParts;
do {
String fullName = JOptionPane.showInputDialog("Enter your full name");
nameParts = fullName != null ? fullName.split("\\s+") : null;
} while (nameParts!=null && nameParts.length<2);
String lastName = nameParts[1];
System.out.println(lastName);
}
EDIT: JOptionPane.showInputDialog might return null which wasn't handled before. Also fixed some typos.
Related
I want to make a test that reads from a file some data and passes that data to a function. That function calls other methods and some of them throw some exceptions. I'm interested in how can I check whether or not calling the method with the parameters from the file triggered an IOException somewhere along. I know that the code snippet provided will stop the execution because I've used assert. How should I write if I want to check if an IOException was thrown and if it was, to get the error message, without stopping the execution of the test? Thanks!
void test() throws IOException {
Service service = helperFunction();
File articles = new File("file.txt");
Scanner scanner = new Scanner(articles);
while(scanner.hasNextLine()) {
String line = scanner.nextLine();
line = line.replaceAll("[^\\d]", " ");
line = line.trim();
line = line.replaceAll(" +", " ");
String[] numberOnTheLine = line.split(" ");
List<Integer> list = Arrays.stream(numberOnTheLine).map(Integer::valueOf).collect(Collectors.toList());
Article article = new Article(Long.valueOf(list.get(0)),
new HashSet<>(List.of(new Version(list.get(1)))));
List<List<Article>> listOfArticles = Collections.singletonList(List.of(article));
Assertions.assertThrows(IOException.class,
() -> service.etlArticles(listOfArticles.stream().flatMap(List::stream).collect(Collectors.toList())));
}
}
Simple; a try/catch statement will take care of it.
Replace this:
service.etlArticles(listOfArticles.stream().flatMap(List::stream).collect(Collectors.toList())));
With:
try {
service.etlArticles(listOfArticles.stream().flatMap(List::stream).collect(Collectors.toList())));
} catch (IOException e) {
// Code jumps to here if an IOException occurs during the execution of anything in the try block
}
You are free to e.g. do some logging and then just Assert.fail, if you want.
assertThrows is quite simple, all it does is this:
try {
runThatCode();
} catch (Throwable e) {
if (e instanceof TypeThatShouldBeThrown) {
// Great, that means the code is working as designed, so, just...
return;
}
// If we get here, an exception was thrown, but it wasn't the right type.
// Let's just throw it, the test framework will register it as a fail.
throw e;
}
// If we get here, the exception was NOT thrown, and that's bad, so..
Assert.fail("Expected exception " + expected + " but didn't see it.");
}
Now that you know how it works, you can write it yourself and thus add or change or log or whatever you want to do during this process at the right place. However given you know it's IOException, instead of an instanceof check you can just catch (IOException e), simpler.
Could someone explain me what could be the reason for such an error log. When would this be printed. I am not able to understand and this is causing a performance issue in my app.
my error log is like below-
at xxx.createBooking(MailEJB3ServiceZipProxy.java:453)
at xxxx.onSelectBooking(Main.java:2524)
at xxxx.onSelectBooking(Main.java:2603)
at xxxx.onSelectBooking(Main.java:2603)
at xxxx.onSelectBooking(Main.java:2603)
at xxxx.onSelectBooking(Main.java:2603)
at xxxx.onSelectBooking(Main.java:2603)
at xxxx.onSelectBooking(Main.java:2603)
my catch block code looks like -
public void onSelectBooking(){
try{
////
} catch(ReservationBusinessException ex){
m_hModuleContainer.setBusy(false);
List mail = ex.getMailHeader();
m_hCargoRecordDTO = (CargoRecordDTO)mail.get(0);
ReservationObserver m_hReservationObserver= new ReservationObserver();
m_hReservationObserver.setCargoRecordDTO(m_hCargoRecordDTO);
m_hReservationParameterDTO.setReservationObserver(m_hReservationObserver);
ExceptionTab exceptionTab = new ExceptionTab(m_hReservationParameterDTO,m_hCargoRecordDTO,ex);
if ( exceptionTab.isErrorsOverridden() ){
// set all overridden flags
m_hCargoRecordDTO.setSoftErrorsAccepted(true);
m_hCargoRecordDTO.setErrorShown(true);
m_hMailHeaderDTO.addHtCar(m_hCargoRecordDTO);
onSelectBooking();**// line 2603**
}
Presuming the error printed before the first line is StackOverflowError, it's because you have infinite recursion, where the logic in the try block fails with ReservationBusinessException, causing the code to retry infinitely with a recursive call in line 2603, until the call stack is full.
There are 2 ways to fix this:
Change the code to use a loop, instead of recursion, to retry, e.g.
public void onSelectBooking() {
boolean retry;
do {
retry = false;
try {
...
} catch(ReservationBusinessException ex) {
...
retry = true; // instead of recursive call
}
} while (retry);
The problem with this solution is that the code may never complete, if the cause of the exception isn't resolved.
Limit the number of retries. This should be done using a loop like above but with a retry count instead of a boolean, but can still be done using recursion:
private static int MAX_RETRIES = 3;
public void onSelectBooking() {
onSelectBooking(0); // first attempt is not a "retry"
}
public void onSelectBooking(int retry) {
try {
...
} catch(ReservationBusinessException ex) {
if (retry > MAX_RETRIES) {
throw new RuntimeException("Max. number of retries (" + MAX_RETRIES + ") exceeded: " + ex, ex);
}
...
onSelectBooking(retry + 1);
}
}
I am checking if number the user entered is Zeckendorf and I want to display an exception if it is not, how do i do that? Also how do I convert the Zeckondorf to its decimal equivalent?
import java.util.Scanner;
public class IZeckendorfNumberConvertor {
static String number;
int zeckonderEquivalent;
static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
convertToZeckonderNumber();
isTrueZeckonderNumber();
}
private static boolean isTrueZeckonderNumber() {
System.out.println("Enter a Zeckonder Number:");
number = scanner.nextLine();
if (number.equals("10100"))
{
return true; }
else if (number.equals("010011") || number.equals("010100"))
{
return false; }
return false;
}
private static void convertToZeckonderNumber() {
}}
I advise you not to display an exception (i.e. trace and such) as it is very user Unfriendly.
You can use the throw syntax to throw a proper exception :
throw new Exception("Given number is not a Zeckendorf number");
but be sure to catch it and display a nice and clean message :
try {
// Your input code goes here
} catch (Exception e) {
System.out.println(e.getMessage());
}
Another easier option will be to just check the return value of the method and print the results accordingly.
I will recommend to use the latter solution as exceptions are used when something bad and unexpected happens in your program and you want to handle it gracefully. In your case the behavior is expected (i.e. user giving a wrong number) so checking the return value will be much clean and easier.
Use try catch block for catch an exception
try {
} catch (Exception e) {
e.printStackTrace();
}
Also use throw for throw a new exception
Assuming to really do want to display the exception, and not a more user friendly message, the first step is probably to get the exception as a string. Then you can do what you like with that string (echo to console, place in a javax.swing.JTextArea, email it, etc).
If you just want the message from the exception, then getMessage() will do:
try { ... }
catch(FooException e) {
String msg = e.getMessage();
}
However, if you want the whole exception, stack trace and all, you'll want something like this:
public static String stackTrace(Exception e) {
StringWriter w = new StringWriter();
e.printStackTrace(new PrintWriter(w));
return w.toString();
}
// ...
try { ... }
catch(FooException e) {
String st = stackTrace(e);
}
If you just want to echo the full stack trace to the console, there is the printStackTrace(), no-arg method:
try { ... }
catch(FooException e) {
e.printStackTrace();
}
If you want to take more control of the presentation of the stack trace you can get the details with:
try { ... }
catch(FooException e) {
StackTraceElement[] stes = e.getStackTrace();
// Do something pretty with 'stes' here...
}
You can just print a error message to the user saying that the input is wrong using a simple if.
if(yourCondition){
// Happy scenario
// Go shead
}else{
// Error Scenario
System.out.println("Error. Invalid Input.");
// If you persist to throw an exception, then you can do something like this
// throw new Exception("Exception Explanation"); // I've commented this, but you can uncomment it if needed
// But the advice is to display an error message, than throw a exception.
}
And regarding the conversion, you can convert binary to decimal like this
int i = Integer.parseInt(binaryString, 2); // 2 indicates the radix here, since you want to convert from binary.
With this code snippet you can convert the String into an integer :
int numberAsInt;
try {
numberAsInt = Integer.parseInt(number);
} catch (NumberFormatException e) {
//Will throw an Exception
}
If you want to create your own Exception class, you can do it like shown here or just throw a RuntimeException with
throw new RuntimeException("Your Message");
My opinion, you can try some thing like following
public static void main(String[] args) {
if(!isTrueZeckonderNumber()){
// your message should goes here
System.out.println("Your message");
}
}
If you really want to throws an exception do following
private static boolean isTrueZeckonderNumber() throws Exception{
System.out.println("Enter a Zeckonder Number:");
number = scanner.nextLine();
if (number.equals("10100")) {
return true;
} else{
throw new Exception("your message");
}
}
What do you mean you want to display an exception?
I would suggest just giving the user feedback instead, as exceptions are used more commonly for EXCEPTIONAL actions that are not supposed to happen.
However if you do want to, you can print a message explaining what happened.
try {
} catch (Exception e) {
System.out.println(e.getMessage());
}
I'm trying to pass a String from one class to another class but the result I'm getting is 'null'. I want to pass the String username from LoginFrame to HomeworkFrame;
HomeworkFrame:
public void loadSubjects (){
String item;
try{
System.out.println(username);
Scanner f = new Scanner (new FileReader (username + " " + "Subjects" + ".txt"));
while(f.hasNext()){
item = f.nextLine();
chSubjects.add(item);
}
f.close();
}catch(Exception e){
JOptionPane.showMessageDialog(null, "Subjects cannot be loaded!", "Error", JOptionPane.ERROR_MESSAGE);
}
}
LoginFrame:
public void loginUser(){
r = new Registration();
h = new HomeworkFrame();
l = new Login();
l.username = txtUser.getText();
l.password = txtPass.getText();
try{
String line;
boolean passwordFound = false ;
BufferedReader f = new BufferedReader(new FileReader(l.username + ".txt"));
while((line = f.readLine()) != null){
if(line.equals(l.password)){
passwordFound = true;
}
}
if(passwordFound){
h.username = l.username;
dispose();
m.setSize(700,600);
m.setLocation(100,100);
m.setVisible(true);
}else{
JOptionPane.showMessageDialog(null, "Wrong information!", "Error", JOptionPane.ERROR_MESSAGE);
}
f.close();
}catch(Exception e){
JOptionPane.showMessageDialog(null, "Wrong information!", "Error", JOptionPane.ERROR_MESSAGE);
}
}
Obviously I'm getting the error "Subjects cannot be loaded" as the username is null(I checked it by using the println method).
In case problems like this you have to track your variables/fields from the place you've noticed your 'username' field is null. Next steps should be:
Check what operations you do on 'h' object before you call the loadObjects() method and if any then check what influence they have on username field in HomeWorkFrame (using println or a debugger).
Check if your passwordFound in LoginFrame is true (because if it's false it doesn't assign a value to h.username)
If it's false check if your password's been retrieved from a file (using same println statement)
This kind of scenario should help you finding most of 'null' bugs.
Try to check first, which type of Exception you get.
May be the file is not existing or the list is null or....
Is a format problem : put a \ before your space in pathString : "\ "
You have to write it "\ Subjects.txt", without '+' between.
public class LoginFrame{
private HomeworkFrame hw;
public void doSomething(){
String username = "your username";
hw = new HomeworkFrame(username);
}
}
public class HomeworkFrame{
public HomeworkFrame(String username){
doSomething with 'username'
}
}
Ans to your question! :)
If System.out.println(username); displays null this means that
1.username variable is not initialized and left.
2.value is not assigned to it properly.
3.It might be a static variable and you are changing the value of it.
Please check all these conditions and please give that part of the code from where the loadSubjects() is being called, and not the body of that method as you have provioded it already.
Also all those parts of code where the username is initialized,assigned,modified.
It is required to specify or pass the value otherwise it will definitely give Null as it will not find any value to execute.
Let's say I can a set of statements:
try {
String a = getProperty("a");
String b = getProperty("b");
String c = getProperty("c");
} catch(Exception e) {
}
Now, lets say property b was not found and the function throws an exception. In this case, how would I just continue or perhaps set b to null without having to write a try-catch block for each property? I mean, a,b,c exist but sometime they might not be found at all during which an exception is thrown.
Assuming you can't change the function so that it returns null when the property isn't found, you are kind of stuck wrapping everything in its own try catch block -- especially if you want for every value that can be retrieved to be retrieved (as opposed to letting the first value that fails cancel the whole operation.)
If you have a lot of these properties to retrieve, perhaps it would be cleaner to write a helper method to use:
String getPropertySafely(String key) {
try {
return getProperty(key);
} catch (Exception e) {
return null;
}
}
You have to put a try-catch around each statement. There is no continue (like there is in ON ERROR ... RESUME blocks in VB). Instead of:
String a = null;
try {
a = getProperty("a");
} catch(Exception e) {
...
}
String b = null;
try {
b = getProperty("b");
} catch(Exception e) {
...
}
String c = null;
try {
c = getProperty("c");
} catch(Exception e) {
...
}
you could write:
public String getPropertyNoException(String name) {
try {
return getProperty(name);
} catch (Exception e) {
return null;
}
}
Personally I think a getProperty() is a poor candidate for throwing exceptions just for all this extra boilerplate required
Since you are using the same function each time you might be able to put this in a loop:
String[] abc = new String[3];
String[] param = {"a", "b", "c"};
for (int i = 0; i < 3; i++) {
try {
abc[i] = getProperty(param[i]);
} catch(Exception e) {
}
}
but this is rather contrived and would only be useful for a large number of properties. I suspect you will have to simple write 3 try-catch.
You should reconsider how getProperty is handled if you plan to use many of them because there isn't a plain way to do it.
You can exploit finally statement but you still need a try-catch for every call.