Search code examples
scalaexceptionplayframework

Catching Exception in Controller NonFatal


Assume I have the following controller method:

def getAllRules() = AuthAction("View" on "Rules").async {
   Metrics.measureTime("getAllRules", category = Category) {
     ruleService.getAllRules.map({
       case Nil => NoContent
       case rules => Ok(Json.toJson(rules.toViewRules))
     }).recover {
       case e: Exception => handlerError(s"Failure occurred on getAllRules, ex: ${e.getMessage}", "getAllRules")
     }
   }
}

when handleError is:

def handlerError(err: String, occurredOn: String): Result = {
    Metrics.errorsCounter(occurredOn).increment()
    logger.error(err)
    InternalServerError(Json.toJson(Json.obj("error" -> err)))
}

I understood that catching all exceptions is a mistake, and I should catch only NonFatal Exceptions.

I wanted to ask:

  1. What is a Fatal Exception? How can occur? VirtualMachineError, InterruptedException, LinkageError, ControlThrowable
  2. Why it's not good to catch all exceptions, but only NonFatal?
  3. In the case of Fatal Exception - how its need to be handled?, code-example would be great with an explanation
  4. Just to make sure - If the controller will not catch any Exception, in k8s & docker env, the Pod will be failed with status Error and make a Restart - Right?

Solution

  • What is a Fatal Exception? How can occur? VirtualMachineError, InterruptedException, LinkageError, ControlThrowable

    Basically, you can conisider fatal errors - those which you can not handle properly. E.g. VirtualMachineError or any another java.lang.Error identifies problems occured in JVM internals, which you can't do much with: like AbstractMethodError - identifies that somehow was invoked method without implementation, which means that the issue in bytecode. Or famous OutOfMemmoryError - usually recommended to not handle, because it might lead to heap corrution or another problems. Let them just crash an app.

    Why it's not good to catch all exceptions, but only NonFatal? Because, suing case NonFatal(e) => you avoiding possible problems describe before.

    In the case of Fatal Exception - how its need to be handled?, code-example would be great with an explanation

    You should not catch them - fatal errors your friends and will make troubleshooting easier. Let them crash the app. It is correct approach.

    Just to make sure - If the controller will not catch any Exception, in k8s & docker env, the Pod will be failed with status Error and make a Restart - Right?

    Yes, but make sure you have some circuit breaker logic - don't re-start app endless time, if it is does not help. E.g. in case with AbstractMethodError - problems with binaries and only way to fix it - re-build or fix dependencies, but restating will only consume resources, without result.