score:0
I've written some Scala Apis before for things like this and I tend to use the type Either to differentiate between errors and success like this, rather than do the Java-esc thing of throwing exceptions.
case class MyClientError(errorMessage :String)
class MyClient(baseUrl: String) {
def getDataSet(dataSetId: String) : Either[MyClientError,DataSet] = {
call(dataSetId) match {
case dataset if result.status == HTTP_OK => Right(dataset)
case _ if result.status == HTTP_404 => Left(MyClientException("Not found"))
case result => Left(MyClientException(s"Got non 200 response: ${result.status}")
}
}
}
This way the caller can do this:
getDataSet(54) match {
case Left(err) => println(s"got an error ${err.errorMessage}")
case Right(dataset) => println("got a good answer!")
}
Either tends to compose quite well, can be used in for-yield blocks, is rich in terms of returning a reason for a failure etc. It's easy to turn List(ids) -> Either[List[errors], List[datasets]] etc.
--
How you handle exceptions on failures is a slightly wider question. Ultimately up to the system designer. You could return the error, put it aside and move on or implement retry logic. Of course, it depends what call() returns when an error occurs. This example demonstrates how you could retry if call() returns a Future that fails with a throwable:
def getDataSet(dataSetId: String, retries :Int = 3) : Future[Either[MyClientError,DataSet]] = {
call(dataSetId).flatMap {
case Success(dataset) if result.status == HTTP_OK => Future.successful(Right(dataset))
case Success(_) if result.status == HTTP_404 => Future.successful(Left(MyClientException("Not found")))
case Failure(exc) if thr.isTransientError && retries > 0 => getDataSet(dataSetId, retries - 1)
case Failure(exc) if thr.isTransientError && retries == 0 => Future.successful(Left(MyClientException(s"Tried 3 times but failed: ${exc.getMessage}")))
case Failure(exc) => Future.successful(Left(MyClientException(s"Unrecoverable: ${exc.getMessage}")))
case Success(result) => Future.successful(Left(MyClientException(s"Got non 200 response: ${result.status}")))
}
}
}
score:4
This is very much a matter of opinion, but I would use exceptions for all error cases. You can define your own HTTP exceptions:
case class MyHttpException(code: StatusCode) extends Throwable
If your client is synchronous then return Try
but typically a REST client is asynchronous, in which case you return Future
. Both of these object track exceptions and make the Throwable
available in the case of error.
Source: stackoverflow.com
Related Query
- Scala RestAPI Client design : handling exceptions
- Handling and throwing Exceptions in Scala
- handling swing exceptions in scala application
- Handling exceptions in Scala collections
- Handling exceptions in Scala object constructors
- Handling unexpected exceptions on scala Futures
- Catching multiple exceptions at once in Scala
- Simple and concise HTTP client library for Scala
- Scala 2.8 collections design tutorial
- define your own exceptions with overloaded constructors in scala
- Scala client composition with Traits vs implementing an abstract class
- Error handling Scala : Future For Comprehension
- Read CSV in Scala into case class instances with error handling
- How do I get hold of exceptions thrown in a Scala Future?
- Redis client library recommendations for use from Scala
- Design Patterns and Scala
- how to get started with Elastic Search using scala client
- Why should one prefer Option for error handling over exceptions in Scala?
- Using Finagle for simple Scala SOAP client
- Scala Catalog of functional Design Patterns
- Improving Scala script startup time -- client mode?
- Scala continuation and exception handling
- Handling properties in Scala
- Handling Postgres json datatype in slick, scala
- Catch all exceptions in Scala 2.8 RC1
- scala try/catch not catching some exceptions
- Scala future sequence and timeout handling
- Handling microseconds in Spark Scala
- Handling exceptions in an iteratee library without an error state
- Scala @throws multiple exceptions
More Query from same tag
- Scala and implicit imports?
- Raw string to list of tuples
- Serialization issue while renaming HDFS File using scala Spark in parallel
- How to repeat Await multiple times?
- sublime-ensime for scala not finding android packages
- Akka Streams - How to check if a stream ran successfully?
- Type for parallel or sequential collection in scala
- Scala: List of class objects printing the class variable/attributes
- sbt subproject source folders not created automatically?
- Autocasting types using 'value: Type' syntax
- What is the procedure to Import word2vec model written in C++ using H2O framework?
- Is this really the way to pass void functions to Scala methods from Java?
- methode map in class cats.data.Nested not recognized
- How to setup build.sbt with sbt-assembly plugin?
- Type Parameters and Algebraic Data Type?
- Folding on Type without Monoid Instance
- Unexpected behaviour with long keys using bcrypt
- Unit testing Scala package object
- ScalaJs + ZIO: Program works with sbt 1.2.8 but not >= 1.3
- Spark running time in local changes a lot with "println"
- How to compare types of different, generic HLists?
- org.hibernate.MappingException - Scala Many-to-many
- How to use reduceByKey to select records on particular columns?
- Fault tolerance in Spark streaming
- Scalaz, the purpose of *syntax classes
- Spark Hbase inserts too many connections open
- Play framework form parameter
- Spark join 2 dataframe based on multiple columns
- Server side pagination in Graphql Scala
- Scala Slick Database Views