How to handle exceptions in a playframework 2 Async block (scala) -
my controller action code looks this:
def addingredient() = action { implicit request => val boundform = ingredientform.bindfromrequest boundform.fold( formwitherrors => badrequest(views.html.admin.index(formwitherrors)), value => { async { val created = service.addingredient(value.name, value.description) created map { ingredient => redirect(routes.admin.index()).flashing("success" -> "ingredient '%s' added".format(ingredient.name)) } // todo on exception following // badrequest(views.html.admin.index(boundform.copy(errors = seq(formerror("", ex.getmessage()))))) } }) } my service.addingredient(...) returns promise[ingredient] can throw custom validationexception. when exception thrown return commented code.
currently page renders 500 , in logs have:
play - waiting promise, got error: ingredient name 'test' exists. services.validationexception: ingredient name 'test' exists.
two questions:
- is bad idea return exception service, there better/more scala way handle case?
- how catch exception?
i'd pure functional way have been use type can hold valid , error states.
for that, can use validation form scalaz
but if don't need more scalaz (you ^^), use simple stuff using promise[either[string, ingredient]] result , fold method in async block. is, map convert value when promise redeemed , fold on redeemed.
the point => no exception => every thing typed check :-)
edit
it might need bit of information more, here 2 options: try catch, @kheraud) , either. didn't put validation, ask me if needed. object application extends controller {
def index = action { ok(views.html.index("your new application ready.")) } //using try catch // missing wrapping of badrequest promise since async // requiring such result. that's done using promise.pure def test1 = async { try { val created = promise.pure(new {val name:string = "myname"}) created map { stuff => redirect(routes.application.index()).flashing("success" -> "stuff '%s' show".format(stuff.name)) } } catch { case _ => { promise.pure(redirect(routes.application.index()).flashing("error" -> "an error occurred man")) } } } //using either (kind of validation) // on left side => success value name val success = left(new {val name:string = "myname"}) // on right side exception message (could exception instance => keep stack) val fail = right("bang bang!") // how use // simulate service using promise.pure wraps either result // return type of service should promise[either[{val name:string}, string]] in exemple // while mapping (that create promise around convert content), folds create right result (redirect in case). // point => compiled time checked ! , no wrapping pure error case. def test2(trysuccess:boolean) = async { val created = promise.pure(if (trysuccess) success else fail) created map { stuff /* either */ => stuff.fold( /*success case*/s => redirect(routes.application.index()).flashing("success" -> "stuff '%s' show".format(s.name)), /*the error case*/f => redirect(routes.application.index()).flashing("error" -> f) ) } } }
Comments
Post a Comment