I am having a trouble with my scala code below:
class ClassMyHelper {
protected var logger: Logger = LogManager.getLogger(classOf[AvroHelper])
def somefunc(schema: Schema, datum: GenericRecord): Array[Byte] = {
<code>
var byteData: Array[Byte] = null
try {
<code>
byteData = os.toByteArray()
//byteData
} catch {
case e: IOException =>
logger.error("IOException encountered!! ", e)
case e: Exception =>
logger.error("Something went wrong!! ", e)
} finally try os.close()
catch {
case e: IOException =>
logger.error("IOException encountered while closing output stream!! ", e)
case e: Exception =>
logger.error("Something went wrong while closing output stream!! ", e)
}
byteData //Unreachable code
}
}
The problem is that the last line in the somefunc function I am getting an unreachable code error.
Can you please help me in identifying what am I doing wrong here.
If you add a finally {} after the 2nd catch block things appear to clear up. I'm not sure why. I never use try/catch/finally myself. I prefer the Scala Try class from the Standard Library.
BTW, next time you post code please include the required imports, and check to make sure your code compiles as presented.
Related
I am having multiple resources and I want to quietly close them in the finally block.
Following is the current approach that I am using. Is there any better (preferably a more concise and readable) approach to achieve the same?
I am also looking for some cleaner way to eliminate the use of var for storing resources.
var connection1 = getConnection()
var connection2 = getConnection()
try {
// do stuff
} finally {
try {
if (connection1 != null) connection1.close()
} catch {
case NonFatal(_) => // log exception
}
try {
if (connection2 != null) connection2.close()
} catch {
case NonFatal(_) => // log exception
}
}
Edit: I know that I can keep a collection of resources and loop over them to close them making the code concise. However, I am curious whether there is some better scala construct to make it more concise.
With Scala 2.13 it is quite nice:
import scala.util.Using
import java.io.{FileReader, FileWriter}
Using.resources(
new FileReader("input.txt"),
new FileWriter("output.txt")) { (reader, writer) =>
???
}
This will do all the work for you.
I found this here: my-favorite-new-features-of-scala-2-13
There is also a link if you cannot use 2.13: scala-try-with-resources
I have some spark code, I need to catch all exception and store to file for some reason, so I tried to catch the exception and print it but its print empty
try {
/* Some spark code */
}
catch {
case e: Exception => {
println(" ************** " + e.printStackTrace())
}
}
output currently printing nothing ************** ()
printStackTrace doesn't return a stacktrace. It just prints it into the stderr. If you want to store it in the file you can
a) call e.getStackTrace and save each element manually
b) call e.printStackTrace(s) where s is a PrintStream or a PrintWriter pointing to your output file.
[Please find below the link that has answer to query][1]
Scala: Silently catch all exceptions
When I read from a directory in Scala, what is the proper way to catch the exceptions and how to initialize directory?
var directory = ??
try {
directory = new File(path)
}
catch {
}
if (directory.exists) {
You can wrap it in a Try:
Try(new File("path"))
.filter(_.exists)
.map(directory =>
// do something with the code
).recover{
case exc: Exception =>
// handle Exception
}
You can also replace the if with a filter.
In our Scala, Play, Reactivemongo we have a big problem with exception handling - when there is an error, in Iteratee/Enumeratee or in Actor system Play just swallows it, without logging any error to the output. So we effectively need to guess where, and why this error might happen.
We made Globals override, to always print the error, and specified logger.root=TRACE, but still saw no output, from which we could analyse our problems.
How to forcebly make Play print all the errors
Didn't found the way to explicitly log everything but there is a way to log exceptions locally.
I did this:
def recover[T] = Enumeratee.recover[T] {
case (e, input) => Logger.error("Error happened on:" + input, e)
}
and then used it on all the enumeratees that can produce errors
def transform(from: Enumerator[From]): Enumerator[String] = {
heading >>> (from &> recover[From] ><> mapper) >>> tailing
}
here, mapper throws exception, and they are all logged.
I think your problem is with how Future works in scala, let's take the following exemple :
val f :Future[Int]= Future {
throw new NullPointerException("NULL")
1
}
f.map(s1 => {println(s" ==> $s1");s" ==> $s1"})
This code will throw an exception but the stack trace will not be printed as futures handle the error.
If you want to get the error that happened you can
just call:
f.onComplete{
case Success(e) => {}
case Failure(e) => e.printStackTrace()
}
e is a throwable that you can use as you want to handle the error.
At the solution I used, is override through ErrorHandling in Play https://www.playframework.com/documentation/2.4.2/ScalaErrorHandling, basically creating ErrorHandler that logs all the errors, with needed detalization.
I am using scalatra to "export" a MongoDB data to JSon, my actions are very simple, like:
get("/") {
val title = db.get_collection("main", "api", "title")
send_json(title)
}
I want to send a HTTP error and a text if something go wrong, on the other side it will be converted to something meaninful to the user.
So the method becames:
get("/") {
try {
val title = db.get_collection("main", "api", "title")
send_json(title)
} catch {
case e:java.util.NoSuchElementException => send_error("DB malformed", InternalError)
case e:com.mongodb.MongoException => send_error("Can not connect to MongoDB", InternalError)
case e => send_error("Internal Error", InternalError)
}
}
The try catch is bigger that the actual method and I need to do this for every method, the class become at first sight an ugly collection of try catch.
There is any way to avoid or minimize the bad looking and distracting try catch all over the code? I am new to Scala (and Java BTW) so I guess I am missing something.
I dont want the DB object to send JSON, so having the try catch on the db.get_collection method is not an option.
There's a special route handler for this:
error {
case e: Throwable => {
redirect("/")
}
}
By changing the case statement you can switch on the error type.
Well, I don't know Scalatra enough, but the catch block is a partial function, so you could do something like this:
val errorHandling: PartialFunction[Throwable, Unit] = {
case e:java.util.NoSuchElementException => send_error("DB malformed", InternalError)
case e:com.mongodb.MongoException => send_error("Can not connect to MongoDB", InternalError)
case e => send_error("Internal Error", InternalError)
}
get("/") {
try {
val title = db.get_collection("main", "api", "title")
send_json(title)
} catch errorHandling
}