We have a system that is possible to customise using groovy scripts and I've spotted a very strange effect on the type of exceptions throw from these scripts.
We have a groovy script with the following:
process {
throw new Exception("weeee")
}
Process is defined as a Closure in the base class of the script:
public abstract class ScriptBaseClass extends Script {
Closure process;
public void process( Closure code ) {
process = (Closure) code.clone();
}
}
In the Java class that actually runs the scripts we have the following method (omitted all the set up code as it doesn't seem relevant):
public void process() {
try {
script.process.call();
} catch (Exception e) {
logger.debug("exception thrown from groovy script", e);
throw e;
}
}
Note the process method here doesn't declare it throws any exceptions. However it quite clearly re-throws the Exception e that it caught. This code is valid, it compiles and runs quite happily. It throws the Exception as I wanted.
Does any one know how this is legal code? In theory I shouldn't be able to throw a checked exception out of a method that doesn't declare that it throws it.
It works because Java compiler (starting since Java 7) can determine re-thrown exception. For catch (Exception e) it thinks it's RuntimeException because there were no other (checked) exception declared in call().
You can read about it there, for example: https://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
So this code compiles perfectly:
public void xxxxx() {
try {
System.out.println('Hi!'); //or anything else w/o declared exceptions
} catch (Exception e) {
throw e;
}
}
Java compiled sees that only RuntimeException could be caught here, so it doesn't ask you do declare anything.
But for this:
public void xxxxx() {
try {
throw new IOException(); //or anything that have declared checked exception
} catch (Exception e) {
throw e;
}
}
it will fail to compile, because IOException could be caught and re-thrown
Introducing closures or anything Groovy related is unnecessary complexity. The following is valid Java code:
public class Demo {
public void someMethod() {
try {
System.out.println("Hello");
} catch (Exception e) {
throw e;
}
}
}
Note that the following is not valid and will not compile:
import java.sql.*;
public class Demo {
public void someMethod() {
try {
Connection c = DriverManager.getConnection("", "", "");
} catch (SQLException e) {
throw e;
}
}
}
Groovy and the JVM don't really care about an exception being a checked one or not. Only the Java compiler cares about this here. In fact you can use the catch on any RuntimeException or its parent classes (of which Exception is one) without requiring it being declared as thrown from something called in the try-block. So it is fine by the compiler to catch Exception or Throwable even. Of course, from a program logic view it is an entirely different matter.
Related
Why does the following code compile fine, but the method being called does not need to throw Exception? Isn't Exception a checked exception and not an unchecked exception? Please clarify.
class App {
public static void main(String[] args) {
try {
amethod();
System.out.println("try ");
} catch (Exception e) {
System.out.print("catch ");
} finally {
System.out.print("finally ");
}
System.out.print("out ");
}
public static void amethod() { }
}
If I want to use a try catch with IOexception (a checked exception), the method being called needs to throw IOException. I get this.
import java.io.IOException;
class App {
public static void main(String[] args) {
try {
amethod();
System.out.println("try ");
} catch (IOException e) {
System.out.print("catch ");
} finally {
System.out.print("finally ");
}
System.out.print("out ");
}
public static void amethod() throws IOException { }
}
Isn't 'Exception' a checked exception and not an unchecked exception?
Yes, it is.
But even if we know the method doesn't throw Exception itself, the code catch(Exception e){ could still execute. The code in the try block could still throw something that inherits from Exception. That includes RuntimeException and its subclasses, which are unchecked.
catch(IOException e){, on the other hand, can only catch checked exceptions. (Java doesn't allow multiple inheritance, so anything that's a subclass of IOException can't possibly be a subclass of RuntimeException.) The compiler can fairly easily figure out that none of the code in the try block can possibly throw an IOException (since any method throwing a checked exception must explicitly say so) which allows it to flag the code.
Normally there would be a compiler error for having a try block that never throws a checked exception that you have a catch block for, but the behavior you're observing comes from the fact that the Java Language Specification treats Exception specially in this circumstance. According to ยง11.2.3:
It is a compile-time error if a catch clause can catch checked exception class E1 and it is not the case that the try block corresponding to the catch clause can throw a checked exception class that is a subclass or superclass of E1, unless E1 is Exception or a superclass of Exception.
This is reasonable because Exception (and its superclass Throwable) can be used to catch exceptions that extend RuntimeException also. Since runtime exceptions are always possible, the compiler always allows Exception to appear in a catch clause regardless of the presence of checked exceptions.
I have some code that might throw both checked and runtime exceptions.
I'd like to catch the checked exception and wrap it with a runtime exception. But if a RuntimeException is thrown, I don't have to wrap it as it's already a runtime exception.
The solution I have has a bit overhead and isn't "neat":
try {
// some code that can throw both checked and runtime exception
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
Any idea for a more elegant way?
I use a "blind" rethrow to pass up checked exceptions. I have used this for passing through the Streams API where I can't use lambdas which throw checked exceptions. e.g We have ThrowingXxxxx functional interfaces so the checked exception can be passed through.
This allows me to catch the checked exception in a caller naturally without needing to know a callee had to pass it through an interface which didn't allow checked exceptions.
try {
// some code that can throw both checked and runtime exception
} catch (Exception e) {
throw rethrow(e);
}
In a calling method I can declare the checked exception again.
public void loadFile(String file) throws IOException {
// call method with rethrow
}
/**
* Cast a CheckedException as an unchecked one.
*
* #param throwable to cast
* #param <T> the type of the Throwable
* #return this method will never return a Throwable instance, it will just throw it.
* #throws T the throwable as an unchecked throwable
*/
#SuppressWarnings("unchecked")
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T {
throw (T) throwable; // rely on vacuous cast
}
There is a lot of different options for handling exceptions. We use a few of them.
https://vanilla-java.github.io/2016/06/21/Reviewing-Exception-Handling.html
Guava's Throwables.propagate() does exactly this:
try {
// some code that can throw both checked and runtime exception
} catch (Exception e) {
throw Throwables.propagate(e);
}
UPDATE: This method is now deprecated. See this page for a detailed explanation.
Not really.
If you do this a lot, you could tuck it away into a helper method.
static RuntimeException unchecked(Throwable t){
if (t instanceof RuntimeException){
return (RuntimeException) t;
} else if (t instanceof Error) { // if you don't want to wrap those
throw (Error) t;
} else {
return new RuntimeException(t);
}
}
try{
// ..
}
catch (Exception e){
throw unchecked(e);
}
I have a specially compiled .class file containing the following:
public class Thrower {
public static void Throw(java.lang.Throwable t) {
throw t;
}
}
It just works. The java compiler would normally refuse to compile this, but the bytecode verifier doesn't care at all.
The class is used similar to Peter Lawrey's answer:
try {
// some code that can throw both checked and runtime exception
} catch (Exception e) {
Thrower.Throw(e);
}
You can rewrite the same using instanceof operator
try {
// some code that can throw both checked and runtime exception
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw e;
} else {
throw new RuntimeException(e);
}
}
However, your solution looks better.
The problem is that Exception is too broad. You should know exactly what the possible checked exceptions are.
try {
// code that throws checked and unchecked exceptions
} catch (IOException | SomeOtherException ex) {
throw new RuntimeException(ex);
}
The reasons why this wouldn't work reveal deeper problems that should be addressed instead:
If a method declares that it throws Exception then it is being too broad. Knowing that "something can go wrong" with no further information is of no use to a caller. The method should be using specific exception classes in a meaningful hierarchy, or using unchecked exceptions if appropriate.
If a method throws too many different kinds of checked exception then it is too complicated. It should either be refactored into multiple simpler methods, or the exceptions should be arranged in a sensible inheritance hierarchy, depending on the situation.
Of course there can be exceptions to the rule. Declaring a method throws Exception can be perfectly reasonable if it's consumed by some kind of cross-cutting framework (such as JUnit or AspectJ or Spring) rather than comprising an API for others to use.
I generally use the same type of code structure, but condense it down to one line in one of the few times a ternary operator actually makes code better:
try {
// code that can throw
}
catch (Exception e) {
throw (e instanceof RuntimeException) ? (RuntimeException) e : new RuntimeException(e);
}
This does not require additional methods or catch blocks which is why I like it.
lombok has this handled with a simple annotation on the method ๐
Example:
import lombok.SneakyThrows;
#SneakyThrows
void methodThatUsusallyNeedsToDeclareException() {
new FileInputStream("/doesn'tMatter");
}
In the example the method should have declared throws FileNotFoundException, but with the #SneakyThrows annotation, it doesn't.
What actually happens behind the scenes is that lombok does the same trick as the high rated answer to this same question.
Mission accomplished!
I have the following code
public static void nocatch()
{
try
{
throw new Exception();
}
finally
{
}
}
Which gives the error
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type CustomException
My Question is why was it designed that the catch block is optional, when there is no way of getting around not having a catch?
From finally()'s perspective, I understand that
finally should have atleast a try block, catch is optional. The point of finally blocks is to make sure stuff gets cleaned up whether an exception is thrown or not. As per the JLS
A finally clause ensures that the finally block is executed after the try block and any catch block that might be executed, no matter how control leaves the try block or catch block.
Edit:
By adding a return in the finally block, compiler does not give the error WHY?!
public static void nocatch()
{
try
{
throw new Exception();
}
finally
{
return; //By adding this statement, the compiler error goes away! Please let me know why
}
}
My Question is why was it designed that the catch block is optional, when there is no way of getting around not having a catch?
Yes there is: Declare that the method throws the exception:
public static void nocatch() throws CustomException
{
try
{
throw new CustomException();
}
finally
{
}
}
try/finally without catch is to ensure that you clean up anything you need to clean up, even if you aren't handling the exception yourself. (Be sure not to allow any other exception to be thrown from within finally, or you'll hide the primary exception.)
Here's an example to play with (live copy):
private static class CustomException extends Exception {
}
public static void main (String[] args) throws java.lang.Exception
{
try
{
System.out.println("Calling nocatch(false)");
nocatch(false);
}
catch (CustomException ce) {
System.out.println("Caught CustomException for false case");
}
try
{
System.out.println("Calling nocatch(true)");
nocatch(true);
}
catch (CustomException ce) {
System.out.println("Caught CustomException for true case");
}
}
public static void nocatch(boolean foo) throws CustomException
{
try
{
if (foo) {
System.out.println("Throwing");
throw new CustomException();
}
}
finally
{
System.out.println("In finally");
}
System.out.println("Reached outside the try/finally block");
}
Output:
Calling nocatch(false)
In finally
Reached outside the try/finally block
Calling nocatch(true)
Throwing
In finally
Caught CustomException for true case
As you can see, the finally block's code runs regardless of whether an exception occurred, but the code after the try/finally doesn't.
Re your follow-up asking why adding return within the finally makes the error go away:
try
{
throw new CustomException();
}
finally
{
return; // <=== Makes the compiler happy (but don't do it!)
}
Interesting edge case! It's because the code in the finally block always runs, and so you'll always return rather than throw, hiding the exception that occurred. E.g., this is the sequence:
throw new CustomException() throws the exception, which transfers control to the finally block
Code in the finally block issues a normal return from the method
This hides the fact the exception occurred; in effect, you've "handled" the exception (without actually handling it) via the finally block. In general, this isn't a good idea; use catch to handle exceptions, or declare them on the method so calling code can handle them.
Suppose I have a class and a method
class A {
void foo() throws Exception() {
...
}
}
Now I would like to call foo for each instance of A delivered by a stream like:
void bar() throws Exception {
Stream<A> as = ...
as.forEach(a -> a.foo());
}
Question: How do I properly handle the exception? The code does not compile on my machine because I do not handle the possible exceptions that can be thrown by foo(). The throws Exception of bar seems to be useless here. Why is that?
You need to wrap your method call into another one, where you do not throw checked exceptions. You can still throw anything that is a subclass of RuntimeException.
A normal wrapping idiom is something like:
private void safeFoo(final A a) {
try {
a.foo();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
(Supertype exception Exception is only used as example, never try to catch it yourself)
Then you can call it with: as.forEach(this::safeFoo).
If all you want is to invoke foo, and you prefer to propagate the exception as is (without wrapping), you can also just use Java's for loop instead (after turning the Stream into an Iterable with some trickery):
for (A a : (Iterable<A>) as::iterator) {
a.foo();
}
This is, at least, what I do in my JUnit tests, where I don't want to go through the trouble of wrapping my checked exceptions (and in fact prefer my tests to throw the unwrapped original ones)
This question may be a little old, but because I think the "right" answer here is only one way which can lead to some issues hidden Issues later in your code. Even if there is a little Controversy, Checked Exceptions exist for a reason.
The most elegant way in my opinion can you find was given by Misha here Aggregate runtime exceptions in Java 8 streams
by just performing the actions in "futures". So you can run all the working parts and collect not working Exceptions as a single one. Otherwise you could collect them all in a List and process them later.
A similar approach comes from Benji Weber. He suggests to create an own type to collect working and not working parts.
Depending on what you really want to achieve a simple mapping between the input values and Output Values occurred Exceptions may also work for you.
If you don't like any of these ways consider using (depending on the Original Exception) at least an own exception.
You might want to do one of the following:
propagate checked exception,
wrap it and propagate unchecked exception, or
catch the exception and stop propagation.
Several libraries let you do that easily. Example below is written using my NoException library.
// Propagate checked exception
as.forEach(Exceptions.sneak().consumer(A::foo));
// Wrap and propagate unchecked exception
as.forEach(Exceptions.wrap().consumer(A::foo));
as.forEach(Exceptions.wrap(MyUncheckedException::new).consumer(A::foo));
// Catch the exception and stop propagation (using logging handler for example)
as.forEach(Exceptions.log().consumer(Exceptions.sneak().consumer(A::foo)));
I suggest to use Google Guava Throwables class
propagate(Throwable throwable)
Propagates throwable as-is if it is an
instance of RuntimeException or Error, or else as a last resort, wraps
it in a RuntimeException and then propagates.**
void bar() {
Stream<A> as = ...
as.forEach(a -> {
try {
a.foo()
} catch(Exception e) {
throw Throwables.propagate(e);
}
});
}
UPDATE:
Now that it is deprecated use:
void bar() {
Stream<A> as = ...
as.forEach(a -> {
try {
a.foo()
} catch(Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
});
}
You can wrap and unwrap exceptions this way.
class A {
void foo() throws Exception {
throw new Exception();
}
};
interface Task {
void run() throws Exception;
}
static class TaskException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TaskException(Exception e) {
super(e);
}
}
void bar() throws Exception {
Stream<A> as = Stream.generate(()->new A());
try {
as.forEach(a -> wrapException(() -> a.foo())); // or a::foo instead of () -> a.foo()
} catch (TaskException e) {
throw (Exception)e.getCause();
}
}
static void wrapException(Task task) {
try {
task.run();
} catch (Exception e) {
throw new TaskException(e);
}
}
More readable way:
class A {
void foo() throws MyException() {
...
}
}
Just hide it in a RuntimeException to get it past forEach()
void bar() throws MyException {
Stream<A> as = ...
try {
as.forEach(a -> {
try {
a.foo();
} catch(MyException e) {
throw new RuntimeException(e);
}
});
} catch(RuntimeException e) {
throw (MyException) e.getCause();
}
}
Although at this point I won't hold against someone if they say skip the streams and go with a for loop, unless:
you're not creating your stream using Collection.stream(), i.e. not straight forward translation to a for loop.
you're trying to use parallelstream()
Scala doesn't have checked exceptions. However, when calling scala code from java, it's desirable to catch exceptions thrown by scala.
Scala:
def f()=
{
//do something that throws SomeException
}
Java:
try
{ f() }
catch (SomeException e)
{}
javac doesn't like this, and complains that "this exception is never thrown from the try statement body"
Is there a way to make scala declare that it throws a checked exception?
Use a throws annotation:
#throws(classOf[SomeException])
def f()= {
//do something that throws SomeException
}
You can also annotate a class constructor:
class MyClass #throws(classOf[SomeException]) (arg1: Int) {
}
This is covered in the Tour of Scala
You can still catch too many exceptions and then re-throw the ones you can't handle:
try { f(); }
catch (Exception e) {
if (e instanceof SomeException) // Logic
else throw e;
}