Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java with Groovy handling of closures throwing Exceptions

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.

like image 808
Wil Selwood Avatar asked Aug 13 '15 09:08

Wil Selwood


People also ask

How do I create a custom exception in Groovy?

A try/catch block is placed around the code that might generate an exception. All of your code which could raise an exception is placed in the Protected code block. In the catch block, you can write custom code to handle your exception so that the application can recover from the exception.

How do you avoid throwing exceptions in Java?

The try-catch is the simplest method of handling exceptions. Put the code you want to run in the try block, and any Java exceptions that the code throws are caught by one or more catch blocks. This method will catch any type of Java exceptions that get thrown. This is the simplest mechanism for handling exceptions.


3 Answers

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

like image 114
Igor Artamonov Avatar answered Oct 25 '22 00:10

Igor Artamonov


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;
        }
    }
}
like image 38
Jeff Scott Brown Avatar answered Oct 24 '22 22:10

Jeff Scott Brown


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.

like image 31
blackdrag Avatar answered Oct 25 '22 00:10

blackdrag