Convert scala future to java future
Asked Answered
I

3

17

I have a generated java interface containing a method:

public Future<?> getCustomersAsync(AsyncHandler<Customer> asyncHandler);

I want to implement it using Akka. I wrote following:

override def getCustomerAsync(asyncHandler: AsyncHandler[Customer]): Future[_] = {
  myActorRef.ask(GetCustomer, system.actorOf(Props[Responder]))
}

The issue is that ask returns scala.concurrent.Future[Any] and the method must return java.util.concurrent.Future[?]:

Error:(33, 17) type mismatch;
 found   : scala.concurrent.Future[Any]
 required: java.util.concurrent.Future[?]
    myActorRef.ask(GetCustomer, system.actorOf(Props[Responder]))
                  ^

How can I do this conversion?

Indeciduous answered 2/2, 2015 at 12:31 Comment(0)
B
5

Well its not practical to convert them, because scala Future do not provide functionality to interrupt or any other mechanism for cancellation. So there is no direct full-proof way to cancel a future via interruption or otherwise via method call in Future.

So the simplest solution can be if cancellation is not desired would be:

  def convert[T](x:Future[T]):java.util.concurrent.Future[T]={
    new concurrent.Future[T] {
      override def isCancelled: Boolean = throw new UnsupportedOperationException

      override def get(): T = Await.result(x, Duration.Inf)

      override def get(timeout: Long, unit: TimeUnit): T = Await.result(x, Duration.create(timeout, unit))

      override def cancel(mayInterruptIfRunning: Boolean): Boolean = throw new UnsupportedOperationException

      override def isDone: Boolean = x.isCompleted
    }
  }

But in case if you still need cancel, a handicapped fix would be as shown

here. But I wouldn't recommend it though as its shaky

Busyness answered 2/2, 2015 at 18:35 Comment(0)
D
7

Starting Scala 2.13, the standard library includes scala.jdk.FutureConverters which provides Scala to Java Future conversions (and vice versa):

import scala.jdk.FutureConverters._

// val scalaFuture: scala.concurrent.Future[Int] = Future.successful(42)
scalaFuture.asJava
// java.util.concurrent.CompletionStage[Int] = <function1>

Note for Java users, you'd rather use FutureConverters the explicit way:

import scala.jdk.javaapi.FutureConverters;

// val scalaFuture: scala.concurrent.Future[Int] = Future.successful(42)
FutureConverters.asJava(scalaFuture);
// java.util.concurrent.CompletionStage[Int] = <function1>
Durman answered 2/4, 2019 at 2:27 Comment(1)
Could you please include the information how the converted future handles the cancellation?Indeciduous
B
5

Well its not practical to convert them, because scala Future do not provide functionality to interrupt or any other mechanism for cancellation. So there is no direct full-proof way to cancel a future via interruption or otherwise via method call in Future.

So the simplest solution can be if cancellation is not desired would be:

  def convert[T](x:Future[T]):java.util.concurrent.Future[T]={
    new concurrent.Future[T] {
      override def isCancelled: Boolean = throw new UnsupportedOperationException

      override def get(): T = Await.result(x, Duration.Inf)

      override def get(timeout: Long, unit: TimeUnit): T = Await.result(x, Duration.create(timeout, unit))

      override def cancel(mayInterruptIfRunning: Boolean): Boolean = throw new UnsupportedOperationException

      override def isDone: Boolean = x.isCompleted
    }
  }

But in case if you still need cancel, a handicapped fix would be as shown

here. But I wouldn't recommend it though as its shaky

Busyness answered 2/2, 2015 at 18:35 Comment(0)
L
1

I don't think that there is a easy way to convert scala Future to java Future. One possible solution is to wrap scala future by java future but you must pass a new task to the thread pool, see java docs: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html

Lietuva answered 2/2, 2015 at 16:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.