Scala: failing a Future based on a Future#collect - scala

WS.post returns a Future[Response], but I want a Future[Data] so I'm using Future.collect for that purpose.
private def getDataFuture(data: String): Future[JsValue] =
initAuthenticatedRequest().post(body).collect {
case response => response.json(0)
}.recoverWith {
case NonFatal(_) => getDataFuture(data)
}
However, sometimes response.json(0) returns a bad value because I receive an empty json. I expected this to cause the Future to fail and do the recoverWith, but that didn't happen.
Do I need to do branching within the collect case?
How can I handle this more elegantly? I imagined that Future would have provisions for this.

You must use
initAuthenticatedRequest().post(body).map(_.json.as[JsArray])
json.as[JsArray] casts json to JsArray or throws exception, which can be handled with recoverWith

Related

Scala, how to not use None

I have a bit of code that I am checking with Scala Scapegoat. I am not sure how to refactor this code the way it wants.
def strToDouble(valueParam: Option[String]): Option[java.lang.Double] = {
valueParam.map(value => {
Try {
Double.box(value.toDouble)
}.recoverWith({
case e: NumberFormatException => {
val logger = LoggerFactory.getLogger(getClass.getName)
logger.warn("error parsing string to double", e)
return None
}
}).getOrElse(null)
})
}
Scapegoat is complaining about my use of return and the getOrElse(null). Unfortunately in this situation I can't figure out how to do what I want:
convert the string to double, returning Option[Double]
log an error if there is a parsing error
return None in the case of parsing error
any ideas?
In general in Scala, you never need to use return, and it has some surprising semantics so it's generally advised to never use return.
Instead of return, the result of a block expression (such as the body of a function) is the result of the last expression evaluated in the block.
I would write your code along these lines
valueParam.flatMap { value =>
val attempt =
Try {
Double.box(value.toDouble)
}
attempt.recoverWith {
case e: NumberFormatException =>
val logger = LoggerFactory.getLogger(getClass.getName)
logger.warn("error parsing string to double", e)
attempt
}.toOption
}
The first key difference is that since we're transforming an Option into another Option, and might sometimes turn a Some into a None (e.g. Some("hello")), flatMap is called for.
Saving the Try[Double] in a local val enables us to get around there not being a foreach equivalent on a failed Try, thus the recoverWith which results in the same Try after side-effecting.
At the end, we convert the Try into an Option with toOption.
null is generally never used in Scala, with Option preferred (and an Option which could be null is especially verboten, as it's virtually guaranteed to blow up). If you have an Option[java.lang.Double] and need a possibly null java.lang.Double in order to work with a Java API, the orNull method on an Option is probably the most idiomatic thing to use.
I'm fairly sure that scala.Double is, on the JVM, a compiler-synthesized alias for java.lang.Double, so Double.box might not be needed.
Everything that #Levi said. I just have a preference for fold() in place of recooverWith().
import scala.util.Try
def strToDouble(valueParam: Option[String]): Option[Double] =
valueParam.flatMap { value =>
Try(value.toDouble).fold({
case e:NumberFormatException =>
LoggerFactory.getLogger(getClass.getName)
.warn("error parsing string to double", e)
None
}, Some(_))
}

Use Future.successful(None) vs Future.failed(new Exception()) for an API that may return no results?

What is the idiomatic way in Scala to type an API that may or may not return results?
I can simply type to Future[Option[A]] and return a None if there is no results, but this will make things a little more verbose for API clients I think because it has to do some pattern matching (or other techniques like folding) over the Option returned.
trait SomeAPI {
def fetch(): Future[Option[String]]
}
object APIImpl {
def asyncDBCall(): Future[List[String]] = ???
override def fetch(): Future[Option[String]] = asyncDBCall().map(r => if (r.isEmpty) None else Some(r.head)
}
However, Futures already give us a way to say that there are no results making it fail. But I don't know if this is a proper or expressive way of say that the call doesn't return results.
trait SomeAPI {
def fetch(): Future[String]
}
class NoResultsException extends Exception
object APIImpl extends SomeAPI {
def asyncDBCall(): Future[List[String]] = ???
override def fetch(): Future[String] = asyncDBCall().map(r => if (r.isEmpty) throw new NoResultsException() else r.head)
}
At first it seems that both options are acceptable and the final decision may be just about personal preference, but maybe I'm missing something and make a Future fail is not a good option.
Exceptions should be reserved for errors. If the API may or may not returns results, and both cases are considered normal, then the API should use Option.
If that makes it more verbose by forcing the client to handle both situations, that's good, because the client should handle both situations. Exceptions are good when you don't want to force the client code to handle an exceptional case (unexpected error) which should probably cascade and be handled by an error handler.
Now, if lack of results truly indicates that something went wrong, then an exception would be appropriate.
I'd expect clients want to treat "success, no results" and failure differently, generally speaking (e.g. retry in the second case, but not the first). If you denote the first with a failed future, you make verbosity for the clients worse, not better: they just need to check the exception instead of the success, and the API isn't helping them to be aware of that like Future[Option[A]] would.
If you really worry about verbosity, you could add custom extractors or methods for the clients to use if they want, e.g.
implicit class FutureOption[A](future: Future[Option[A]]) {
def mapOpt[B](handleSuccessWithResult: A => B, handleSuccessWithNoResult: () => B) = Future.map {
case Some(x) => onSuccessWithResult(x)
case None => onSuccessWithNoResult()
}
}
The others are right. Failures are not a good way to describe the lack of a concrete result, if this is part of regular operation.
Scala gives you another possibility to explicitly note, that there may be no results, sealed traits.
sealed trait MyOperationReturn
case object OkNoResult
case class OkWithStringResponse(data: String) extends MyOperationReturn
case class OkWithIntResponse(data: Int) extends MyOperationReturn
The user can then just pattern match. This option is especially handy, if you have either multiple return types (not only two) and no natural empty return type (like Seq.empty)

Returning Future[Int] from Future[Option[Int]] with support of Failing the future

I have the below block of code. My intent is to do some processing with the method params and return Future[Int] or fail the Future. I want to fail the Future if my argument to method inside the Future is of type None. I have the below code. I wonder if there is a much more concise and functional way to achieve the same.
def testoption(myFutOptInt: Future[Option[Int]]) = {
myFutOptInt.map { myOptInt =>
myOptInt match {
case None => throw new BadRequestException("Oh no.....") //Future.failed(BadRequestException(""))
case Some(myInt) => myInt + 45
}
} recoverWith {
case e:Exception => Future.failed(e)
}
}
I am not liking the part that I have to do a match, wondering if there is a way to do a map or something better and still achieve it. If I do getOrElse I guess I won't be able to write the business logic if the value is not None? So getOrElse is not possible either I think?
The other thing I do not like about this code is that I am throwing an exception and then I have to do recoverWith to fail the Future.
I can enhance the above code how?
If you need specifically BadRequestException, this is enough:
def testoption(myFutOptInt: Future[Option[Int]]) =
myFutOptInt.map {
case None => throw new BadRequestException("Oh no.....")
case Some(myInt) => myInt + 45
}
And if you don't care about particular error type, you can cut it even more:
def testoption(myFutOptInt: Future[Option[Int]]) = myFutOptInt.map(_.get + 45)
This will give you java.util.NoSuchElementException: None.get if there's no value
recoverWith is absolutely redundant b/c if an exception is thrown inside a map, whole operation results in a failed Future. This is true for most, if not all, Future methods.
For match, you can avoid it using opt.fold(throw ...)(...) or .map(...).getOrElse(throw ...), but I'd argue those options are less readable. I suggest just using pattern-matching function definition to reduce extra code

Picking the right exception handling in scala

I'm new to Scala, being slightly confused at the various ways to handle exceptions and looking for best-practice advice on the topic. I'm writing a simple method to retrieve a Customer using an existing blocking SDK. The possible outcomes are:
Customer is found
Customer is not found (comes back as a NotFoundException from the SDK)
Error while talking to remote server (SDK throws some other exception)
So I want my method to have a return type Future[Option[Customer]], and return for each case above:
Successful Future: Some(customer)
Successful Future: None
Failed Future
Here is what I wrote using try/catch:
private def findCustomer(userId: Long): Future[Option[Customer]] = future {
try {
Some(gateway.find(userId))
} catch {
case _: NotFoundException => None
}
}
This works fine and seems clean to me, but doesn't seem to be really the "Scala way" to do it - I've been told to avoid using try/catch. So I've been looking for a way to rewrite it using a Try instead.
Here are 2 variants that (I think) behave exactly the same, using a Try.
Variant A:
private def findCustomer(userId: Long): Future[Option[Customer]] = future {
Try(
Some(gateway.find(userId))
).recover {
case _: NotFoundException => None
}.get
}
Variant B:
private def findCustomer(userId: Long): Future[Option[Customer]] = future {
Try(
Some(gateway.find(userId))
).recover {
case _: NotFoundException => None
}
} flatMap {
case Success(s) => Future.successful(s)
case Failure(f) => Future.failed(f)
}
I'm not a huge fan of A (even though it's more concise than B) since the .get seems a bit treacherous. B is definitely the most explicit but mapping the Try cases to corresponding Future outcomes seems boring.
How would an experienced Scala programmer write this?
I think your initial version using try/catch is perfectly fine, because it's a wrapper around an existing SDK.
Alternatively, you can use the recover method on Future:
def findCustomer(userId: Long): Future[Option[Customer]] =
Future(Option(gateway.find(userId))).recover {
case e: NotFoundException => None
}
One option is to avoid chaining Try and Future. In a sense, a future is an asynchronous Try.
You could use Future[Customer] directly and consider NotFoundException as something to recover from rather than a None value. Normally, you would chain operation on the future itself, with no need to deal with the failure cases (by mapping it, etc). It all depends on how you are going to use it (how your logic branches when the future is completed). In other words, maybe it seems convoluted to you because it is, and you are forcing it to be by forcing the Future[Option[Customer]] return type.
The ability to do chain multiple operations and carry on with computing if and only if all if going all right is the nice Scala feature here (especially on for comprehensions, etc).
You might be looking for:
Future.fromTry(myTry)
So for your example you might do:
Future.fromTry {
Try(Some(gateway.find(userId))).recover {
case _: NotFoundException => None
}
}
To only catch the NotFoundException, as in your solution. The only problem here is that the method won't be executed asynchronously. If that is necessary, consider using Future.recover, as suggested by Ionut.
Another idiomatic option worth mentioning here is to use Either[F, S], where S is the type of the successful return, and F can hold the errors (which you might want to propagate). So you could use Either[ Exception, Option[String]] or Either[String, Option[String]] where the first String is an error message.
If you're ready to adopt some scalaz. disjunction from scalaz is very useful and natural in handling erronous scenarios. It's like scala Either but scalaz disjunction \/ is right biased. you'll have success value on the right and exception on left. wrapping your code block with \/.fromTryCatch returns exception on the left side of disjunction. right will always have success value. mapping over disjunction is easiser than Scala Either since disjunction is right biased and easily gives you value from right.
import scalaz.\/
private def findCustomer(userId: Long): Future[\/[Throwable,Option[Customer]] ]= future {
\/.fromTryCatch {
Some(gateway.find(userId))
}
}

Fusing execution flow and exception flow in Scala

I am using the following to wrap a Boolean function and return its success status:
def wrapper(wrapped: => Boolean) : Boolean = { // this form of prototype takes a function by name
try {
return wrapped
} catch {
case anyException : Throwable =>
log(anyException.toString)
return false }
}
The rationale being that the wrapper function should return an overall binary status, regardless of whether the wrapped function failed to capture its own unexpected exceptions and do the same. So the wrapper conveys success and failure via its Boolean return value. It can also be an Option for function result data, rather than a Boolean.
How would you accomplish this in other, even better ways, in Scala?
I note that one rationale (of few others) for this code, admittedly has been that try catch blocks are cumbersome in flow control blocks. Another has been that I tend to use this pattern a lot in a certain area of my project.
You can use Try. Although it will catch only NonFata(scala.util.control.NonFatal) but in most cases this is what you do want.
import scala.util.Try
def wrapper(predicate: => Boolean) : Boolean = {
Try(predicate) getOrElse false
}
Or another way (For example if you really do want to catch any Throwable)
import scala.util.control.Exception._
def wrapper(predicate: => Boolean) : Boolean = {
catching(classOf[Throwable]) opt predicate getOrElse false
}
Scala provides Try feature, which is intended to be used in this occasions.
Notice that keeping your current wrapper leads to potential several errors. When you get a false result, you cannot know if it came from an application exception or a simple false evaluation. Thus, you can't properly handle any exception in your system, which may lead to multiple inconsistencies. Moreover, when you get a false result, your application internal state could be considered as unknown, making it very difficut to look into the box to know if the cat is dead or alive.
To solve this, scala's Try feature will handle this possible states for you, returning -in your case- a Success(elem: Boolean) in case your predicate effectively executes, and a Failure(ex: Throwable) in case an exception was thrown during execution. Then, you can use pattern matching to find out which was the case:
import scala.util.{Try, Success, Failure}
[...]
Try(predicate) match {
case Success(bool) => bool
case Failure(ex) => /* Do something to handle ex */
}
This somehow eliminates the need of your wrapper, for you can keep Try's result and then either match it or get it's result whenever you need to. And, as seen in previous answers, there is a rather complete set of operations you can use to handle all this cases in a more fashionable way.