No need to declare checked exceptions in throws clause or handling them in try/catch block in scala is the feature that I love. But it can be a problem when exception must be handled but was ignored. I'm looking for tools (maybe compiler flag/plugin) to find methods that ignored checked exceptions.
One option is catch the exception at a very high level of you application (The top would be the main-method).
Another option would be to use an UncaughtExceptionHandler (if you are on a JVM):
object MyUncaughtExceptionHandler extends Thread.UncaughtExceptionHandler {
def uncaughtException(thread: Thread, throwable: Throwable) {
println("Something bad happened!")
}
}
val t = new Thread(new Runnable {
override def run() {
null.toString
}
});
t.setUncaughtExceptionHandler(MyUncaughtExceptionHandler)
t.start()
AFAIK, there is no such tools, however one technique I've used successfully is to simply install an at-throw-point break point in your IDE (IntelliJ or Eclipse) for java.lang.Throwable which will pause execution at throw point of every java exception (or error) as the program runs and then to keep hitting "play" to see them all (at least on the path of execution you're interested in)
Cheers...
Related
I would like to know the guarantees of the following pattern:
try {
//business logic here
} catch {
case t: Throwable =>
//try to signal the error
//shutdown the app
}
I'm interested in catching all unexpected exceptions (that can be thrown by any framework, library, custom code etc...), trying to record the error and shutting down the virtual machine.
In Scala what are the guarantees of the catch Throwable exception? Are there any differences with the java Exception hierarchy to take in consideration?
Throwable is defined in the JVM spec:
An exception in the Java Virtual Machine is represented by an instance of the class Throwable or one of its subclasses.
which means that both Scala and Java share the same definition of Throwable. In fact, scala.Throwable is just an alias for java.lang.Throwable. So in Scala, a catch clause that handles Throwable will catch all exceptions (and errors) thrown by the enclosed code, just like in Java.
There are any difference with the java Exception hierarchy to take in consideration?
Since Scala uses the same Throwable as Java, Exception and Errors represent the same things. The only "difference" (that I know of) is that in Scala, exceptions are sometimes used under the hood for flow control, so that if you want to catch non-fatal exceptions (thus excluding Errors), you should rather use catch NonFatal(e) instead of catch e : Exception. But this doesn't apply to catching Throwable directly
All harmless Throwables can be caught by:
try {
// dangerous
} catch {
case NonFatal(e) => log.error(e, "Something not that bad.")
}
This way, you never catch an exception that a reasonable application should not try to catch.
this is a test program:
object Test {
def main(args: Array[String]): Unit = {
// there is an unhandled exception in here, I expect program can remind me, and I can handled it before running.
myException()
}
def myException: Unit ={
throw new Exception
}
}
In Java, when I called a method with unhandling exception, the program will occur error, and tell you add throws declaration or surround with try/catch.
How to know the program have unhandled exceptions before running in Scala?
Scala has a somewhat different philosophy with regards to Exceptions.
The rule of thumb is to not use them unless for something truly exceptional and, thus "let it fail". The reason invoked behind this rule is that, in FP terms, exceptions break referential transparency.
The good practice is to use Either or Option to handle/wrap "errors" rather than throwing exceptions. (the link provided by #Tawkir seems a good read)
Unfortunately this does not help when interfacing with Java code which often uses Exceptions for program control flow, and the compiler will not help you there. A practical way around this is to wrap Exception throwing code with a Try and then call recover or recoverWith to handle these exceptions and, say, wrap them in another structure.
Please note that you can mark a scala method with an #throws annotation to specify the Exception(s) that this method throws, but this should really be used when writing scala code meant to be used by a Java caller expecting an Exception to be thrown.
There's no distinction between checked and unchecked exceptions in the JVM. This is only enforced in the Java compiler, based on whether the class extends RuntimeException or not. Scala compiler doesn't check it, so, there is no way to know, does program have unhandled unchecked exceptions, or not.
This is a rather general question, but hopefully a reasonable one. When is ExecutionContext#reportFailure(Throwable) called?
It doesn't seem to be called in the Scala standard library. I suppose I perhaps should call it in some circumstances? What are these?
This method reports exceptions that cannot be reported otherwise.
It is called when an exception happens during the execution of a callback that has no other way of reporting failure. In particular, calls to Future.onComplete (e.g. via Future.foreach) return Unit and may be executed on any thread, so they have no way of reporting failure back to their callers. When an exception is thrown within onComplete, it is sent to this method.
It is called a couple of times deep within the implementation for Promise in the standard library. See the source.
try onComplete(value) catch { case NonFatal(e) => executor reportFailure e }
An ExecutionContext can implement reportFailure to execute arbitrary code when a future/promise fails. The only thing in the standard library that implements this method is ExecutionContextImpl, which is not in the public API, but found here. This class accepts a reporter: Throwable => Unit function. The default ExecutionContext.Implicits.global uses ExecutionContext.defaultReporter, which simply prints the stack trace to System.err.
If you wanted to customize the behavior, you could need to define your own ExecutionContext. It's difficult to imagine a scenario where you'd want to produce some other side-effect other than logging the stack trace, or some other kind of logging.
What is the analogous in manners of scala Try to:
timer.start()
try {
doThis()
} finally {
timer.cancel()
}
Given that an exception inside a Try simply creates a Failure value (as opposed to transferring control to an outer catch block when using try), the code in your original finally block would just need to be executed after the Try.
In other words, this will do:
timer.start()
val result = Try{
doThis()
}
timer.cancel()
result
As far as I know there is no built-in shortcut that would allow to avoid capturing result just to return it as is.
Since Try won't throw an exception in your program flow I believe just write the following:
timer.start()
Try(doThis())
timer.cancel()
You can assign Try(doThis()) to a value and process it further if you wish to process the exception (rather than blindly ignoring it) or the call result.
How about
Try {
scala.util.control.Exception.ultimately {
timer.cancel()
} {
doThis()
}
}
?
Despite other answers saying otherwise, the correct answer is a Try cannot be completely analogous to a traditional try...finally. The reason for this is Try will ignore certain types of exceptions including InterruptedException, ControlThrowable, and others.
Consider if you use Try as recommended by other answers:
lock.lock()
val t = Try(doStuff()) // Doesn't absorb all types of exceptions!
lock.unlock() // THIS MIGHT BE SKIPPED!!!
t.get
If the thread is interrupted during doStuff(), then an InterruptedException will be thrown, and Try will rethrow it instead of creating a Failure! This will cause lock.unlock() to be skipped (and you'll probably deadlock). The same will happen if doStuff() invokes a lambda that invokes a non-local return (which throws a sub-type of ControlThrowable).
This is likely why the standard Scala library does not include a finally method in the Try class -- because it wouldn't work properly.
However, there is some good news. Scala 2.13 introduces Using which essentially performs a try-with-resources. We can trick this into doing a more general try...finally by using a dummy resource:
Using(lock.lock())(_ => doStuff())(_ => lock.unlock())
And if you don't have anything that is idiomatically performed before the try, then you can provide a Unit in the first parameter list:
Using(())(_ => doStuff())(_ => lock.unlock())
But in any case, Try is not going to do the job.
If a Scala future fails, and there is no continuation that "observes" that failure (or the only continuations use map/flatMap and don't run in case of failure), then errors go undetected. I would like such errors to be at least logged, so I can find bugs.
I use the term "observed error" because in .Net Tasks there is the chance to catch "unobserved task exceptions", when the Task object is collected by the GC. Similarly, with synchronous methods, uncaught exceptions that terminate the thread can be logged.
In Scala futures, to 'observe' a failure would mean that some continuation or other code reads the Exception stored in the future value before that future is disposed. I'm aware that finalization is not deterministic or reliable, and presumably that's why it's not used to catch unhandled errors, although .Net does succeed in doing this.
Is there a way to achieve this in Scala? If not, how should I organize my code to prevent unhandled error bugs?
Today I have andThen checkResult appended to various futures. But it's hard to know when to use this and when not to: if a library method returns a Future, it shouldn't checkResult and log errors itself, because the library user may handle the failure, so the responsibility falls onto the user. As I edit code I sometimes need to add checks and sometimes to remove them, and such manual management is surely wrong.
I have concluded there is no way to generically notice unhandled errors in Scala futures.
You can just use Future.recover in the function that returns the Future.
So for instance, you could just "log" the error and rethrow the original exception, in the simplest case:
def libraryFunction(): Future[Int] = {
val f = ...
f.recover {
case NonFatal(t) =>
println("Error : " + t)
throw t
}
}
Note the use of NonFatal to match all the exception types it is sensible to catch.
That recover block could equally return an alternative result if you wish.