3
votes

The code below uses Slick 3.1.x to read a row from a table, attempting to catch any SQL errors. UserDB is the Slick representation of the table, and User is the related object.

This code does not compile in the failure statement with the following error:

type mismatch; found : Unit required: scala.concurrent.Future[Option[user.manage.User]]

How to fix this to catch the SQL error?

   def read (sk: Int): Future[Option[User]] = {
      val users = TableQuery[UserDB]
      val action = users.filter(_.sk === sk).result
      val future = db.run(action)
      future.onSuccess {
        case result =>
              if (!result.isEmpty)
                  Some(result(0))
              else
                  None
      }
      future.onFailure {   // <-- compilation error
          case e => println (e.getMessage)
          None
      }
   }
2
onFailure reigsters a callback and returns Unit. Therefore your entire method returns Unit.rethab
Thanks. Assume that on failure I need to write an entry in a log and return None (as opposed to return Some if the record is read correctly), what should be the approach?ps0604
Don't use onFailure but on of the methods on Future that can handle an Exception and still return something.rethab
My objective is to catch (somehow) the SQL exception, taking into consideration that the function returns a Future with an option. Any ideas?ps0604

2 Answers

9
votes

You can use asTry method to catch exception ex into a successful result Failure(ex) and the successful value in Success(v). In your case the following should work.

db.run(action.asTry).map{
  case Failure(ex) => { 
         Log.error(s"error : ${ex.getMessage}") 
         None
        }
  case Success(x) => x
}

As mentioned in the slick documentation, asTry is used to pipeline the exceptions for recovery handling logic.

4
votes

You can use the onComplete method of the future.

        future.onComplete{
            case Success(r) ⇒ ...
            case Failure(t) ⇒ log.error("failure in db query " + t.getMessage)
        }