user3451476
user3451476

Reputation: 307

Scala wrapper API for java API

I am new to Scala and I need to have a scala wrapper for my Java API

I have three Java Interfaces

public interface Client<T> {

   <T> Future<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);

}

Following is the Java code to create an App

public class RandomApp extends App<String> {

  @Override
  public String process(AppContext context) {

      // Inorder to access the methods in AppContext I need to access  
      // it by the following way

      appContext.createDirectory("some path");
      return "random";
  }
 }

I want to have a Scala Wrapper for the Client Interface which in turn call the Java API. But I have some modifications for the new Scala API

object ScalaConverter {

  implicit class ScalaWrapper(client: Client) {

  def scalaClient = new ScalaClient(client)

  }
}

class ScalaClient(client: Client) {

  def execute[T](appContext: AppContext => T): Future[T] = {

      // I am passing appContext as closure instead of passing in
      // App because I want to take the advantage of Closures in Scala

      // I basically want to create an App with this appContext and
      // pass it to the execute method

      // For example - but this is not working

      var app = // Need to create this app with appContext

      Future {
        client.execute(app)
      }
  }

}

Upvotes: 0

Views: 1212

Answers (1)

Olivier Samyn
Olivier Samyn

Reputation: 1115

If I'm not mistaken, you just want to be able to create App objects from a function that takes a AppContext as parameter and returns a any object (let's say T).

As it's not really interesting to try to mirror the whole java API, just use it as it is, but add some extensions. And to do this you should use implicits.

To do this, I see two possibilities: either add an implicit class on the Client interface to add some functions to it, or add an implicit conversion from (AppContext => T) to App objects.

Let's got with the first solution, you have to embed the implicit class in an object (this can be a package object if you need automatic imports).

object ScalaConverter {
  class ScalaApp[T](val block: AppContext => T) extends App[T] {
    def process(context: AppContext): T = block(context)
  }

  implicit class ScalaClient(client: Client) extends AnyVal{
    def execute[T](block: AppContext => T): Future[T] = {
      client.execute(new ScalaApp(block))
    }
  }
}

Then, you just have to use your existing java Client object:

import ScalaConverter._
myJavaClient.execute { context => 
   ???
}

You should get the principle, I maybe made a mistake (did not tried to compile this)

Upvotes: 2

Related Questions