autowire icon indicating copy to clipboard operation
autowire copied to clipboard

Can't Use API Factory Functions for Namespacing Purposes

Open michaelahlers opened this issue 8 years ago • 3 comments

In a similar vein as #7, I wish to have functions (or values) on my auto-wired API that serve as namespaces for more specific functionality. The following variant on the Minimal Example illustrates the intent:

import autowire._
import upickle._

trait MySpecificApi {
  def doThing(i: Int, s: String): Seq[String]
}

object MySpecificApiImpl extends MySpecificApi {
  def doThing(i: Int, s: String) = Seq.fill(i)(s)
}

trait MyApi {
  def mySpecificApi: MySpecificApi
}

object MyApiImpl extends MyApi {
  override val mySpecificApi: MySpecificApi = MySpecificApiImpl
}

object MyServer extends autowire.Server[String, upickle.Reader, upickle.Writer]{
  def write[Result: Writer](r: Result) = upickle.write(r)
  def read[Result: Reader](p: String) = upickle.read[Result](p)

  val routes = MyServer.route[MyApi](MyApiImpl)
}

object MyClient extends autowire.Client[String, upickle.Reader, upickle.Writer]{
  def write[Result: Writer](r: Result) = upickle.write(r)
  def read[Result: Reader](p: String) = upickle.read[Result](p)

  override def doCall(req: Request) = {
    println(req)
    MyServer.routes.apply(req)
  }
}

MyClient[MyApi].mySpecificApi.doThing(3, "lol").call().foreach(println)

This fails to compile with an error similar to:

Error:(27, 38) A$A36.this.MySpecificApi does not take parameters
  val routes = MyServer.route[MyApi](MyApiImpl)
                                    ^

Is this supported, and—in any case—is there any other preferred approach?

michaelahlers avatar May 17 '17 18:05 michaelahlers

Is this duplicative of #22?

michaelahlers avatar May 17 '17 18:05 michaelahlers

I also wanted to separate my Apis and went for this approach (maybe also works for you?):

trait MySpecificApi {
  def doThing(i: Int, s: String): Seq[String]
}

trait My MyOtherApi {
  def doOtherThing(): String
}

// server
object MySpecificApiImpl extends MySpecificApi {...}
object MyOtherApiImpl extends MyOtherApi {...}
val route = MyServer.route[MySpecificApi](MySpecificApiImpl) orElse MyServer.route[MyOtherApi](MyOtherApiImpl)

// client
object MyApis {
  val specificApi = MyClient[MySpecificApi]
  val otherApi = MyClient[MyOtherApi]
}

cornerman avatar Nov 20 '17 19:11 cornerman

@cornerman, that's a great suggestion. I'll give that a whirl!

michaelahlers avatar Nov 20 '17 19:11 michaelahlers