I'm using Spray and have a Base Route trait which defines a number of functions that should be implemented...
trait ServiceBaseRoute extends HttpService {
def function1():Type
def function2():Type
lazy val serviceBaseRoute = ...
I then mixin this trait to a number of other traits...
trait MyRoute1 extends HttpService
with ServiceBaseRoute {
override def function1():Type = {...}
override def function2():Type = {...}
val myRoute1 = serviceBaseRoute
and...
trait MyRoute2 extends HttpService
with ServiceBaseRoute {
override def function1():Type = {...}
override def function2():Type = {...}
val myRoute2 = serviceBaseRoute
Finally I construct the top level of the route as follows...
trait V1Routes extends HttpService
with MyRoute1
with MyRoute2 {
val v1Routes =
pathPrefix("v1") {
authenticate(...) {
myRoute1 ~ myRoute2
}
}
Compiles fine etc... However when I run this the function overrides of MyRoute2 override those defined in MyRoute1. I am thinking this is because I don't have actual instances of MyRoute1 and MyRoute2 as they are being simply mixed in and since MyRoute2 is added in after MyRoute1 its values overwrite those of MyRoute1?
So what would be the best way to implement this preserving the overrides defined in each trait?
Do I need to define MyRoute1 and MyRoute2 as objects instead?
Thanks
Based on your comments, the aim is to have distinct routes in MyRoute1 and MyRoute2, where each is created by customizing serviceBaseRoute. Since ServiceBaseRoute is customized by two functions, you could make serviceBaseRoute a higher order function and pass the implementations of the two functions to it in the sub traits:
trait ServiceBaseRoute extends HttpService {
def serviceBaseRoute(f1: () => Type, f2: () => Type)= ???
}
trait MyRoute1 extends HttpService
with ServiceBaseRoute {
def f1ImplA(): Type = ???
def f2ImplA(): Type = ???
val myRoute1 = serviceBaseRoute(f1ImplA, f2ImplA)
}
trait MyRoute2 extends HttpService
with ServiceBaseRoute {
def f1ImplB(): Type = ???
def f2ImplB(): Type = ???
val myRoute2 = serviceBaseRoute(f1ImplB, f2ImplB)
}
trait V1Routes extends HttpService
with MyRoute1
with MyRoute2 {
val v1Routes =
pathPrefix("v1") {
authenticate(...)
{
myRoute1 ~ myRoute2
}
}
}
Related
I am trying to create a serializable trait that has a dependency on type class.
package dsl
import zio.schema._
sealed trait Random[A] {
def generate: A
}
object Random {
case object RandomDouble extends Random[Double] {
override def generate: Double = ???
implicit val RandomDoubleSchema: Schema[Random[Double]] = DeriveSchema.gen[Random[Double]]
}
}
sealed trait DummyExpr[A] {
def eval(value: DummyExpr[A]): A
}
object DummyExpr {
case object DummyTrue extends DummyExpr[Boolean] {
override def eval(value: DummyExpr[Boolean]): Boolean = ???
}
case object DummyFalse extends DummyExpr[Boolean] {
override def eval(value: DummyExpr[Boolean]): Boolean = ???
}
case class DummyOperator[A](random: Random[A], predicate: DummyExpr[Boolean]) extends DummyExpr[A] {
override def eval(value: DummyExpr[A]): A = ???
}
}
object main extends App {
val schemaRandom = DeriveSchema.gen[Random[Double]]
val schemaDummy = DeriveSchema.gen[DummyExpr[Double]]
}
Here is a reproducible link https://scastie.scala-lang.org/3PnmF52hSkuduzGP10wTdg
But type derivation for this fails with the error magnolia: could not find any direct subtypes of trait Random
I am using zio-schema which internally uses magnolia. I tried adding implicit Derivation of typeclass too but that didn't help too.
I have a trait and a class that extends the trait. I can use the methods from the trait as follows:
trait A {
def a = ""
}
class B(s: String) extends A {
def b = a
}
However, when I use the trait's method in the constructor like this:
trait A {
def a = ""
}
class B(s: String) extends A {
def this() = this(a)
}
then the following error appears:
error: not found: value a
Is there some way to define default parameters for the construction of classes in the trait?
EDIT: To clarify the purpose: There is the akka-testkit:
class TestKit(_system: ActorSystem) extends { implicit val system = _system }
And each test looks like this:
class B(_system: ActorSystem) extends TestKit(_system) with A with ... {
def this() = this(actorSystem)
...
}
because I want to create common creation of the ActorSystem in A:
trait A {
val conf = ...
def actorSystem = ActorSystem("MySpec", conf)
...
}
It's a little bit tricky because of Scala initialization order. The simplest solution I found is to define a companion object for your class B with apply as factory method:
trait A {
def a = "aaaa"
}
class B(s: String) {
println(s)
}
object B extends A {
def apply() = new B(a)
def apply(s: String) = new B(s)
}
I'm writing a facade to use CreateJS lib in scala, like this
object CreateJS
{
sealed trait EventListener extends js.Object
type EventHandler = js.Function
class DisplayObject extends js.Object
{
}
class Container extends DisplayObject
{
def addChild(item:DisplayObject):Unit = ???
def update():Unit = ???
}
#JSName("createjs.Stage")
class Stage(canvasId:String) extends Container with EventListener
// TODO: Is enum done this way ???
object MovieClip
{
#JSName("createjs.MovieClip")
var INDEPENDENT:String = _
#JSName("createjs.SINGLE_FRAME")
var SINGLE_FRAME:String = _
#JSName("createjs.SYNCHED")
var SYNCHED:String = _
}
#JSName("createjs.MovieClip")
class MovieClip(mode:js.String=MovieClip.INDEPENDENT,startPosition:js.Number=0, loop:js.Boolean=true, labels:js.Object = null) extends DisplayObject
{
def addEventListener(eventName:String, target:EventHandler):Unit = ???
var timeline:TimeLine = _
def gotoAndPlay(where:String):Unit = ???
}
class TimeLine extends js.Object
{
def addTween(tween:Tween):Unit = ???
}
#JSName("createjs.Shape")
class Shape(graphics:Graphics = null) extends DisplayObject
#JSName("createjs.Graphics")
class Graphics extends js.Object
{
def beginFill(color:String):Graphics = ???
def drawCircle(x:js.Number, y:js.Number, r:js.Number):Graphics = ???
}
#JSName("createjs.Ticker")
object Ticker extends js.Object
{
def addEventListener(eventName:String, handler:EventHandler):Unit = ???
def addEventListener(eventName:String, stage:Stage):Unit = ???
}
class Tween extends js.Object
{
def get(item:DisplayObject):Tween = ???
def to(state:js.Dynamic, time:js.Number = 0):Tween = ???
}
#JSName("createjs.Tween")
object Tween extends Tween
/* Load queue */
class Plugin extends js.Object
#JSName("createjs.Sound")
object Sound extends Plugin {
def play(soundId:String):Unit = ???
}
#JSName("createjs.LoadQueue")
class LoadQueue(useXHR:Boolean = true, basePath:String="", crossOrigin:String="") extends js.Object
{
def installPlugin(plugin:Plugin):Unit = ???
def on(event:String, handler:EventHandler):Unit = ???
def addEventListener(event:String, handler:EventHandler):Unit = ???
def loadFile(params:js.Dynamic):Unit = ???
def loadManifest(paramList:js.Array[js.Dynamic]):Unit = ???
}
}
This file becomes just a large pile.
In real createJS these are split in 4 files - easel, tween, sound and preload, each extending base createjs object. Is it possible I do this file separation in scala while keeping everything in CreateJS namespace?
(Maybe such port already exist?)
You can split code in different trait, each one responsible for a coherent aspect (and gathering related functions), each trait in a separate file, then have the public singleton facade object exposing all.
For example with trait A implementing function foo and bar in file A.scala, and trait B with functions oof and rab in file B.scala, then facade object can be declared like object Facade extends A with B.
In this way, I would suggest to declare trait as package private, as they are there only to organise code: private[mypackage] trait A { ... }.
I'd like some help sorting out this scenario. I have an Akka actor where I want to inject a dependency, in this case RemoteFetcher, which I would also like mock in my tests. Like so:
main/src/scala/mypackage/Services.scala
package mypackage
import RemoteFetcherFileSystem._
trait RemoteFetcher {
def fetch( path:String ): Future[Stream[String]]
}
class MyRemoteResourceActor extends Actor with ActorLogging {
def fetchRemote( path:String ) = implicitly[RemoteFetcher].fetch( path )
def receive = {
case FetchRemoteResource( path ) => fetchRemote( path ).map( _.foreach( sender ! _ ) )
}
}
For this to work I have an implicit object that I import into the file above. Would look something like this:
implicit object RemoteFetcherFileSystem extends RemoteFetcher {
def fetchRemote( path:String ) = Future[Stream[String]] { ... reading from file system ... }
}
Now in my tests I have TestActor from the akka-testkit. Here I want to instead import my mock dependency:
implicit object RemoteFetcherMock extends RemoteFetcher {
def fetchRemote( path:String ) = Future[Stream[String]] { ... mock implementation ... }
}
My problem is that to compile Services.scala I need to import the implicit object. But how do I go about to shadow/override this in my test-files. The reason I'm not using implicit arguments is that I want to avoid having to modify all my actors constructor arguments.
I when looking around and reading up on the type class dependency injection pattern and I get it to work according to the tutorials, but I don't get it to work when I want to test and override like in my example.
I'm not sure how to do it with implicits, but typically one could inject instead like so:
trait RemoteFetcherComponent {
def remoteFetcher: RemoteFetcher
trait RemoteFetcher {
def fetch(path: String): Future[Stream[String]]
}
}
trait RemoteFetcherFileSystemComponent extends RemoteFetcherComponent {
val remoteFetcher = RemoteFetcherFileSystem
object RemoteFetcherFileSystem extends RemoteFetcher {
def fetch(path: String): Future[Stream[String]] = ???
}
}
class MyRemoteResourceActor extends Actor with ActorLogging with RemoteFetcherFileSystemComponent {
def fetchRemote(path: String) = remoteFetcher.fetch(path)
def receive = {
case FetchRemoteResource(path) => fetchRemote(path).map( _.foreach(sender ! _))
}
}
val myRemoteResourceActor = new MyRemoteResourceActor()
And then a test value would be defined like so:
trait RemoteFetcherMockComponent extends RemoteFetcherComponent {
def remoteFetcher = RemoteFetcherMock
object RemoteFetcherMock extends RemoteFetcher {
def fetch(path: String): Future[Stream[String]] = ???
}
}
val myMockedResourceActor = new MyRemoteResourceActor with RemoteFetcherMockComponent {
override val remoteFetcher = super[RemoteFetcherMockComponent].remoteFetcher
}
The reason you are having an issue with implicits is because the way you're using it is no different from simply using def fetchRemote(path: String) = RemoteFetcherFileSystem.fetch(path). With the import, you've defined the implementation, rather than allowed it to be injected later.
You could also change the implicitly to an implicit parameter:
trait RemoteFetcher {
def fetch(path: String): Future[Stream[String]]
}
object RemoteFetcher {
implicit val fetcher = RemoteFetcherFileSystem
}
class MyRemoteResourceActor extends Actor with ActorLogging {
def fetchRemote(path: String)(implicit remoteFetcher: RemoteFetcher) = remoteFetcher.fetch(path)
def receive = {
case FetchRemoteResource(path) => fetchRemote(path).map( _.foreach(sender ! _))
}
}
Then you could override the implicit that is resolved in the companion object of RemoteFetcher by simply importing RemoteFetcherMock.
See this post for more information about implicit parameter resolution precedence rules.
Most of the examples of the Cake Pattern I've come across appear to consider dependencies as singleton type services; where there is only one instance of each type in the final assembly of components. Is it possible to write a configuration that has more than one instance of a particular type, perhaps configured in different ways, when using the Cake Pattern for dependency injection?
Consider the following components. Generic HTTP service:
trait HttpService { def get(query:String):String }
trait HttpServiceComponent {
val httpService:HttpService
class HttpServiceImpl(address:String) extends HttpService {
def get(query:String):String = ...
}
}
Trade & Company services, that each depend on an HttpService, which may be different instances:
trait TradeService { def lastTrade(symbol:String):String }
trait TradeServiceComponent {
this:HttpServiceComponent => // Depends on HttpService
val tradeService:TradeService
class TradeServiceImpl extends TradeService {
def lastTrade(symbol:String):String =
httpService.get("symbol=" + symbol)
}
}
trait CompanyService { def getCompanySymbols(exchange:String):String }
trait CompanyServiceComponent {
this:HttpServiceComponent => // Depends on different HttpService instance
val companyService:CompanyService
class CompanyServiceImpl extends CompanyService {
def getCompanySymbols(exchange:String):String =
httpService.get("exchange=" + exchange)
}
}
Main app component that depends on Trade & Company services:
trait App { def run(exchange:String):Unit }
trait AppComponent {
this:CompanyServiceComponent with TradeServiceComponent =>
val app:App
class AppImpl extends App {
def run(exchange:String) =
companyService.getCompanySymbols(exchange).split(",").foreach(sym => {
val lastTrade = tradeService.lastTrade(sym)
printf("Last trade for %s: %s".format(sym, lastTrade))
})
}
}
Is it possible to wire up the App so that its TradeService uses a HttpService that points to one address, and its CompanySerivce uses a different HttpService instance pointing to another address?
As you can see from the answers (notably Daniel's, but also your own), it is possible, but it doesn't look elegant. The difficulty appears because when you use the Cake pattern, you mix all required traits into one object (using "with" keyword), and you cannot mix a trait more than once into one instance. That is how mixins work, and the Cake is based on them.
The fact you can force Cake to handle non-singleton dependencies doesn't mean you should do it. I would advise you to simply use plain-old constructor in such cases, that is where self-type annotation doesn't fit well:
trait HttpService { ... }
/* HttpServiceImpl has become a top-level class now,
* as the Cake pattern adds no more value here.
* In addition, trait HttpServiceComponent gets deleted */
class HttpServiceImpl(address:String) extends HttpService {
...
}
trait TradeService { def lastTrade(symbol:String):String }
trait TradeServiceComponent {
// The dependency on HttpService is no longer declared as self-type
val tradeService:TradeService
// It is declared as a constructor parameter now
class TradeServiceImpl(httpService: HttpService) extends TradeService {
def lastTrade(symbol:String):String =
httpService.get("symbol=" + symbol)
}
}
trait CompanyService { def getCompanySymbols(exchange:String):String }
trait CompanyServiceComponent {
// Again, self-type annotation deleted
val companyService:CompanyService
// Again, the dependency is declared as a constructor parameter
class CompanyServiceImpl(httpService: HttpService) extends CompanyService {
def getCompanySymbols(exchange:String):String =
httpService.get("exchange=" + exchange)
}
}
The App and AppComponent traits stay in their original form. Now you can use the all components in the following way:
object App {
def main(args:Array[String]):Unit = {
val appAssembly = new AppComponent
with TradeServiceComponent
with CompanyServiceComponent {
// Note, that HttpServiceComponent it neither needed nor mixed-in now
val tradeService = new TradeServiceImpl(
new HttpServiceImpl("http://trades-r-us.com"))
val companyService = new CompanyServiceImpl(
new HttpServiceImpl("http://exchange-services.com"))
val app = new AppImpl
}
appAssembly.app.run(args(0))
}
}
Also, you may want do double-check if the Cake pattern is really best suited for your needs, as it is actually a complex pattern and dependency injection is only one part of it. If you use it only for DI, I would advise you to use a simpler solution. I've blogged about that here.
Since each "client" may need a different implementation, you could just parameterize the service.
trait HttpService { def get(query:String):String }
trait HttpServiceComponent {
def httpService(name: String):HttpService
class HttpServiceImpl(address:String) extends HttpService {
def get(query:String):String = ...
}
}
To be used like this:
trait TradeService { def lastTrade(symbol:String):String }
trait TradeServiceComponent {
this:HttpServiceComponent => // Depends on HttpService
val tradeService:TradeService
class TradeServiceImpl extends TradeService {
def lastTrade(symbol:String):String =
httpService("TradeService").get("symbol=" + symbol)
}
}
The final mix would then do something like this:
trait AppComponent {
this:CompanyServiceComponent with TradeServiceComponent =>
val httpServices = Map( "TradeService" -> new HttpServiceImpl("http://trades-r-us.com"),
"CompanyService" -> new HttpServiceImpl("http://exchange-services.com"))
def httpService(name: String) = httpServices(name)
This compiles and runs as expected, but it leaves a lot to be desired:
object App {
def main(args:Array[String]):Unit = {
val tradeServiceAssembly = new TradeServiceComponent with HttpServiceComponent {
val httpService = new HttpServiceImpl("http://trades-r-us.com")
val tradeService = new TradeServiceImpl
}
val companyServiceAssembly = new CompanyServiceComponent with HttpServiceComponent {
val httpService = new HttpServiceImpl("http://exchange-services.com")
val companyService = new CompanyServiceImpl
}
val appAssembly = new AppComponent
with TradeServiceComponent
with CompanyServiceComponent
with HttpServiceComponent {
lazy val httpService = error("Required for compilation but not used")
val tradeService = tradeServiceAssembly.tradeService
val companyService = companyServiceAssembly.companyService
val app = new AppImpl
}
appAssembly.app.run(args(0))
}
}