Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a Java Future to a Scala Future

I have a Java Future object which I would like to convert into a Scala Future.

Looking at the j.u.c.Future API, there is nothing much that I could use other than the isDone method. Is this isDone method blocking?

Currently this is what I have in my mind:

val p = Promise()
if (javaFuture.isDone())
  p.success(javaFuture.get)

Is there a better way to do this?

like image 317
joesan Avatar asked Jan 27 '16 09:01

joesan


People also ask

What is the difference between a Java Future and a Scala Future?

A Java Future works in a synchronous blocking way. It does not work in an asynchronous non-blocking way, whereas a Scala Future works in an asynchronous non-blocking way. If we want an asynchronous non-blocking feature, we should use Java 8's CompletableFuture.

Is Scala the future?

Future represents a result of an asynchronous computation that may or may not be available yet. When we create a new Future, Scala spawns a new thread and executes its code. Once the execution is finished, the result of the computation (value or exception) will be assigned to the Future.

What is Future object in Scala?

A Future is a placeholder object for a value that may not yet exist. Generally, the value of the Future is supplied concurrently and can subsequently be used. Composing concurrent tasks in this way tends to result in faster, asynchronous, non-blocking parallel code.

What is Future type in Java?

A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation.


3 Answers

Starting Scala 2.13, the standard library includes scala.jdk.FutureConverters which provides Java to Scala CompletableFuture/Future implicit conversions:

import scala.jdk.FutureConverters._

// val javaFuture = java.util.concurrent.CompletableFuture.completedFuture(12)
val scalaFuture = javaFuture.asScala
// scalaFuture: scala.concurrent.Future[Int] = Future(Success(12))
like image 170
Xavier Guihot Avatar answered Oct 17 '22 10:10

Xavier Guihot


How about just wrapping it (I'm assuming there's an implicit ExecutionContext here):

val scalaFuture = Future {
    javaFuture.get
}

EDIT:

A simple polling strategy could look like this (java.util.Future => F):

def pollForResult[T](f: F[T]): Future[T] = Future {
    Thread.sleep(500)
    f
  }.flatMap(f => if (f.isDone) Future { f.get } else pollForResult(f))

This will check if the Java future is done every 500ms. Obviously the total blocking time is the same as above (rounded up to the nearest 500ms) but this solution will allow other tasks to be interleaved in the same thread of the ExecutionContext.

like image 31
pablochan Avatar answered Oct 17 '22 09:10

pablochan


For those reading this question now, if you're using Scala 2.13 and above, use:

import scala.jdk.FutureConverters._

And convert using completableFuture.asScala

If you're using Scala 2.12 and below, use

import scala.compat.java8.FutureConverters._

And convert using: toScala(completableFuture) or completableFuture.toScala

Also, in Scala 2.12 make sure you're using the correct artifact:

org.scala-lang.modules:scala-java8-compat_2.12:0.9.0

Now, if for some reason what you have is actually a Future and not CompletableFuture, which should be a rare case nowadays, please follow first one of those answers: Transform Java Future into a CompletableFuture

like image 12
Alexey Soshin Avatar answered Oct 17 '22 09:10

Alexey Soshin