Entre Scala Option
e lift’s Box
(eu uso lift-mongorecord com Scalatra), raramente uso try {...} catch {...}
em Scala. Mas, em uma ocasião, acabei usando-o para lidar com qualquer problema que pudesse surgir ao falar com um serviço externo.
try {
// call external service
} catch {
case e => halt(500, e.getMessage)
}
As coisas funcionaram bem no inÃcio. Posteriormente, precisei adicionar uma verificação de autorização no try {...}
bloco, o que causava uma halt()
falha na verificação.
try {
// call external service
if (!authorized) {
halt(401, "Authorization required")
}
} catch {
case e => halt(500, e.getMessage)
}
Para minha surpresa, meu aplicativo retornou 500 em vez do 401 esperado se o serviço externo retornou algo que falhou na verificação de autorização. Depois de me intrigar um pouco, me lembrei de ter lido as obras de Scalatra lançando uma exceção sob o capô. (Na verdade, ele lança uma subclasse de , mais sobre isso em breve.) Quando o interno é chamado, o 401 é capturado pelo bloco e convertido em 500.halt()
Throwable
halt()
catch {...}
Para fazer isso funcionar, eu teria que alterar meu cobertor catch
para procurar o que quer que fosse halt()
e deixar que borbulhasse. Mas o que halt()
joga? Acontece que halt()
lança a Throwable
, que é a superclasse de Exception
. Como observado no este post , apenas a subclasses de Exception
deve ser tratado no catch {...}
bloco, que permite que o interior halt()
é Throwable
a borbulhar.
try {
// call external service
if (!authorized) {
halt(401, "Authorization required")
}
} catch {
// only handle subclasses of Exception
case e:Exception => halt(500, e.getMessage)
}
Para aqueles de vocês que estão curiosos, halt()
realmente lança um HaltException
que se estende ControlThrowable
.
Esta dica foi republicada do meu blog, jontai.me