Guice Assisted Inject with Providers or FactoryModuleBuilder - scala

This is kind of a weird use-case and I need some help in figuring out how to use Assisted/Providers/FactoryModuleBuilders in conjunction with each other. Ignore the absence of #Singleton. This is just an example.
A set of traits belonging to a library I cannot change have the following pattern. It uses Cake Pattern.
trait A { //Has abstract methods and abstract service 'webService' }
trait B extends A { //First Concrete Service Implementation assigned to 'webService' }
trait C extends A { //Second Concrete service Implementation assigned to 'webService' }
Since the traits cannot be directly injected, I created a wrapper that would allow them to be injected
BB extends B
CC extends C
In my code, I have a Controller that depends on a Service, that in turn depends on the library. The service should be able to either use "BB" or "CC" depending on what the controller needs. So the components look like the following
I create my service as
//Note: Uses 'trait A' with #Assisted
class SomeWebServiceComponent #Inject()(#Assisted aInstance: A, foo: Foo){
//Do something with aInstance
}
The Factory to create this (should be created by Guice by using FactoryModuleBuilder)
class SomeServiceFactory {
def getWebServiceComponent(a:A) SomeWebServiceComponent
}
The FactoryModule will look something like this
class ApplicationModule extends AbstractModule {
override def configure() = {
install(new FactoryModuleBuilder().build(classOf[SomeServiceFactory]))
}
}
I don't mind annotating the controllers with the actual classes that I need.
class OneController #Inject()(factory: SomeServiceFactory, bb: BB) extends Controller {
val webServiceComponent = factory.getWebServiceComponent(bb)
}
class AnotherController #Inject()(factory: SomeServiceFactory, cc: CC) extends Controller {
val webServiceComponent = factory.getWebServiceComponent(cc)
}
With this setup, I get errors of the following kind
No implementation for 'A' annotated with #com.google.inject.assistedinject.Assisted(value=) was bound
I need to understand how I can tell Guice that there are two implementations for Trait A, namely, BB and CC and the choice will be supplied at runtime.
Is there a way to achieve this use-case?

Ok, I created a separate project to test this whole scenario.
And it works the way the question is framed.
It turns out, the test cases that I were using, were not currently using GuiceInjection directly. The error message was however, so specifically related to GuiceInjection that I never investigated if the test setup was correct.
Changing the test base, resolved the issue.

Related

Is it possible to have the view implementation hidden in a Scala application?

My goal is to have an MVC pattern in a simulation application where the controller knows there is a view (and interacts with it using an interface) but doesn't know how it is implemented:
object Controller extends App {
View.initView()
...
}
object View {
stage: Stage = ...
def initView: Unit = {
...
}
}
However I only managed to do so having the entry point of the program to extend scalafx.application.JFXApp, javafx.application.Application (example below) or swing.SimpleSwingApplication which forces the controller to know how the view is implemented. Is there any simple workaround?
def main(args: Array[String]): Unit = {
Application.launch(classOf[SimulatorApp])
}
class SimulatorApp extends Application {
override def start(stage: Stage): Unit = {
View.initView(stage)
}
}
Well, you can design your application as abstract e.g.
class MyApplication(dependency1: Dependency1, dependency2: Dependency2)
extends Application {
// code using things
}
and then pass implementations somewhere else
class MyApplicationImplemented
extends MyApplication(implementation1, implentation2)
Application.launch(classOf[MyApplicationImplemented])
where dependencies could be:
instances
recipes for instances (functions)
configs
etc.
You can also make some methods abstract and implement them in some top level.
In general you treat your final Application implementation as class with main method - this is not an object you pass dependencies into but a place where you finally wire them together. So in the end you have to design it to be your main. (launch methods' signatures confirm that this is the intent).
That said a lot of logic can be extracted into traits or abstract classes or components so that you could have some general logic somewhere else, have it rely on dependency injection, create several implementations, and wire them in separate "mains" for e.g. production code and end-to-end tests.

Check if Scala class is instance of T

My application handles a lot of third party integrations. I have an abstract base class for third party integrations which specifies a bunch of methods that an integration class should handle – then certain integrations can be extended with additional functionality that is not available on all integrations.
Basically it looks like this:
abstract class Integration { ... }
trait SingleSignOn { ... }
class NormalIntegration extends Integration {}
class SingleSignOnIntegration extends Integration with SingleSignOn {}
I would like to be able to sort out all integrations that have a specific trait, and this is what I thought of as the basic solution:
val allIntegrations: Seq[Integration] = ...
def integrationsWithTrait[T]: Seq[Integration] = {
allIntegrations.filter(_.isInstanceOf[T])
}
The usage is:
val singleSignOnIntegrations = integrationsWithTrait[SingleSignOn]
The issue is that isInstanceOf[T] always returns true (meaning I end up with singleSignOnIntegrations == allIntegrations), while hard coded isInstanceOf[SingleSignOn] works as intended.
How do I fix integrationsWithTrait to work as I intend?
This will work:
def integrationsWithTrait[T](implicit tag: scala.reflect.ClassTag[T]): Seq[Integration] = {
allIntegrations.filter(tag.runtimeClass.isInstance)
}
Scalac will inject ClassTag instance for every class that this method will be called with. This will allow to access the Class object in runtime and verify if the class is the instance of given class/trait.
I think the original code doesn't work because of type erasure.

Guice bind a class and its adapter

I would like implement a Guice module which binds an adapter to a named argument, but to create this adapter, it needs to instantiate another class, which also need injected arguments.
Here is the example in Scala:
trait Service
class UserService #Inject()(#Named(value = "foo") foo: String) extends Service
trait Adapter
class AdapterImpl(service: Service) extends Adapter
class AdapterRef(val adapter: Adapter)
class Module extends AbstractModule {
override def configure(): Unit = {
val fooValue = "bar"
bind(classOf[String])
.annotatedWith(Names.named("foo"))
.toInstance(fooValue)
val userService = new UserService(fooValue) //It should be instantiated by Guice somehow
bind(classOf[AdapterRef])
.annotatedWith(Names.named("userService"))
.toInstance(new AdapterRef(new AdapterImpl(userService))) //Thats kinda ok
}
}
Can someone point me to the right direction?
Thank you,
Gabor
You can use a Provides method within your module, which lets you remove the binding. This is my best effort at Scala so if the syntax is incorrect let me know.
#Provides() #Singleton() def provideAdapterRef(service: Service): AdapterRef = {
return new AdapterRef(new AdapterImpl(service))
}
Note the use of Singleton to imitate your examples use of toInstance. If you don't need it to always provide the same instance I would recommend removing the scope and letting it create a new one every time.
An alternative solution is to use a Provider. This requires you to keep a modified version of the binding in your module and create an extra class, but it can be a cleaner solution if your Provider is more complex.
//Can inject UserService as well, or provide annotations to configure which
//implementation of Service you get if you have more than one.
class UserServiceProvider #Inject()(service: Service) extends Provider[AdapterRef] {
override def get(): AdapterRef {
return new AdapterRef(new AdapterImpl(service))
}
}
Then you can change your binding in the module to
bind(classOf[AdapterRef])
.annotatedWith(Names.named("userService"))
.toProvider(classOf[UserServiceProvider])
.in(classOf[Singleton])
Here note the use of in(Singleton) to replicate your toInstance behavior.

Exclude particular test subclass in ScalaTest (maven)

I have one superclass with WordSpecLike and several subclasses for each backend.
abstract class A extends TestKit(_system) with WordSpecLike {
"backend" must {
"do something useful" in {
//test useful stuff
}
"print something pretty" in {
//test pretty print
}
}
}
class B extends A {
}
class C extends A {
}
C and B tests different backends but the thing is I need to turn on/off each backend-test separately for integration tests (using exclude groups).
Obviously, I can't use taggedAs.
Using a separate traits like in a bellow example didn't work:
trait backendB { this: Tag =>
override val name = "backendB"
}
class B extends A with backendB {
//...
}
}
Pure java annotation didn't work ether:
#TagAnnotation
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE})
public #interface backendB {
}
So, the question is: Have I any other options to run each backend test under a special group or I have to copy-paste code?
Scala version 2.10
ScalaTest version 2.2.2
Java version 1.8.0_20
Can't use sbt instead of maven, can't bump scala version.
If I understand correctly, you want sometimes to exclude class B and run just class C. Other times exclude class C and run just class B. If that's correct, then normally you would annotate B and C with a respective tag annotation (make using Java). For example, doing this would cause all tests of B to be tagged as backendB:
#backendB
class B extends A {
}
What you didn't show is where the actor system is coming from. One thing about tags is that it only excludes tests, an instance of B will still be created. That means any state it holds onto will be initialized, and that might in your case mean an actor system. This might be what you meant by "didn't work." If so, my usual advice is to make that state lazily initialized. The instance will still be created, but because no tests run, he state will never be accessed, and since it is lazy, will never be initialized.
Since there are a lot of unknowns in this reply, you might do better on scalatest-users, where it is easier to go back and forth.
Ok, my final solution is not so elegant as it could be but it's work at least (still kinda more java-way solution).
Several small changes:
trait A-suite extends WordSpecLike {
val tagToExclude = Tag("here we can write anything")
def createTestBackend: Backend
"backend" must {
"do something useful" taggedAs(tagToExclude) in {
val backend = createTestBackend
//test useful stuff
}
"print something pretty" taggedAs(tagToExclude) in {
val backend = createTestBackend
//test pretty print
}
}
}
And test classes for different backends:
`
class backendA(override val tagToExclude = "backendA") extends A-suite {
override def createTestBackend: Backend = new backendA
}
class backendB(override val tagToExclude = "backendB") extends A-suite {
override def createTestBackend: Backend = new backendB
}
Now exclude groups work properly with maven.

Scala cake pattern for objects with different lifetimes

I tried to use cake pattern in my project and liked it very much, but there is one problem which bothers me.
Cake pattern is easy to use when all your components have the same lifetime. You just define multiple traits-components, extend them by traits-implementation and then combine these implementations within one object, and via self-types all dependencies are automatically resolved.
But suppose you have a component (with its own dependencies) which can be created as a consequence of user action. This component cannot be created at the application startup because there is no data for it yet, but it should have automatic dependency resolution when it is created. An example of such components relationship is main GUI window and its complex subitems (e.g. a tab in notebook pane) which are created on user request. Main window is created on application startup, and some subpane in it is created when user performs some action.
This is easily done in DI frameworks like Guice: if I want multiple instances of some class I just inject a Provider<MyClass>; then I call get() method on that provider, and all dependencies of MyClass are automatically resolved. If MyClass requires some dynamically calculated data, I can use assisted inject extension, but the resulting code still boils down to a provider/factory. Related concept, scopes, also helps.
But I cannot think of a good way to do this using cake pattern. Currently I'm using something like this:
trait ModelContainerComponent { // Globally scoped dependency
def model: Model
}
trait SubpaneViewComponent { // A part of dynamically created cake
...
}
trait SubpaneControllerComponent { // Another part of dynamically created cake
...
}
trait DefaultSubpaneViewComponent { // Implementation
self: SubpaneControllerComponent with ModelContainerComponent =>
...
}
trait DefaultSubpaneControllerComponent { // Implementation
self: SubpaneViewComponent with ModelContainerComponent =>
...
}
trait SubpaneProvider { // A component which aids in dynamic subpane creation
def newSubpane(): Subpane
}
object SubpaneProvider {
type Subpane = SubpaneControllerComponent with SubpaneViewComponent
}
trait DefaultSubpaneProvider { // Provider component implementation
self: ModelContainerComponent =>
def newSubpane() = new DefaultSubpaneControllerComponent with DefaultSubpaneViewController with ModelContainerComponent {
val model = self.model // Pass global dependency to the dynamic cake
}.asInstanceOf[Subpane]
}
Then I mix DefaultSubpaneProvider in my top-level cake and inject SubpaneProvider in all components which need to create subpanes.
The problem in this approach is that I have to manually pass dependencies (model in ModelContainerComponent) down from the top-level cake to the dynamically created cake. This is only a trivial example, but there can be more dependencies, and also there can be more types of dynamically created cakes. They all require manual passing of dependencies; moreover, simple change in some component interface can lead to massive amount of fixes in multiple providers.
Is there a simpler/cleaner way to do this? How is this problem resolved within cake pattern?
Have you considered the following alternatives:
Use inner classes in Scala, as they automatically have access to their parent class member variables.
Restructuring your application in an actor based one, because you will immediately benefit of:
Hierarchy / supervision
Listening for creation / death of components
Proper synchronization when it comes to access mutable state
It will probably be helpful having some more code to provide a better solution, can you share a compiling subset of your code?
Let's say we have a program that has only two components: one contains the business logic of our program and the other one contains the dependency of this program, namely printing functionality.
we have:
trait FooBarInterface {
def printFoo: Unit
def printBar: Unit
}
trait PrinterInterface {
//def color: RGB
def print(s: String): Unit
}
For injecting the fooBar logic, the cake-pattern defines:
trait FooBarComponent {
//The components being used in this component:
self: PrinterComponent =>
//Ways for other components accessing this dependency.
def fooBarComp: FooBarInterface
//The implementation of FooBarInterface
class FooBarImpl extends FooBarInterface {
def printFoo = printComp.print("fOo")
def printBar = printComp.print("BaR")
}
}
Note that this implementation does not leave any field unimplemented and when it comes to mixing all these components together, we would have:
val fooBarComp = new FooBarImpl. For the cases where we only have one implementation, we don't have to leave fooBarComp unimplemented. we can have instead:
trait FooBarComponent {
//The components being used in this component:
self: PrinterComponent =>
//Ways for other components accessing this dependency.
def fooBarComp: new FooBarInterface {
def printFoo = printComp.print("fOo")
def printBar = printComp.print("BaR")
}
}
Not all components are like this. For example Printer, the dependency used for printing foo or bar needs to be configured and you want to be able to print text in different colours. So the dependency might be needed to change dynamically, or set at some point in the program.
trait PrintComponent {
def printComp: PrinterInterface
class PrinterImpl(val color: RGB) extends PrinterInterface {
def print(s:String) = ...
}
}
For a static configuration, when mixing this component, we could for example have, say:
val printComp = PrinterImpl(Blue)
Now, the fields for accessing the dependencies do not have to be simple values. They can be functions that take some of the constructor parameters of the dependency implementation to return an instance of it. For instance, we could have Baz with the interface:
trait BazInterface {
def appendString: String
def printBar(s: String): Unit
}
and a component of the form:
trait BazComponent {
//The components being used in this component:
self: PrinterComponent =>
//Ways for other components accessing this dependency.
def bazComp(appendString: String) : Baz = new BazImpl(appendString)
//The implementation of BazInterface
class BazImpl(val appendString: String) extends BazInterface {
def printBaz = printComp.print("baZ" + appendString)
}
}
Now, if we had the FooBarBaz component, we could define:
trait FooBarBazComponent {
//The components being used in this component:
self: BazComponent with FooBarComponent =>
val baz = bazComp("***")
val fooBar = fooBarComp
//The implementation of BazInterface
class BazImpl(val appendString: String) extends BazInterface {
def PrintFooBarBaz = {
baz.printBaz()
fooBar.printFooBar()
}
}
}
So we have seen how a component can be configured:
statically. (mostly the very low level dependencies)
from inside another component. (usually it's one business layer configuring another business layer, see "DEPENDENCIES THAT NEED USER DATA
" in here)
What differed in these two cases is simply the place where the configuration is taking place. One is for the low level dependencies at the very top level of the program, the other is for an intermediate component being configured inside another component. Question is, where should the configuration for a service like Print take place? The two options we have explored so far are out of the question. The way I see it, the only options we have is adding a Components-Configurer that mixes in all the components to be configured and returns the dependency components by mutating the implementations. Here is a simple version:
trait UICustomiserComponent {
this: PrintComponent =>
private var printCompCache: PrintInterface = ???
def printComp: PrintInterface = printCompCache
}
obviously we can have multiple such configurer components and do not have to have only one.