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?
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.
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.
By default, futures and promises are non-blocking, making use of callbacks instead of typical blocking operations. To simplify the use of callbacks both syntactically and conceptually, Scala provides combinators such as flatMap , foreach , and filter used to compose futures in a non-blocking way.
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.
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>
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With