Say you have a spring component like below with dependencies constructor injected (builder is a singleton):
#Component
public class houseBuilder{
private WindowMaker windowMaker;
private DoorMaker doorMaker;
private RoofMaker roofMaker;
#Autowired
public houseBuilder(WindowsMaker wm, DoorMaker dm, RoofMaker rm){
this.windowMaker = wm;
this.doorMaker = dm;
this.roofMaker = rm;
}
//Other methods omitted for brevity
}
However the house requires something called "foundation" that should be passed in through the constructor or set before making the house begins and foundation is not a spring bean. I'd like to use the builder pattern as well so I could do something like the below but I am unsure how to do this with spring. Something like the below is what I am after except I want to use spring:
Foundation foundation = new Foundation();
HouseBuilder hb = new HouseBuilder(foundation)
.windowMaker(args)
.doorMaker(args)
.roofMaker(args);
Any advice is appreciated.
Spring Dependency injection and fluent builders are not really designed to work together.
The first is a way to set dependencies of an object in an "automatic" way via annotation or configuration.
While the second is a way for clients of the class to specify how the object should be build.
Automatic dependency injection and declarative construction are so really two distinct ways to create objects.
As a side note, Spring dependency injection with constructor brings two major fluent builder benefits : no more cumbersome constructor to call as the injection is performed by the container and the object may be immutable as no setter are required.
Related
I have the following problem:
I have a superclass called Entity, which provides some basic methods every entity has. For this, it needs some services to run such as AbstractPotionService. This dependency is needed by none of its subclasses directly, but I would have to pass it every time I instantiate a sub-type of an Entity such as MobileEntity
public class Entity {
private AbstractPotionService potionService;
protected EntityTypeConverter converter;
public Entity(EntityTypeConverter converter, AbstractPotionService potionService) {
this.converter = converter;
this.potionService = potionService;
}
public void addEffect(EffectType effectType, int durationInSeconds) {
potionservice.applyEffectTo(this, effectType, durationInSeconds);
}
...
}
public class MobileEntity extends Entity {
public MobileEntity(EntityTypeConverter converter, AbstractPotionService potionService){
super(converter, potionService);
}
public attack(MobileEntity victim) {
...
}
...
}
This feels kind of wrong as it is a lot of tedious work and makes the project less maintainable when I want to extend the Entity class. My first thought was to use a Singleton here and get an instance of the services in the constructor of Entity directly (via static methods), but wouldn't that create a God dependency?
I also read about composition but I couldn't find an appropriate example on how to apply it in my case. Does anyone have an idea?
Chapter 4 (page 106) of Dependency Injection Principles, Practices, and Patterns (DIPP&P) (that I coauthored) states:
Entities that contain behavior besides their usual set of data members would easily get a wide range of methods, each requiring their own dependencies. Although you might be tempted to use Constructor Injection to inject such dependencies, that leads to a situation where each such entity needs to be created with all of its dependencies, even though only a few may be necessary for a given use case. This complicates testing the logic of an entity, because all dependencies need to be supplied to the constructor, even though a test might only be interested in a few dependencies. Method Injection [...] offers a better alternative.
The case of the required constructor dependencies is even exaggerated in your case, because every sub type needs to have those dependencies in their own constructor and need to pass them through to the Entity base type. If you add a new dependency to Entity it will cause all derived entities to change (and with them, all their tests), which can cause maintainability issues.
So instead, DIPP&P advises the use of Method Injection instead which, in your case, would look like this:
public class Entity {
public Entity() { } // <-- No more Constructor Injection
public void addEffect(
EffectType effectType,
int durationInSeconds,
AbstractPotionService potionService) // <-- Method Injection
{
potionservice.applyEffectTo(this, effectType, durationInSeconds);
}
...
}
With Method Injection, the method requiring the dependency is supplied with that dependency. And while the method uses the dependency, unlike Constructor Injection, it doesn't store the dependency.
This has the effect that its now the consumer's responsibility to supply the correct dependency. In most cases it would mean that the dependency is injected into the consumer using Constructor Injection.
Thank you for the answers/comments. With #Steven's answer and #Andy's comment, I was able to build a solution. As already pointed out in Steven's answer, using pure method injection every time an effect is added might not be the cleanest solution as you would have to request the dependency in any class using this method.
So I took the idea of using a factory class to create my entities. After it has checked the entity type and injected the specific data, some method injections are done at the end:
public Entity createEntity(EntityType type) {
Entity output = new Entity();
if (type == EntityType.MONSTER) {
output = new MonsterEntity(someMonsterDependency);
} else if (type == EntityType.PLAYER) {
output = new PlayerEntity(somePlayerDependencies);
} if (type == EntityType.FRIENDLY_NPC) {
...
}
output.setPotionService(potionService);
output.injectOtherDependencies...
return output;
}
So now, I only have to load the service implementations on startup, inject them into my EntityFactory, and can then create entities. If someone still has a better solution, feel free to post it.
In a simple Spring boot application I have my component like this:
#Data
#Component
public class GenericHandler {
private String path;
private HandlerType type;
}
And my properties might look like this:
my.handlers[0].path='/vol1/abc'
my.handlers[0].type='Single'
my.handlers[1].path='/vol1/dora'
my.handlers[1].type='MultiSequence'
I tried decorating with the GenericHandler-class with #ConfigurationProperties(prefix="my.handlers") and getting a list of all component instances in a service using
#Autowired
private List<GenericHandler> handlers;
But that created just one component, ignoring the property values at all.
How can I get one component instance per my.handlers property-entry?
You need a wrapper class
#Component
#ConfigurationProperties(prefix="my.handlers")
#Data
public class GenericHandlerWrapper {
private List<GenericHandler> handlers;
...
}
Then you can autowire the GenericHandlerWrapper
Update
As #zoolway pointed out in the comments, for the properties in the question to work as it is, #ConfigurationProperties(prefix="my.handlers") should be changed to #ConfigurationProperties(prefix="my")
That's not possible. What can be done is this:
#Data
#Component
public class GenericHandler {
private List<String> path;
private List<HandlerType> type;
}
I dealt with a similar issue in a different manner. I created a factory and an interface. The factory would hold different implementations of that interface In your case, GenericHandler would be your interface. Then you write any number of implementations of your interface and each implementation is declared as a Component. So, Spring will instantiate it as bean upon a startup (you might use #Lazy(false) to force the instantiation at startup) using some infrastructure that I wrote each bean of that interface will self-insert itself into its factory. Then at any part of your code in any bean, you can use the factory to access concrete implementation (base on your property "type" for example). The beauty is that you don't need to inject all the implementations in your bean at the time of writing but access needed implementation dynamically at run-time. I found this to be a useful pattern and created an infrastructure that does most of the work for you and published it as an Open Source library called MgntUtils. The detailed description of the idea (including reference to the library) could be found here. Also detailed explanation with examples of how to use it can be found in library Javadoc here. The library is available (with source code and Javadoc) as Maven artifacts and on the Github. Also a general article about the MgntUtils library could be found here
Suppose I have a class that looks like this:
public class MyClass {
#Inject
public MyClass(#Foo("whatever") Bar dependency) {
// ...
}
}
And I wanted to have some custom logic that can see we're injecting an object of type Bar with an annotation of type #Foo("whatever") and construct a corresponding Bar object...something like a Guice Provider, but that gets more context information about the injection site. Does Guice let me do something like that?
What you're describing isn't possible through normal Guice: Providers are intended to be zero-argument pure functions and there's no way to plumb the injection site information into them as you would a flexible callback function.
You can approximate what you want, though, two different ways:
If you know every single possible value of #Foo's parameter, you can make your #Foo a binding annotation and bind it by providing a Annotation-compatible equals and hashCode. This provides the most intuitive experience: You can do anything with your #Foo you can do with any other type, such as using #Foo in constructors or injecting #Foo("value") Provider<Bar> barProvider.
#Override public void configure() {
for (String value : PREDEFINED_VALUES) {
bind(Bar.class)
.annotatedWith(new FooImpl(value))
.toProvider(new BarProvider(value));
}
}
If you want #Foo to work for arbitrary parameters, you'll need to extend Guice with custom injections. This won't work for constructor injection or alongside any other #Inject annotations, but it will allow you to inspect types after Guice injection is finished to augment them as you see fit (e.g. detecting and reacting to #Foo annotations on fields).
See the example in the Guice docs for more information there.
Internally, Guice's core is effectively a Map<Key, Provider>, where a Key represents a pair of a possibly-parameterized type and an optional binding annotation. The former binding annotation trick works because Guice can map your injection request to a Provider all on its own, where the latter skips Guice's map so you can inspect/construct/inject instances all on your own.
If you're willing to skip the annotation part of your solution, you could inject a BarProvider or BarFactory that exposes a forFoo(String) method, which would give you consistent injection without knowing all your String values ahead of time. This would allow you to use assisted injection or AutoFactory to generate your factory (if you want to generate one instance per call), or let you write a straightforward factory yourself for added flexibility.
public class MyClass {
private final Bar dependency;
#Inject
public MyClass(BarProvider barProvider) {
dependency = barProvider.forFoo("whatever");
// ...
}
}
Background
I want to realize dependency injection in Python using injector (or pinject) which itself heavily borrows from guice. While an answer using Python/injector would be ideal, I'm also very happy about solutions/approaches that feature Java/guice.
Intention
I'll give you a quick summary of what I want to achieve: I have a component that depends on a list/sequence of other components that all implement the same interface. Those components have dependencies themselves which may vary amongst the different implementations. The concrete types (implementations) shall be configurable by the user (or using any mechanism of the DI framework).
Example
Yes, I've read Modules should be fast and side-effect free which suggests not to use an XML file for configuration, however as I don't know how to realize this within the framework I'll use one to demonstrate the dependency structure:
<RentingAgency>
<Vehicles>
<Car>
<DieselEngine></DieselEngine>
</Car>
<Car>
<PetrolEngine></PetrolEngine>
</Car>
<Bike></Bike>
</Vehicles>
</RentingAgency>
In this example there is a renting agency (the component that depends on a list of others) that rents out all kinds of vehicles (the interface). The specific vehicles in their fleet (in this case two cars and one bike) should be configurable but fixed during runtime. The vehicles themselves can have dependencies and they can be different depending on the type of vehicle (a car depends on a motor, a bike has no dependencies in this case).
Question
How can I construct the renting agency within the DI framework so that all required vehicles are injected and their dependencies resolved properly?
Maybe helpful
Multibinder
I've read about Multibinder (injector seems to have something similar with Binder.multibind) which allows for injecting a collection of objects that implement the same interface. However:
Can it be used to create multiple instances of the same class that need to receive different dependencies (the two cars (Class Car) in the example have different motors: Interface Motor, Class DieselEngine, class PetrolEngine)?
Using providers to accomplish that task seems to me like giving up the benefits of dependency injection: I could manually create the Car instances in the provider, passing the required Motor as argument, however because this pattern repeats further down the chain (i.e. multiple Motors of the same type are used and they also have dependencies) I want to use dependency injection for generating those objects too. But to manually use them in the provider it seems to me like I have to obtain the instances directly from the injector. The docs mention that injecting the injector is a rare case and from my understanding of dependency injection, the great benefit is that one can request a component and all dependencies are resolved by the framework automatically.
Also because I actually use Python I'm not sure if this approach is appropriate (as Python is quite flexible when it comes to dynamic code generation). Also injector.Injector.get.__doc__ mentions
Although this method is part of :class:Injector's public interface
it's meant to be used in limited set of circumstances.
For example, to create some kind of root object (application object)
of your application (note that only one get call is needed,
inside the Application class and any of its dependencies
:func:inject can and should be used):
Dependency injection frameworks are primarily for dependencies and because your Vehicles object is configured by the user at runtime it is more like application data than a dependency. It probably can't just be injected in one shot using MultiBinding unless you know it at compile time.
Likewise, you are right in saying that it would not be a good approach to construct your set of components by iterating and calling injector.getInstance(Bike.class) etc. For one, this is not good for testing.
However, because the objects contained in Vehicles have their own dependencies you can leverage the DI framework in the creation of your Vehicles object. Remember, also, that although you cannot bind a Provider to an implementation, when you bind a key Guice will inject that provider for you.
For the simple example in the post, consider creating a VehicleFactory. Inside, you could have something like the following:
public class VehicleModule implements Module {
#Override
public void configure(Binder binder) {
binder.bind(DieselEngine.class).toProvider(DieselEngineProvider.class);
binder.bind(PetrolEngine.class).toProvider(PetrolEngineProvider.class);
binder.bind(Bike.class).toProvider(BikeProvider.class);
}
}
public class DieselEngineProvider implements Provider<DieselEngine> {
#Inject
public DieselEngineProvider() {
//if DieselEngine has any dependencies, they can be injected in the constructor
//stored in a field in the class and used in the below get() method
}
#Override
public DieselEngine get() {
return new DieselEngine();
}
}
public class VehicleFactory {
private final CarFactory carFactory;
private final Provider<Bike> bikeProvider;
#Inject
public VehicleFactory(CarFactory carFactory, Provider<Bike> bikeProvider) {
this.carFactory = carFactory;
this.bikeProvider = bikeProvider;
}
public Bike createBike() {
return bikeProvider.get();
}
public Car createDieselCar() {
return carFactory.createDieselCar();
}
public Car createPetrolCar() {
return carFactory.createPetrolCar();
}
}
public class CarFactory {
private final Provider<DieselEngine> dieselEngineProvider;
private final Provider<PetrolEngine> petrolEngineProvider;
#Inject
public CarFactory(Provider<DieselEngine> dieselEngineProvider, Provider<PetrolEngine> petrolEngineProvider) {
this.dieselEngineProvider = dieselEngineProvider;
this.petrolEngineProvider = petrolEngineProvider;
}
public Car createDieselCar() {
return new Car(dieselEngineProvider.get());
}
public Car createPetrolCar() {
return new Car(petrolEngineProvider.get());
}
}
As you mention, there is the danger of this becoming 'factories all the way down', but Guice can help you here.
If the production of Engine becomes more complicated and involves a combination of different parameters, you can use tools like AssistedInject to auto-create the factories for you.
If you end up with a set of common dependencies and uncommon dependencies that you want to use to create different 'flavours' of an object then you have what is known as the robot legs problem then Guice can solve it using private modules.
Do note the following caveat from the Dagger 2 user guide:
Note: Injecting Provider has the possibility of creating confusing
code, and may be a design smell of mis-scoped or mis-structured
objects in your graph. Often you will want to use a factory or a
Lazy or re-organize the lifetimes and structure of your code to be
able to just inject a T.
If you follow this advice, it would seem that you would have to carefully balance using providers and using factories to create your Vehicle.
With Google Guice or Gin I can specify parameter with are not controlled by the dependency injection framework:
class SomeEditor {
#Inject
public SomeEditor(SomeClassA a, #Assisted("stage") SomeClassB b) {
}
}
The assisted parameter stage is specified at the time an instance of SomeEditor is created.
The instance of SomeClassA is taken from the object graph and the instance of SomeClassB is taken from the caller at runtime.
Is there a similar way of doing this in Dagger?
UPDATE: As of Dagger 2.31 from January 2021, Dagger now natively supports assisted injection, which is recommended over the Square and Auto options. (Those other options still work, but may require extra setup compared to the native option.)
class SomeEditor {
#AssistedInject public SomeEditor(
SomeClassA a, #Assisted SomeClassB b) {
// ...
}
}
#AssistedFactory interface SomeEditorFactory {
SomeEditor create(SomeClassB b);
}
(original answer)
Because factories are a separate type of boilerplate to optimize away (see mailing list discussion here), Dagger leaves it to a sister project, AutoFactory. This provides the "assisted injection" functionality Guice offers via FactoryModuleBuilder, but with some extra benefits:
You can keep using AutoFactory with Guice or Dagger or any other JSR-330 dependency injection framework, so you can keep using AutoFactory even if you switch between them.
Because AutoFactory generates code, you don't need to write an interface to represent the constructor: AutoFactory will write a brand new type for you to compile against. (You can also specify an interface to implement, if you'd prefer, or if you're migrating from Guice.)
Because all the type inspection happens at compile-time, it produces plain old Java, which doesn't have any slowness due to reflection and which works well with debuggers and optimizers. This makes the Auto library particularly useful for Android development.
Example, pulled from AutoFactory's README, which will produce a SomeClassFactory with providedDepA in an #Inject-annotated constructor and depB in a create method:
#AutoFactory
final class SomeClass {
private final String providedDepA;
private final String depB;
SomeClass(#Provided #AQualifier String providedDepA, String depB) {
this.providedDepA = providedDepA;
this.depB = depB;
}
// …
}
Just like #xsveda, I also wrote an answer about this in this other question, which I'll also reproduce here.
Today, for assisted injection with Dagger you probably want to use AssistedInject. I wrote about it in this blogpost, but I'll add a full example here to make things easier.
First thing you need are the dependencies:
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0'
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0'
Then here's how it can look like:
class ImageDownloader #AssistedInject constructor(
private val httpClient: HttpClient,
private val executorService: ExecutorService,
#Assisted private val imageUrl: URL,
#Assisted private val callback: ImageCallback
) {
#AssistedInject.Factory
interface Factory {
fun create(imageUrl: URL, callback: ImageCallback): ImageDownloader
}
}
First thing is that instead of annotating the constructor with #Inject, we annotate it with #AssistedInject. Then we annotate the parameters that will have to go through the factory, which is the opposite of what AutoFactory expects. Finally, we need an inner factory interface annotated with #AssistedInject.Factory that has a single method that receives the assisted parameters and returns the instance we're interested in.
Unfortunately, we still have an extra step here:
#AssistedModule
#Module(includes = [AssistedInject_AssistedInjectModule::class])
interface AssistedInjectModule
We don't necessarily need a dedicated module for it, even though that's a valid option. But we can also have those annotations in another module that is already installed in the component. The nice thing here is that we only need to do it once, and after that any factory will automatically become part of the graph.
With that, you can basically inject the factory and ask for your object as you'd normally do.
Yes, please check this Square project: square/AssistedInject
Currently it is not in 1.0 yet for purpose. They wait until Dagger will introduce a public API for registering those generated Module classes automatically - see this issue. With that you won't have to reference them in your Dagger code as in this example from README:
#AssistedModule
#Module(includes = AssistedInject_PresenterModule.class)
abstract class PresenterModule {}