How to "override" an exception in scala? - scala

so I have a method which already has a try block that throws ExceptionA. Now I need to put another try block where this method is being called and needs to throw an exception with some added details. Something like this:
method inner():
try{
//some logic
} catch {
throw new ExceptionA("exceptionA occurred")
}
method outer():
identifier = fromSomeDBCallPrivateToOuter()
try{
inner()
} catch {
// now either
// throw new Exception("Error with identifier" + identifier)
// or
// append identifier to thrown error from inner()
}
Can someone please provide any insight or suggestion on how to do this in Scala? Thanks in advance!

What you have in your snippet would work as written (if you correct the syntax), with a caveat, that exceptions are immutable (and even they weren't, it's still not a good idea to mutate them), so, instead of "appending" to exception, you'd need to create a new one, and set the original as cause.
It is more idiomatic in scala though to use Try monad instead of the "procedural" try/catch blocks. Something like this:
case class ExceptionB(id: String, original: ExceptionA)
extends Exception(s"Badness happened with id $id", original)
def outer(): Try[ReturnType] =
val id = getId()
Try {
inner
} recover {
case e: ExceptionA if iWannaNewException => throw new Exception(s"Id: id")
case e: ExceptionA => throw ExceptionB(id, e)
}

You can also use Either structure. This structure can return Right(value) if function completes without error or Left(message) containing information about error. You can adapt your code like below one:
def inner(): Either[String, Int] = {
if (checkSomeStuff()) Left("Cannot assigne identifier")
else Right(doSomeStuff())
}
def outer(): Either[String, Int] = {
inner() match {
case Left(error) => {
println("There is an error: " + error)
// you can also throw new Exception(s"Some info about $error") here
}
case Right(identifier) => {
println("Identifier : " + identifier)
doSomeStuffWithId() // do some staff for id
}
}
}
If you want to use Exceptions you need to choose who will handle the error case (in the inner or in the outer function).

Related

Scala "Try" return type and exception handling

I am a newbie for Scala and now am trying to complete an exercise. How can I return an InvalidCartException while the function return type is Try[Price]
//Success: return the calculated price
//Failure: InvalidCartException
def calculateCartPrice(cart:Cart): Try[Price] = {
if(isCartValid(cart)) {
//Calculations happen here
return Try(Price(totalPrice));
}
}
def isCartValid(cart: Cart): Boolean = {
//THIS WORKS FINE
}
Thank you for the help
If you mean "how to make the Try contain an exception", then use the Failure() like below:
def calculateCartPrice(cart:Cart): Try[Price] = {
if(isCartValid(cart)) {
//Calculations happen here
Success(Price(totalPrice));
} else {
Failure(new InvalidCartException())
}
}
Then, given a Try you can use getOrElse to get the value of success or throw the exception.
Try will catch the exception for you, so put the code that can throw the exception in there. For example
def divideOneBy(x: Int): Try[Int] = Try { 1 / x}
divideOneBy(0) // Failure(java.lang.ArithmeticException: / by zero)
If what you have is a Try and you want to throw the exception when you have a Failure, then you can use pattern matching to do that:
val result = divideByOne(0)
result match {
case Failure(exception) => throw exception
case Success(_) => // What happens here?
}
The Neophyte's Guide to Scala has lots of useful information for people new to Scala (I found it invaluable when I was learning).

Is there a way to chain `Try` as a monad while also not catching exceptions raised along the chain?

The Scala Try construct together with its flatMap does not work as I would expect or want it to. The TL;DR is that I want to do a series of operations that can fail in two ways: either by raising an exception, which should be promoted and caught higher up in the call stack, or by returning Failure, as the failure must logically be handled in different parts of the program.
I would expect something like this to do the trick:
def firstStepSucceeds(): Try[Int] = Try {
1
}
def secondStepThrows(input: Int) = {
throw new Exception("Exception thrown in second step")
}
// I expect this to propagate the exception thrown in secondStepThrows
firstStepSucceeds() flatMap (secondStepThrows _)
(Full Scastie with example)
However, in this case, the flatMap() call actually implicitly catches the uncaught exception thrown by secondStepThrows, which is not what I want (which is why I left out the Try block). Is there a way to get the same behaviour without the implicit exception-catching?
What happens in a Try should stay in a Try. Most Scala programmers would be very surprised if a function returning a Try also sometimes threw an exception.
The typical pattern if you want to handle exceptions in different places is to differentiate by the type of the exception. So
val partiallyRecoveredTry = originalTry.recover{
case _: SecondStepException => "second step had an exception"
}
// Further up the call stack
partiallyRecoveredTry.getOrElse("first step had an exception")
Try.flatMap() did not caught exceptions implicitely, it is the essence of Try.
When you use it, it is very explicit, and that's the goal.
I don't really understand what you want, but is something like that is possible for you ?
try {
val first = firstStepSucceeds()
val second = first.map(secondStepThrows).get
val third = secondStepFails(second)
// ...
}
catch {
case e: Exception => ???
}
I did some further experimentation, and what I ended up with was this reimplementation of Try as (the now right-biased and hence monadic) Either:
object CatchAll {
def apply[SomeType](block: => SomeType) = try { Right(block) }
catch { case e: Throwable => Left(e) }
}
def firstStepSucceeds() = CatchAll {
1
}
def firstStepFails() = CatchAll {
throw new Exception("First step failed")
}
def secondStepSucceeds(input: Int) = CatchAll {
input + 1
}
def secondStepFails(input: Int) = CatchAll {
throw new Exception("Second step failed in try block!")
}
def secondStepThrows(input: Int) = {
throw new Exception("Second step failed unexpectedly!")
}
firstStepSucceeds() flatMap (secondStepSucceeds _)
firstStepFails() flatMap (secondStepSucceeds _)
firstStepSucceeds() flatMap (secondStepFails _)
// This now throws an exception as expected
//firstStepSucceeds() flatMap (secondStepThrows _)

Two exceptions "at the same time", what is the proper way to handle this situation?

I have a situation where I need to call to foo method, if it fails call bar method, then re-throw the original exception (wrapped).
My problem is that bar method could fail too, and its exception information is important too.
When I create a new Exception there only one cause, and I have two. I could create something like class MyException(cause1, cause2) extends RuntimeException(cause1) but cause2 will be out of the standard mechanisms that exceptions have (stacktrace, etc).
Is there a better way to handle this situation?
The following code is a simplified example.
// I can't change this code
def foo:String = throw new FooException("foo method fails")
def bar:String = throw new BarException("bar method fails")
// my code
try {
foo
} catch {
case error1:FooException =>
try {
// if foo fails, I want to call bar
bar
throw new MyException("my exception", error1)
} catch {
case error2:BarException =>
// but bar could fail too
throw new MyException("my exception", ???)
// if my cause is error1, I lost error2 information (message and stack)
// if my cause is error2, I lost error1 information (message and stack)
}
}
Thank you in advance.
You can pack your MyException throwable with one or both of the "suppressed" exceptions.
val myEx = new MyException("my exception")
myEx.addSuppressed(error1)
myEx.addSuppressed(error2)
throw myEx
Then it's up to the catching code to unpack it.
case err : MyException =>
val arr :Array[Throwable] = err.getSuppressed
// arr contains all the "suppressed" exceptions that were added,
// stack traces and all
Still, it's arguably better to express the possibility of error in the type system rather than leave it to the (perhaps nonexistent) catching code to do the right thing.
import util.Try
val res :Either[List[Throwable],String] =
Try(foo).fold(fErr =>
Try(bar).fold(bErr => Left(fErr::bErr::Nil), _ => Left(fErr::Nil))
, Right(_))
From there you can proceed as needed.
res match {
case Right(s) => println(s) //foo result string
case Left(lst) =>
println(lst.map(_.getMessage()).mkString(",")) //foo method fails,bar method fails
lst.foreach(_.printStackTrace()) //both stack traces
}

How could I initialize val object in the try catch block?

I have this code in Scala, a object should be value not a variable, How can I initialize the a object in the try block?
object SomeObject {
private val a : SomeClass
try {
a=someThing // this statement may throw an exception
}
catch {
case ex: Exception=> {
ex.printStackTrace()
}
}
}
Scala tries to avoid undefined/null values. However, you can solve the problem by giving return values for the cases if the try fails and initializing a with the whole try expression:
private val a: SomeClass =
try {
someThing // this statement may throw an exception
} catch {
case ex: Exception => {
ex.printStackTrace()
someDefault
}
}
Update: In Scala it would be probably more idiomatic to use Try from scala.util:
val x : Int =
Try({
someThing
}).recoverWith({
// Just log the exception and keep it as a failure.
case (ex: Throwable) => ex.printStackTrace; Failure(ex);
}).getOrElse(1);
Try allows you to compose computations that can fail with an exception in various ways. For example, if you have two computations of type Try you can call
thing1.orElse(thing2).getOrElse(someDefault)
This runs thing1 and returns its result, if it's successful. If it fails, it continues with thing2. If it fails too, returns someDefault. You can also use recover or recoverWith to recover from some exceptions using partial functions (and potentially reuse those partial functions).
Since in Scala blocks have return values, and the last expression is the return value per default, you can do this:
object SomeObject {
private val a : SomeClass = { //this additional block not necessary, but added for clarity
try {
someThing // this statement may throw an exception
}
catch {
case ex: Exception=> {
ex.printStackTrace()
null
}
}
}
}
. However, I have to add that this looks like you're trying to accomplish something potentially blowing up in your face later - you will need null checks in any code that uses the value.

try block scope

I'm unhappy with the rule about variable scope in a try block not being shared with associated catch and finally blocks. Specifically it leads to code like the following:
var v: VType = null
try {
v = new VType()
}
catch {
case e => // handle VType constructor failure (can reference v)
}
finally {
// can reference v.
}
As opposed to:
try {
val v = new VType()
}
catch {
case e => // handle VType constructor failure (can reference v)
}
finally {
// can reference v.
}
Can anyone please explain or justify why this rule from Java persists?
and / or is there hope that this could change?
Thanks!
UPDATE
Many thanks for all the responses to date.
The consensus seems to imply "just get on with it" and I'm starting to conclude that perhaps technically what I want is either unsound, not worth the effort or hard to achieve.
I like Rex Kerr's answer but how would the original code above be wrapped in a method call without introducing a local var in the method body?
My own efforts weren't too good, using a by-name parameter to delay construction until safely in the try block works but still doesn't give me access to the constructed (or not) object in the catch or finally blocks.
Just "try" this ;)
val v = try { new VType() } catch { case e: Exception => /* ... */ }
In Scala, try is an expression, so it has a value.
You might be thinking about the problem the wrong way. Why do you want so much stuff in your try/catch/finally block? In your code,
try { val v = new VType() }
the exception could be thrown before you get v back, so you can't safely reference v. But if you can't reference v, then what can you do on the finally side that won't break or throw its own exception or have some other ill-defined behavior? What if you create v but fail to create w, but disposal requires having w as well? (Or doesn't?) It ends up being a mess.
But if you're coming from Java, there are a few things that can help you write try/catch/finally blocks in a sensible way.
One thing you can do is catch certain classes of exceptions and turn them into options instead:
def s2a(s: String) = try { Some(s.toInt) } catch { case nfe: NumberFormatException => None}
Another thing you can do is to create your own resource manager
def enclosed[C <: { def close() }](c: C)(f: C => Unit) {
try { f(c) } finally { c.close() }
}
enclosed(new FileInputStream(myFile))(fis => {
fis.read...
}
Or you can create your own shut-down-and-escape-safely method within another method:
val r = valuableOpenResource()
def attempt[F](f: => F) = {
try { f } catch { case re: ReasonableException => r.close() throw re }
}
doSomethingSafe()
attempt( doSomethingDangerous() )
doSomethingElseSafe()
r.close()
Between these different ways of handling things, I've not had much need to create vars to hold variables that I want to clean up later or otherwise deal with in catch or finally blocks.
How would this code work?
try
{
int i = 0;
// Do stuff...
Foo x = new Foo();
// Do more stuff...
Bar y = new Bar();
}
catch
{
// Print the values of i, x, and y.
}
What are the values of i, x, and y? Did y even get declared before we landed in the catch block?
The exception concept is not a subroutine of the try block, it is an alternate code flow. That makes at try-catch control block more like an "if anything untoward happens" then insert these (catch) lines in the current position of the try block, as needed.
With that in mind, it isn't clear if Val v = Type(); is going to be defined or not because the exception could (theoretically) be thrown before Val v = Type(); is evaluated. Yes, Val v is the first line in the block, but there are JVM errors which could be thrown before it.
Finally is another code construct which adds and alternate, but required, code flow the end of leaving the try-catch construct. Again, we have no idea how much (if any) of the try block was evaluated before the finally block was called, so we cannot depend on the declared variables within that block.
The only alternative left (now that we cannot use try block variables, due to their uncertainty of existence) is to use variable outside of the entire try-catch-finally construct for communications between the individual code blocks.
Does it suck? Maybe a little. Do we have anything that's better? Probably not. Putting the variable declarations outside of the block makes it obvious that the variables will have been defined prior to whatever control structure you process through in a try-catch-finally scenario.
If your main concern is that v should be immutable, you might get close to what you want with:
case class VType(name: String) {
// ... maybe throw an exception ...
}
val v = LazyVal(() => new VType())
try {
// do stuff with v
println(v.name) // implicitly converts LazyVal[VType] to VType
// do other unsafe stuff
} catch {
case e => // handle VType constructor failure
// can reference v after verifying v.isInitialized
} finally {
// can reference v after verifying v.isInitialized
if (v.isInitialized) v.safelyReleaseResources
}
where LazyVal is defined as
/**
* Based on DelayedLazyVal in the standard library
*/
class LazyVal[T](f: () => T) {
#volatile private[this] var _inited = false
private[this] lazy val complete = {
val v = f()
_inited = true
v
}
/** Whether the computation is complete.
*
* #return true if the computation is complete.
*/
def isInitialized = _inited
/** The result of f().
*
* #return the result
*/
def apply(): T = complete
}
object LazyVal {
def apply[T](f: () => T) = new LazyVal(f)
implicit def lazyval2val[T](l: LazyVal[T]): T = l()
}
It would be nice if we could use lazy val v = new VType(), but AFAIK there is no mechanism to safely determine whether a lazy val has been initialized.
Here's another alternative:
object Guard {
type Closing = {def close:Unit}
var guarded: Stack[Set[Closing]] = Stack()
def unapply(c: Closing) = {
guarded.push(guarded.pop + c)
Some(c)
}
private def close {println("Closing"); guarded.head.foreach{c => c.close}}
private def down {println("Adding Set"); guarded.push(Set())}
private def up {println("Removing Set"); guarded.pop}
def carefully(f: => Unit) {
down
try {f}
finally {close; up}
}
}
You can use it like this:
import Guard.carefully
class File {def close {println("Closed File")}}
class BadFile {def close {println("Closed Bad File")}; throw new Exception("BadFile failed")}
carefully {
val Guard(f) = new File
val Guard(g) = new File
val Guard(h) = new BadFile
}
which results in
Adding Set
Closing
Closed File
Closed File
java.lang.Exception: BadFile failed
So the first two files are created, then when the third constructor fails, the first two are automatically closed. All files are values.
Your example does not concretize why you need the finally clause. If VType is e.g. a resource that needs do be closed, you could do it one of the following ways.
1) You want to reference v after using it throws an exception:
try {
val v = new VType // may throw
try {
v.someThing // may throw
}
catch {
case ex => println("Error on doing something with v :" + v + ex) // or whatever
}
finally {
v.close()
}
}
catch {
case ex => println("Error on getting or closing v: " + ex) // v might not be constructed
}
2) You don't care about v in the catch clause:
try {
val v = new VType // may throw
try {
v.someThing // may throw
}
finally {
v.close()
}
}
catch {
case ex => println("Error on either operation: " + ex)
}
In either case, you get rid of the var.