3
votes

In this problem I have to call a third-party Java library that expects a java.util.concurrent.Future with a result from a Scala routine returning a scala.concurrent.Future as for example.

def someScalaFunction(): scala.concurrent.Future[T]

def otherJavaMethod(arg: java.util.concurrent.Future[T]) = ...

I would wrap the Scala-Future into a new Java-Future, however there is no way to implement the Java-Future method def cancel(mayInterruptIfRunning: Boolean): Boolean in a way it interrupts the wrapped Scala-Future (if otherwise please let me know).

How can I solve this problem? These are the approaches I come up with:

  1. write the wrapper anyway and just ignore the call on cancel (or throw an NotImplementedError)
  2. change someScalaFunction to maybe return a closure that will then be wrapped by the caller in a Scala or Java Future.

The problem with 1. is that some client could rely on the proper implementation of cancel but is maybe not very critical. 2. would result in a really ugly api.

1

1 Answers

3
votes

Note that the cancel only attempts to cancel the task, there are no guarantees according to the Javadoc. So you don't really have to implement it to do something -- depending on what the future computation is, ignoring the cancel call may not be subsequential for the entire application.

If you really need to cancel it, see this question for a half-solution.

Otherwise, you could use your second solution -- with the help of some implicit conversions you could make it look nicer.

object JavaInterOp {
  implicit def f2future[F[_]](f: () => T): java.util.concurrent.Future[T] = fc(f)
}

This way, the import controls which conversion you want to provide and when.

One issue with this is that it might do the conversion where you don't really want it -- it might yield surprising effects.