user3451476
user3451476

Reputation: 307

Wrapper scala API over Java API

I am new to Scala and I am building a Scala wrapper for my Java API

I have four Java Interfaces

public interface Client<T> {
 <T> Handle<T> execute(App<T> app);
}

public interface App<T> extends Serializable{
  T process(AppContext context) throws Exception;
}

public interface AppContext {
  File getDirectory();
  void deleteDirectory();
  File createDirectory(String path);
}

public interface Handle<T> extends Future<T> {
   static interface Listener<T> {          
       void onSuccess(Handle<T> handle)
       void onFailure(Handle<T> handle, Throwable e)
   }

   void addListener(Listener<T> listener);
}

Here are my Scala Equivalents

trait Process[T] extends Future[T] { 
  // Few abstract methods
}


class ProcessImpl[T](handle: Handle[T]) extends Process[T] {

val promise = Promise[T]

override def isCompleted: Boolean = ???

override def onComplete[U](func: (Try[T]) => U)(implicit executor: ExecutionContext)  = {
  case Success(t) => promise.success(handle.get())
  case Failure(e) => promise.failure(e)
   }

override def value: Option[Try[T]] = ???

@throws(classOf[Exception])
override def result(atMost: Duration)(implicit permit: CanAwait): T = ???

@throws(classOf[InterruptedException])
@throws(classOf[TimeoutException])
override def ready(atMost: Duration)(implicit permit: CanAwait) = ???

 } 


class ScalaClient(javaClient: Client) {
   def execute[T](func: AppContext => T): ScalaHandle[T] = {
     val app = new App[T]
     @throws(classOf[Exception])
     override def process(AppContext context): T = func(context)

     val handle = javaClient.execute(app) // This returns a Handle obj. I want to convert it to ScalaHandle

    //My approach

     val scalahandle = new ProcessImpl(handle)       
     scalahandle
  }
}

I'm getting the following error

The argument types of an anonymous function must be fully known. (SLS 8.5)

Expected type was: Unit override def onComplete[U](func: (Try[T]) => U)(implicit executor: ExecutionContext) = {

Also, I want to know if my approach here is right

Upvotes: 1

Views: 184

Answers (1)

alf
alf

Reputation: 8523

Your problem isn't in onComplete per se—it's in the way you implement it.

override def onComplete[U](func: (Try[T]) => U)(implicit executor: ExecutionContext)  = {
  case Success(t) => promise.success(test.get())
  case Failure(e) => promise.failure(e)
}

Here, you define onComplete as a partial function from some function Try[_] => U—the type is not known, and it's definitely not overriding the original method, abstract def onComplete[U](f: (Try[T]) ⇒ U)(implicit executor: ExecutionContext): Unit. Note that no case matches anything here: the func is not a Try[T] here.

As a side note, I cannot but mention that you should never ever extend a Future. A very useful motto is, avoid inheritance at any cost. In your case, I don't think inheritance wins you anything—rather, it adds to confusion.

What you probably are looking for is,

def asFuture[T](handle: Handle[T]): Future[T] = {
  val promise = Promise[T]()
  handle.addListener(new Handle.Listener[T] {
    def onSuccess(handle: Handle[T]) {
      promise.trySuccess(handle.get())
    }
    def onFailure(handle: Handle[T], e: Throwable) {
      promise.tryFailure(e)
    }
  })
  promise.future
}

Upvotes: 4

Related Questions