aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorzachdriver <zach@driver.xyz>2018-05-25 12:44:15 -0700
committerGitHub <noreply@github.com>2018-05-25 12:44:15 -0700
commitd61ed25db4d71ac182f09ce7bc02439470f3a998 (patch)
treebdc0089e60ac7cf84e850e2024acd5ddbcdbaaa0 /src/main
parent57cd7aaf5a2154af698fddc39f4bff8fd3e4f6e7 (diff)
downloaddriver-core-d61ed25db4d71ac182f09ce7bc02439470f3a998.tar.gz
driver-core-d61ed25db4d71ac182f09ce7bc02439470f3a998.tar.bz2
driver-core-d61ed25db4d71ac182f09ce7bc02439470f3a998.zip
Add service exception json formatters and pass through exceptions in HttpRestServiceTransport (#168)v1.9.4
Diffstat (limited to 'src/main')
-rw-r--r--src/main/scala/xyz/driver/core/core.scala11
-rw-r--r--src/main/scala/xyz/driver/core/json.scala19
-rw-r--r--src/main/scala/xyz/driver/core/rest/DriverRoute.scala12
-rw-r--r--src/main/scala/xyz/driver/core/rest/HttpRestServiceTransport.scala7
-rw-r--r--src/main/scala/xyz/driver/core/rest/errors/serviceException.scala5
5 files changed, 48 insertions, 6 deletions
diff --git a/src/main/scala/xyz/driver/core/core.scala b/src/main/scala/xyz/driver/core/core.scala
index 14e1b10..72237b9 100644
--- a/src/main/scala/xyz/driver/core/core.scala
+++ b/src/main/scala/xyz/driver/core/core.scala
@@ -3,6 +3,9 @@ package xyz.driver
import scalaz.{Equal, Monad, OptionT}
import eu.timepit.refined.api.{Refined, Validate}
import eu.timepit.refined.collection.NonEmpty
+import xyz.driver.core.rest.errors.ExternalServiceException
+
+import scala.concurrent.{ExecutionContext, Future}
package object core {
@@ -54,6 +57,14 @@ package object core {
def toUnitOptionT: OptionT[H, Unit] =
OptionT.optionT[H](monadT(monadicValue)(_ => Option(())))
}
+
+ implicit class FutureExtensions[T](future: Future[T]) {
+ def passThroughExternalServiceException(implicit executionContext: ExecutionContext): Future[T] =
+ future.transform(identity, {
+ case ExternalServiceException(_, _, Some(e)) => e
+ case t: Throwable => t
+ })
+ }
}
package core {
diff --git a/src/main/scala/xyz/driver/core/json.scala b/src/main/scala/xyz/driver/core/json.scala
index c1c5862..de1df31 100644
--- a/src/main/scala/xyz/driver/core/json.scala
+++ b/src/main/scala/xyz/driver/core/json.scala
@@ -16,6 +16,7 @@ import spray.json._
import xyz.driver.core.auth.AuthCredentials
import xyz.driver.core.date.{Date, DayOfWeek, Month}
import xyz.driver.core.domain.{Email, PhoneNumber}
+import xyz.driver.core.rest.errors._
import xyz.driver.core.time.{Time, TimeOfDay}
import scala.reflect.runtime.universe._
@@ -368,6 +369,24 @@ object json {
NonEmptyName[T](nonEmptyStringFormat.read(value))
}
+ implicit val serviceExceptionFormat: RootJsonFormat[ServiceException] =
+ GadtJsonFormat.create[ServiceException]("type") {
+ case _: InvalidInputException => "InvalidInputException"
+ case _: InvalidActionException => "InvalidActionException"
+ case _: ResourceNotFoundException => "ResourceNotFoundException"
+ case _: ExternalServiceException => "ExternalServiceException"
+ case _: ExternalServiceTimeoutException => "ExternalServiceTimeoutException"
+ case _: DatabaseException => "DatabaseException"
+ } {
+ case "InvalidInputException" => jsonFormat(InvalidInputException, "message")
+ case "InvalidActionException" => jsonFormat(InvalidActionException, "message")
+ case "ResourceNotFoundException" => jsonFormat(ResourceNotFoundException, "message")
+ case "ExternalServiceException" =>
+ jsonFormat(ExternalServiceException, "serviceName", "serviceMessage", "serviceException")
+ case "ExternalServiceTimeoutException" => jsonFormat(ExternalServiceTimeoutException, "message")
+ case "DatabaseException" => jsonFormat(DatabaseException, "message")
+ }
+
val jsValueToStringMarshaller: Marshaller[JsValue, String] =
Marshaller.strict[JsValue, String](value => Marshalling.Opaque[String](() => value.compactPrint))
diff --git a/src/main/scala/xyz/driver/core/rest/DriverRoute.scala b/src/main/scala/xyz/driver/core/rest/DriverRoute.scala
index c23c44d..fe3790f 100644
--- a/src/main/scala/xyz/driver/core/rest/DriverRoute.scala
+++ b/src/main/scala/xyz/driver/core/rest/DriverRoute.scala
@@ -90,11 +90,17 @@ trait DriverRoute {
}
{ (ctx: RequestContext) =>
- errorResponse(statusCode, serviceException.message, serviceException)(ctx)
+ import xyz.driver.core.json.serviceExceptionFormat
+ val entity =
+ HttpEntity(ContentTypes.`application/json`, serviceExceptionFormat.write(serviceException).toString())
+ errorResponse(statusCode, entity, serviceException)(ctx)
}
}
- protected def errorResponse[T <: Exception](statusCode: StatusCode, message: String, exception: T): Route = {
- complete(HttpResponse(statusCode, entity = message))
+ protected def errorResponse[T <: Exception](statusCode: StatusCode, message: String, exception: T): Route =
+ errorResponse(statusCode, HttpEntity(message), exception)
+
+ protected def errorResponse[T <: Exception](statusCode: StatusCode, entity: ResponseEntity, exception: T): Route = {
+ complete(HttpResponse(statusCode, entity = entity))
}
}
diff --git a/src/main/scala/xyz/driver/core/rest/HttpRestServiceTransport.scala b/src/main/scala/xyz/driver/core/rest/HttpRestServiceTransport.scala
index e54f722..788729a 100644
--- a/src/main/scala/xyz/driver/core/rest/HttpRestServiceTransport.scala
+++ b/src/main/scala/xyz/driver/core/rest/HttpRestServiceTransport.scala
@@ -75,8 +75,11 @@ class HttpRestServiceTransport(
Future.successful(Unmarshal(HttpEntity.Empty: ResponseEntity))
} else if (response.status.isFailure()) {
val serviceCalled = s"${requestStub.method} ${requestStub.uri}"
- Unmarshal(response.entity).to[String] flatMap { error =>
- Future.failed(ExternalServiceException(serviceCalled, error))
+ Unmarshal(response.entity).to[String] flatMap { errorString =>
+ import spray.json._
+ import xyz.driver.core.json._
+ val serviceException = util.Try(serviceExceptionFormat.read(errorString.parseJson)).toOption
+ Future.failed(ExternalServiceException(serviceCalled, errorString, serviceException))
}
} else {
Future.successful(Unmarshal(response.entity))
diff --git a/src/main/scala/xyz/driver/core/rest/errors/serviceException.scala b/src/main/scala/xyz/driver/core/rest/errors/serviceException.scala
index 095936e..db289de 100644
--- a/src/main/scala/xyz/driver/core/rest/errors/serviceException.scala
+++ b/src/main/scala/xyz/driver/core/rest/errors/serviceException.scala
@@ -10,7 +10,10 @@ final case class InvalidActionException(override val message: String = "This act
final case class ResourceNotFoundException(override val message: String = "Resource not found")
extends ServiceException(message)
-final case class ExternalServiceException(serviceName: String, serviceMessage: String)
+final case class ExternalServiceException(
+ serviceName: String,
+ serviceMessage: String,
+ serviceException: Option[ServiceException])
extends ServiceException(s"Error while calling '$serviceName': $serviceMessage")
final case class ExternalServiceTimeoutException(serviceName: String)