2017-04-20 4 views
1

J'ai besoin d'encoder des messages d'exception dans un format JSON spécifique dans mes réponses http. Je me demandais comment je pouvais attraper une exception DeserializationException sur ma route ou en dehors de celle-ci ou encoder l'exception DeserializationException.Gestion (sérialisation, en fait ..) DeserializationException dans akka-http

J'ai essayé les éléments suivants:

1) gestionnaire d'exception autour de mon itinéraire:

val exceptionHandler = ExceptionHandler { 
    case e: DeserializationException => complete(StatusCodes.BadRequest, ServiceBrokerError(e.getMessage)) 
} 

2) format JSON portée implicite DeserializationException

implicit object DeserializationExceptionFormat extends DefaultJsonProtocol with RootJsonFormat[DeserializationException] { 

    def write(e: DeserializationException) = JsObject("message" -> JsString(e.getMessage)) 
    def read(v: JsValue) = throw new NotImplementedError() 

} 

Aucune de ces faire une différence et DeserializationException s sont toujours codés dans le corps de réponse http ci-dessous:

HTTP/1.1 400 Bad Request 
Content-Length: 74 
Content-Type: text/plain; charset=UTF-8 
Date: Thu, 20 Apr 2017 21:23:11 GMT 
Server: akka-http/10.0.1 

The request content was malformed: 
Node count may not be a floating number 

Toutes les suggestions sont grandement appréciées.

Certains context- supplémentaires mes itinéraires reposent sur l'intégration par pulvérisation JSON pour cartographier les entités demande à des objets, tels que:

// service instance management related routes 
put { 
    entity(as[CreateInstance]) { createInstance => handleCreateInstance(s"cluster-$clusterId", createInstance) } 
} 

Répondre

0

Je devrais avoir simplement regardé MarshallingDirectives.entity car il avale les exceptions liées à la sérialisation et les passe à Rejections:

/** 
    * Unmarshalls the requests entity to the given type passes it to its inner Route. 
    * If there is a problem with unmarshalling the request is rejected with the [[Rejection]] 
    * produced by the unmarshaller. 
    * 
    * @group marshalling 
    */ 
    def entity[T](um: FromRequestUnmarshaller[T]): Directive1[T] = 
    extractRequestContext.flatMap[Tuple1[T]] { ctx ⇒ 
     import ctx.executionContext 
     import ctx.materializer 
     onComplete(um(ctx.request)) flatMap { 
     case Success(value) ⇒ provide(value) 
     case Failure(RejectionError(r)) ⇒ reject(r) 
     case Failure(Unmarshaller.NoContentException) ⇒ reject(RequestEntityExpectedRejection) 
     case Failure(Unmarshaller.UnsupportedContentTypeException(x)) ⇒ reject(UnsupportedRequestContentTypeRejection(x)) 
     case Failure(x: IllegalArgumentException) ⇒ reject(ValidationRejection(x.getMessage.nullAsEmpty, Some(x))) 
     case Failure(x) ⇒ reject(MalformedRequestContentRejection(x.getMessage.nullAsEmpty, x)) 
     } 
    } & cancelRejections(RequestEntityExpectedRejection.getClass, classOf[UnsupportedRequestContentTypeRejection]) 

Par conséquent, il s'agit d'une Rejection que je dois gérer, et non l'exception DeserializationException.

1

si vous changez votre gestionnaire d'exception à

val exceptionHandler = ExceptionHandler { case e: DeserializationException => complete(StatusCodes.BadRequest, e) }

+0

Merci pour la réponse. C'est la même sortie. Je ne pense pas que le problème soit l'encodage de l'objet ServiceBrokerError, ou du moins j'espérais qu'il y aurait quelque chose de connecté. – pgn