0

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)
      }
  }

}
user3451476
  • 297
  • 1
  • 4
  • 17
  • Sorry if my post is not clear. I want to create an app Object from the appcontext, as the Java API is execute(app) – user3451476 May 20 '16 at 06:30

1 Answers1

2

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)

Olivier Samyn
  • 1,105
  • 8
  • 13
  • Also, Could you please explain how `def process(context: AppContext): T = block(context)` works. I understand the concept of closures being used. But I'm still not able to get it in this piece of code – user3451476 May 20 '16 at 17:04
  • I am getting a runtime error - override method **process** in trait App of type (AppContext)T - method call has incompatible type.. – user3451476 May 20 '16 at 19:16
  • Actually. that is because we have the implicit class as a value class. Tat fixed the issue. But it would be great if someone could post on why the implicit class cannot be a value class in this code – user3451476 May 20 '16 at 20:06
  • 1
    The method `def process(context: AppContext): T = block(context)` works because `block` parameter is defined as a function that takes an `AppContext` as parameter and returns a T. So, when the process method is called, we call the function defined by block, giving it the received context as parameter, and returning it's value. – Olivier Samyn May 20 '16 at 20:46
  • I edited my answer; a value class may not contain an inner class. And so, I just extracted the anonymous App class. For more info, see http://docs.scala-lang.org/overviews/core/value-classes.html#limitations – Olivier Samyn May 20 '16 at 20:57