Alan, thanks.

This looks excessively complex, given how the existing exception handling
should ( in my opinion ) take care of this.
I've written a test around it, and found that the exception handler is
never called for an exception bubbling up from the json format via
entity(as[Object]). It is called for an exception occurring in the route
itself.

the test is at
https://gist.github.com/andlaz/ca423b6b0d79060a006293b2599e908a
it's output is

[info] A route decoding an entity with an in-scope Format that throws a
DeserializationException
[info] - should invoke it's top-level exception handler *** FAILED ***
[info]   Request was rejected with rejection
MalformedRequestContentRejection(Didn't even
try,spray.json.DeserializationException: Didn't even try)
(RouteTest.scala:57)
[info] A route throwing an exception
[info] - should invoke it's top-level exception handler

in conclusion, I can not prevent the DeserializationException to become a
Rejection, maybe this happens as early as in entity() ? I can certainly
handle the Rejection..

is this expected behavior?

thanks,
Andras

On Tue, 25 Apr 2017 at 05:42 Alan Burlison <alan.burli...@gmail.com> wrote:

> On 25/04/2017 00:13, Andras Szerdahelyi wrote:
>
> > I have a need to encode exception messages in to a specific JSON format
> in
> > my http responses. I was wondering how I could catch a
> > DeserializationException in my route or outside of it or encode the
> > DeserializationException.
>
> Here's how I did it so that it integrasted into my existing REST service
> error handling:
>
> Wrapped the deserialization operation in a try block:
>
>    def getParam[T: JsonReader](params: MMap[String, JsValue], key:
> String, delete: Boolean = true): T = {
>      val value = params.get(key) match {
>        case Some(v) => try {
>            v.convertTo[T]
>          } catch {
>            case de: DeserializationException => throw
> deserializationToRESTException(de, key)
>          }
>        case None => throw RESTException(ERR_MISSING_ARG(key))
>      }
>      if (delete) params -= key
>      value
>    }
>
>    val restErrorRE: Regex = """^Expected (\w+) as \w+, but got (.+)$""".r
>
>    def deserializationToRESTException(de: DeserializationException, key:
> String) = {
>      val msg = de.msg match {
>        case restErrorRE(t, v) => s"expected $key to be $t but got $v"
>        case _ => s"invalid value for $key"
>      }
>      RESTException(ERR_INVALID_ARG(msg), de)
>    }
>
> Then I wrapped all the individual deserialization calls in a try block:
>
>     try {
>     :
>       val name = getParam[String](fields, "name")
>       val uid = getParam[Int](fields, "uid")
>     :
>     } catch {
>        case re: RESTException => complete(re.toResponse)
>
>    final case class RESTException(error: RESTError, cause: Throwable =
> null) extends Exception(error.toString, cause) {
>      def toResponse: HttpResponse = error.toResponse
>    }
>
>    final case class ERR_INVALID_ARG(det: String = null)
>      extends RESTErrorWithDetail(400, "invalid input argument", det)
>
> RESTErrorWithDetail just maps the error code and message onto a normal
> HttpResponse containing the HTTP status code and a JSON formatted error
> message:
>
>    override def toResponse: HttpResponse = {
>      if (detail != null) {
>        HttpResponse(status = code, entity =
> HttpEntity(MediaTypes.`application/json`,
>          """{ "fault": { "code": %d, "name": %s, "message": %s }
> }""".format(
>            code, name.toJson, s"$msg ($detail)".toJson)))
>      } else {
>        super.toResponse
>      }
>    }
>
> That way the JSON deserialization errors are handled as normal
> completions rather than using a specific Akka-HTTP exception handler.
>
> --
> Alan Burlison
> --
>
> --
> >>>>>>>>>>      Read the docs: http://akka.io/docs/
> >>>>>>>>>>      Check the FAQ:
> http://doc.akka.io/docs/akka/current/additional/faq.html
> >>>>>>>>>>      Search the archives:
> https://groups.google.com/group/akka-user
> ---
> You received this message because you are subscribed to the Google Groups
> "Akka User List" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to akka-user+unsubscr...@googlegroups.com.
> To post to this group, send email to akka-user@googlegroups.com.
> Visit this group at https://groups.google.com/group/akka-user.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
>>>>>>>>>>      Read the docs: http://akka.io/docs/
>>>>>>>>>>      Check the FAQ: 
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>>      Search the archives: https://groups.google.com/group/akka-user
--- 
You received this message because you are subscribed to the Google Groups "Akka 
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to akka-user+unsubscr...@googlegroups.com.
To post to this group, send email to akka-user@googlegroups.com.
Visit this group at https://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to