how to catch all the errors in any scalatra action?
Asked Answered
D

2

12

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.

Discretionary answered 28/2, 2012 at 11:35 Comment(0)
V
6

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
}
Vendue answered 28/2, 2012 at 14:56 Comment(2)
my final solution was: val errorHandling: PartialFunction[Throwable, Unit] = { If I use errorHandler, I got an error about that name to need to be override. It also seemed to need java.lang.Throwable instead of ExceptionDiscretionary
@Discretionary Ok, I fixed the code accordingly, so others won't have to figure it out (if they happen to miss your comment).Vendue
T
46

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.

Tude answered 6/2, 2013 at 15:13 Comment(1)
This is the idiomatic method for handling errors in Scalatra, though it's missing from the documentation.Goggin
V
6

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
}
Vendue answered 28/2, 2012 at 14:56 Comment(2)
my final solution was: val errorHandling: PartialFunction[Throwable, Unit] = { If I use errorHandler, I got an error about that name to need to be override. It also seemed to need java.lang.Throwable instead of ExceptionDiscretionary
@Discretionary Ok, I fixed the code accordingly, so others won't have to figure it out (if they happen to miss your comment).Vendue

© 2022 - 2024 — McMap. All rights reserved.