I have a class Game with a constructor with the following signature:
public Game(String[] boardState) throws InvalidStringsInputException, WrongNumberOfMarksException
And there is a method in junit4 testcase:
public static Game newGameFromStringsSuccessful(String[] input) //it is the line 9
{
try
{
return new Game(input);
}
catch (WrongNumberOfMarksException exception)
{
fail("Caught exception where it shouldn't be");
}
catch (InvalidStringsInputException exception)
{
fail("Caught exception where it shouldn't be");
}
}
I am using eclipse and it shows me an error:
This method must return a result of type Game line 9 Java Problem
If I insert return null in the ends of both catch blocks, the error disappears, but my question doesn't: why does java want it even after fail() method is called?
why does java want it even after fail() method is called?
Because the compiler doesn't know that fail can't return normally. There's no way of expressing that within Java. The end of the fail message call is still reachable - so the end of the method is also reachable.
Suppose there was a bug in the fail method, so you ended up reaching the end of the method - what would you expect to happen?
The simplest fix for this is to throw some runtime exception at the end of the method, e.g. AssertionError:
throw new AssertionError("fail must have returned normally!");
It's basically an exception to say "The world is crazy, I don't want to live here any more" - which also keeps the compiler happy, as the closing brace of the method is no longer reachable.
Another alternative - not available here, as you don't control the fail method - would be to declare the fail method to return some kind of runtime exception, at which point your catch blocks could look like this:
catch (InvalidStringsInputException exception)
{
throw fail("Caught exception where it shouldn't be");
}
Of course the implementation of fail would still be to throw an exception rather than return it, but it means the compiler knows that that catch block is definitely not going to complete normally.
Jon's answer below explains why the compiler is complaining. However, I suggest that the correct way to avoid this is to not have the try/catch in you test. Just let the exception propagate up the call stack and out of your test. JUnit will catch it and fail the test while providing the entire stack trace of where the exception was thrown.
Or if you prefer not to have to propagate the throws clause, wrap the exception in a RuntimeException and then throw that. Again, this will provide the stack trace to allow for better diagnosis.
Related
So quoting from this page, which is titled: Exception-Handling Antipatterns Blog and seems to be written (or at least to be approved) by Oracle..
An unchecked exception probably shouldn't be retried, and the correct response is usually to do nothing, and let it bubble up out of your method and through the execution stack. This is why it doesn't need to be declared in a throws clause. Eventually, at a high level of execution, the exception should probably be logged.
I am not sure if I understand this. How can I log an unchecked exception? If I have something like:
public static void main(String args) {
foo();
// How do I know what to log here? The method I am calling
// is not throwing an Exception.
// Do I just blindly catch(Exception ex)?
}
static void foo() {
bar();
}
static void bar() {
baz();
}
static void baz() {
// I will do nothing as Oracle suggests and let this exception bubble up.. I wonder who is going to catch it and how this is going to be logged though!
throw new NullPointerException();
}
Can you help me understand what Oracle is suggesting here? I do not see any direct (or clear) way to catch runtime exceptions (I do not understand why it is not just called unchecked exceptions..) in higher levels and I am not sure how this suggested practice is useful. To me it would make more sense if it were talking about checked exceptions. Something like..
If a checked exception is thrown in a method that is not reasonable to be re-tried, the correct response is to let it bubble up and log..
You can also register a global ExceptionHandler that will handle the Exceptions that were not caught by your code:
Thread.setDefaultUncaughtExceptionHandler
This exception handle could then log whatever occured.
First of all, this is a general advice and it depends on the context. The idea behind it is that when a runtime exception occurs (ex. NullPointerException), the system is usually in an indeterministic state, meaning the rest of the code is not be guaranteed to execute as expected, so it's better to stop everything.
In most cases, your code will run in a separate thread and the exception will only stop the current thread, while the rest of the program keeps running.
This is not the case in your example, because everything is executed in a single thread, so the uncaught exception will effectively stop the whole program. In this scenario you might want to catch the exception and handle it.
public static void main(String args) {
try {
foo();
catch(Throwable t) {
t.printStackTrace(); // log exception
// handle the failure
}
}
You can also catch the exception earlier on, log and rethrow it further.
static void bar() {
try {
baz();
catch (Throwable t) { // catch
t.printStackTrace(); // log
throw t; // rethrow further
}
}
Edit: catch Throwable instead of Exception, will also catch Error
Note: Catching throwable is usually a bad idea, and should only be done with a specific purpose, not in general case. See #RC.'s comment.
As I understand it the documentation is suggesting that you have a generic handler at a high level of your code that logs such 'unexpected' (unrecoverable?) exceptions just as the comments in your main method suggest. So it might look something like this
public static void main(String args) {
try {
foo();
}
catch (ArithmeticException aex) { //if it's arithmetic log differently
log("arith issue! "+aex.getMessage());
}
catch (Exception ex) { //Otherwise do the best we can
log("unknown issue! "+ex.getMessage())
}
}
So there is still no path to recovery but at least before the process ends you get a chance to log the issue. You can also use the methods of Exception (or throwable) to get the stack trace and first causal exceptions in many case - so there is is a lot of extra useful information that might be logged.
There is a very straightforward way to catch unchecked exceptions, since they are all subclasses of RuntimeException or Error:
public static void main(String[] args) {
try {
// your code
} catch (RuntimeException | Error e) {
// handle uncaught exceptions, e.g.
e.printStackTrace();
}
}
How do I know what to log here? The method I am calling is not throwing an Exception.
As Joshua Bloch recommends in the Effective Java
Use the Javadoc #throws tag to document each unchecked exception that
a method can throw, but do not use the throws keyword to include
unchecked exceptions in the method declaration
And if you are using method wrapping in multilayered app i can recommend use exception translation:
Higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of the higher-level abstraction
See Effective Java item 61
So i think for your example actually you should use something like:
try {
bar();
} catch(NullPointerException e) {
throw new HigherLevelException(...);
}
The most important guideline regarding exceptions is that a method that couldn't sucessfully complete its task should throw an exception.
Only if you can guarantee successful completion of your method's task, you should catch an exception inside your method (without re-throwing this or another exception). From my experience that's only true in very specific situations, e.g. if you have an alternative way to try if some first attempt fails, or if you really really understand all possible causes of this specific Exception class that you are about to catch.
Speaking about RuntimeExceptions, there are so many different types of RuntimeException that you can hardly justify an assertion like "When such an exception arises in my code or a method called from inside my code, that won't affect the outcome of my method - I can continue just as if nothing happened." So, you should signal to your caller that you failed to fulfill your task, and the clearest way to do that is to let the exception ripple through, without try/catch block or throws declaration, just relying on Java's default behaviour.
In my opinion, the same reasoning applies to nearly all kinds of exceptions, not only RuntimeExceptions.
The difference with checked exceptions is that you have to declare them in the throws clause of your method. Then you have two choices: list the exception in the throws clause of your method (and all parent methods as well!) or catch the exception, wrap it in a new RuntimeException(ex), and throw that from your method.
With e.g. a typical GUI application, your users will be grateful if a problem in one menu function won't crash the whole application - probably other menu items might still work as expected. So, top-level commands or menu items are typically the places where to catch exceptions, tell the user something like "Oops!", log the exception to some file for later inspection, and allow the user to continue with another action.
In your main/foo/bar/baz application, I don't see a place where continuing after an exception makes sense. So the whole program should be aborted (which happens automatically in your case). If you want some error logging to a file, then establish an uncaught exception handler or wrap the body of main() in a try / catch(Throwable t) block. You'll probably want every exception logged, whatever type it is, so catch them all, and that's why I'm suggesting Throwable.
public static void main(String[] args) {
try {
foo();
}
catch(NullPointerException e){
System.out.println("NullPointerException in main.");
}
}
static void foo() {
bar();
}
static void bar() {
baz();
}
static void baz() {
// I will do nothing as Oracle suggests and let this exception bubble up.. I wonder who is going to catch it and how this is going to be logged though!
throw new NullPointerException();
}
OUTPUT :
NullPointerException in main.
Basically the error is expected at a higher level, so there is no need to catch it on the baz() method level. If I understood correctly.
You can catch them just like any other exception with try-catch block. But the benefit is that you don't have to.
Use cases can vary. To my mind, the most popular is when it doesn't make sense to catch the exception right in that place or the appropriate handling should be implemented several levels (in terms of methods) higher than the method, calling the one throwing the exception (sorry, if that is not clear enough).
For example, the typical web application layout in java is as follows: you have a layer of controllers, a layer of services and a layer of dao. First one is responsible for dispatching requests, the second one is for managing business logic and the last one makes actual calls to db. So here for example it often doesn't make much sense to catch the exception in service layer if something goes wrong on the dao level. Here unchecked exceptions can be used. You log an exception and throw an unchecked exception so it could be handled some levels above for a user to get valuable feedback of work of the application.
If in this case you throw a checked exception you will have to rethrow it every level above just to bubble up it to the place of the actual handling. So here the unchecked exception is better to use in order not to copy and paste all that ugly try-catch block, rethrowing an exception and add the throws clause to the method.
Let me preface this by saying, I am not a Java programmer and have thus far been unable to understand WHY this is the case.
I'm currently working on a homework assignment that requires me to create a basic GUI using JavaFX. The functionality of this GUI requires that there are buttons that will perform CRUD operations when clicked. Currently I have everything set up properly in my Insert method:
public void Insert() throws SQLException{
//Insert new record here
}
However, whenever I try to subscribe to this method using 'setOnAction', the compiler is telling me there's an unhandled exception on the event:
btnInsert.setOnAction(e ->Insert());
I'm more curious if there's a way to handle this in a relatively succinct way? I've thus far been unable to come up with a solution.
That's because Java requires you to declare all checked exceptions you throw - so whenever you call a method that may throw a checked exception, you must either catch it or declare you may throw it yourself.
See this question for an explanation of checked vs. unchecked exception (The short version - any Exception which inherits either Error or RuntimeException is unchecked, while all other exceptions are checked.)
When you are providing setOnAction with a lambda, you are actually creating an anonymous class implementation of EventHandler<ActionEvent>. Since it does not declare it throws any exceptions, neither does your anonymous class (and in fact - it can't).
So you have two options of solving the problem:
Catch and handle the exception:
btnInsert.setOnAction(e -> {
try {
Insert();
} catch (SQLException ex) {
// Log error, show error message, etc... Whichever is applicable for your application
}
});
Rethrow an un-checked exception:
btnInsert.setOnAction(e -> {
try {
Insert();
} catch (SQLException ex) {
throw new RuntimeException(ex); // Or any other subclass of RuntimeException or Error
}
});
As to choosing between the two options - Oracle's documentation says this:
Here's the bottom line guideline: If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.
Of course, this could all be moved away from the actual EventHandler, so it can be called on a method that is checked-exception-free.
I was playing around with some of my code and came across something I didn't fully understand. I have a class called SentimentClassifier, the constructor of which looks like this:
public SentimentClassifier(final int nGramToBeUsed) {
try {
classifier = (DynamicLMClassifier<?>) AbstractExternalizable.readObject(new File(etc));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
I have another class which creates this one, like so:
public TwitterManager(final int nGramToBeUsed) {
sentimentClassifier = new SentimentClassifier(nGramToBeUsed);
}
If I run the code like this, everything works fine. But if I change the first class from using try/catch to throw the exception, like so:
public SentimentClassifier(final int nGramToBeUsed) throws ClassNotFoundException, IOException {
classifier = (DynamicLMClassifier<?>) AbstractExternalizable.readObject(new File(etc));
}
Suddenly the second class complains that the IOException isn't being handled. Why is this thrown only for the thrown exception and not for the try/catch?
When you call a method M1 from another method M2:
If some code in M1 raises some Checked Exception, and the method M1 itself handles it, rather than throwing it, you don't have to worry about the exception while calling it.
Now, if the exception raised in M1, is not being handled in M1 itself, rather it is propagated up the stack trace, then M1 must declare that exception in the throws clause. This is just for the convenience of the calling method to know that it should be ready to handle those exception in case they are thrown. This is only the case with Checked Exception.
But if the calling method M2, doesn't handle that exception, it has the option to re-declare that exception to be thrown in it's own throws clause, in which case the exception will be propagated further up the stack trace.
If method M2 does neither of the previous two task, you will get a compiler error. Because you haven't given any proper path or way to handle the exception that can be thrown.
Note all the above arguments are true for Checked Exception only. For Unchecked exception, you don't need to handle it yourself, neither you need to declare it in throws clause.
Suggested Read:
Java: checked vs unchecked exception explanation
Unchecked Exception controversies
JLS - The Kinds and Causes of Exceptions
In Java, if a method declares that throws an Exception (other than RuntimeException), callers must handle the exception. They can do this one of two ways: catch it, or declare that they themselves throw it.
You moved the handling of these two exceptions from the SentimentClassifier constructor to its callers.
If the constructor declares any exceptions, the calling code must handle them or declare them. After all, the constructor could throw/propagate these exceptions, and any code that calls it must handle them.
When you catch an exception, it means that you will deal with it on the catch block, and its consequences, so the external code can continue to progress without being warned about the internal exception.
If your exception is thrown, you are forcing by contract to any creator/invoker class to deal with any declared exception that could be produced during the initialization/execution process, as it can be critical for the business logic.
In this case, if the exceptions that can be generated during init are critical, and could stop the class from working properly, they should be thrown, as the creator class TwitterManager could have a disfuncional or partially initialized instance of the SentinelClassifier object, leading to unexpected errors.
I've just started my very first toy-project in java and faced with misunderstanding of how it should be done. I'm using java.util.logging and JUnit4 library.
For example we have something like this:
public class SomeClass {
private static Logger log = Logger.getLogger(SomeClass.class.getName());
public static void SomeMethod() {
try{
...some code...
} catch(Exception e){
log.warning("Something bad happened");
}
}
And the unit-test will be:
#Test
public void SomeClassTest(){
SomeClass.SomeMethod();
}
But there will never be an exception, cause I've already handled it in method.
Should I generate new exception in catch-block? Or may be using junit combined with logging is not a good idea?
A method that does not throw an exception (and returns the expected value if any) is meant to work correctly from the perspective of a user.
So you should use try - catch and logging inside a method, when you can catch an exception and the method will still work correctly (do something else when this error happens for example but still return the expected result or perform the supposed operation).
In this case the unit test should check if the operation was performed correctly (if the object is in the expected state and the result value (in your case void) is correct
You should rethrow the exception (and usually not log it, but that depends) if the method cannot do what it is supposed to do when the exception occurs.
In this case the unit test should check if the operation was performed correctly (if the object is in the expected state and the result value (in your case void) is correct if there is no exception, and if there is an exception it should check if this exception was expected
If you want to test that the exception is thrown then you would have to re-throw, or not catch, the Exception.
Otherwise you can unit test that the class is in the correct state after the exception, i.e. that the exception was correctly handled.
I would say one other thing. Don't catch(Exception e), catch the specific exception you are expecting. Otherwise you will handle other, unexpected, exceptions in the same way and that is really quite dangerous.
You can simply rethrow the caught exception:
public class SomeClass {
private static Logger log = Logger.getLogger(SomeClass.class.getName());
public static void SomeMethod() {
try {
// your stuff
} catch (Exception e) {
log.warning("Something happened");
throw e;
}
}
}
Should I generate new exception in catch-block?
No. don't do that! you can test your existing code! when you only want to log the message but you don't want to handle it in the method that call someMethod() don't throw it!
using junit combined with logging is not a good idea?
both are good ideas and can be used together without problems.
Think about how you can test your method. i would not modify the code just that you can easily test it. because you WANTED to catch the exception and log for a reason.
try verifing what variables or objects are modified in your test-method
Suppose i have a method that may fail with a checked exception (checked because it is recoverable, according to Sun's recommendations).
This method fails and it triggers a recovery strategy.
But both the initial method and the recovery strategy failed.
In some cases i may want to have both stacktraces so that i know why both the initial and recovery strategies failed, and not only the last one.
What can i do?
Should i create a CompositeException type or something like that? Is it a good practice?
Java 7 has introduced the concept of a suppressed exception. For instance, the try-with-resources statement is specified by:
Resources are closed in the reverse order from that in which they were initialized. A resource is closed only if it initialized to a non-null value. An exception from the closing of one resource does not prevent the closing of other resources. Such an exception is suppressed if an exception was thrown previously by an initializer, the try block, or the closing of a resource.
and
If the initialization of the resource completes normally, and the try block completes abruptly because of a throw of a value V, then:
If the automatic closing of the resource completes abruptly because of a throw of a value V2, then the try-with-resources statement completes abruptly because of a throw of value V with V2 added to the suppressed exception list of V.
This uses java.lang.Throwable.addSuppressedException, whose javadoc reads:
Appends the specified exception to the exceptions that were suppressed in order to deliver this exception. This method is thread-safe and typically called (automatically and implicitly) by the try-with-resources statement.
The suppression behavior is enabled unless disabled via a constructor. When suppression is disabled, this method does nothing other than to validate its argument.
Note that when one exception causes another exception, the first exception is usually caught and then the second exception is thrown in response. In other words, there is a causal connection between the two exceptions. In contrast, there are situations where two independent exceptions can be thrown in sibling code blocks, in particular in the try block of a try-with-resources statement and the compiler-generated finally block which closes the resource. In these situations, only one of the thrown exceptions can be propagated. In the try-with-resources statement, when there are two such exceptions, the exception originating from the try block is propagated and the exception from the finally block is added to the list of exceptions suppressed by the exception from the try block. As an exception unwinds the stack, it can accumulate multiple suppressed exceptions.
An exception may have suppressed exceptions while also being caused by another exception. Whether or not an exception has a cause is semantically known at the time of its creation, unlike whether or not an exception will suppress other exceptions which is typically only determined after an exception is thrown.
Note that programmer written code is also able to take advantage of calling this method in situations where there are multiple sibling exceptions and only one can be propagated.
That last paragraph seems to apply to your situation. So you could do:
public static void main(String[] args) throws Exception {
try {
throw new RuntimeException("Not now!");
} catch (Exception e) {
try {
tryAgain();
} catch (Exception e2) {
e.addSuppressed(e2);
throw e;
}
}
}
Then, the stack trace will contain both exceptions:
Exception in thread "main" java.lang.RuntimeException: Not now!
at tools.Test.main(Test.java:12)
Suppressed: java.lang.RuntimeException: I'm on holiday.
at tools.Test.tryAgain(Test.java:7)
at tools.Test.main(Test.java:15)
but only the primary exception can be caught by the caller.
I would consider an exception for when the initial method fails and another for when the recovery strategy fails.
You may want to do something like try the recovery strategy multiple times before throwing a exception that recovery failed (e.g. retry and fail when timeout occurs).
It seems like keeping the initial method and recovery strategy exceptions separated makes sense, as they represent two different scenarios.
Unfortunately, a Java Exception only has one cause, so a CompositeException may be your best option. However, you can override the printStackTrace methods to print the stack traces of your composite exceptions:
public class CompositeException extends Exception {
private final List<Throwable> causes = new ArrayList<Throwable>();
public CompositeException(Throwable... causes) {
this.causes.addAll(Arrays.asList(causes));
}
// Other constructors you want
#Override
public void printStackTrace() {
if (causes.isEmpty()) {
super.printStackTrace();
return;
}
for (Throwable cause : causes) {
cause.printStackTrace();
}
}
#Override
public void printStackTrace(PrintStream s) {
if (causes.isEmpty()) {
super.printStackTrace(s);
return;
}
for (Throwable cause : causes) {
cause.printStackTrace(s);
}
}
#Override
public void printStackTrace(PrintWriter s) {
if (causes.isEmpty()) {
super.printStackTrace(s);
return;
}
for (Throwable cause : causes) {
cause.printStackTrace(s);
}
}
}
This is about all you can do to have multiple cause exceptions in one exception. To use it:
CompositeException ce = new CompositeException(ex1, ex2, ex3);
Then ce.printStackTrace() will print all 3 exceptions' stack traces.
What do you exactly mean with "I may want to have both stacktraces"? What I use to do is log both, since they're "things that should not happen". It allows you to check the log and trace what is wrong. If you do "CompositeException" you'll soon explode on combinatory issues: what if "CompositeExceptionHandler" also fails?
I would...
Trace the first exception and act if you can. Otherwise and raise a custom exception.
Catch the second one and act accordingly.
That way you improve coupling. You handle both levels independently