My data model consists of three objects, let's call them A, B and C. A has a one-to-many relationship to B, and B to C. They are only modeled as interfaces.
To get concrete versions of them, I have interfaces AProvider, BProvider and CProvider which provide create, retrieve, and delete operations.
I am now doing an implementation using Spring-JPA and Hibernate by the means of spring-boot-starter-data-jpa. For this, I have three #Entitys InternalA, InternalB and InternalC which do not implement the A, B and C interfaces, but are used as transfer objects only. To access them, I use the autogenerated repositories from Spring (see CrudRepository).
For creating the "real" objects, I have implementations of the XProvider interfaces which inject their necessary dependencies. This structure is the following (I prefer javax.inject style injection):
#Component
public class AProviderImpl implements AProvider {
#Inject
private InternalARepository _aRepository;
// implementation
}
#Component
public class BProviderImpl implements BProvider {
#Inject
private InternalBRepository _bRepository;
#Inject
private AProvider _aProvider;
// implementation
}
#Component
public class CProviderImpl implements CProvider {
#Inject
private InternalCRepository _cRepository;
#Inject
private BProvider _bProvider;
// implementation
}
I figure out that this should work, and the AutowireCapableBeanFactory correctly figures out what to instantiate first. But this only works up to the BProviderImpl, e.g., when removing the CProviderImpl. As soon as CProviderImpl exists, initialization fails with No qualifying bean of type [com.somewhere.BProvider] found.
It makes no difference if I use #Autowired instead of #Inject.
I stepped through the initialization process with a debugger and the CProvider is indeed initialized first, i.e., the bean factory does not correctly figure out that it needs the BProvider which in turn needs the AProvider first.
My current workaround is using #DependsOn like this:
#Component("myAProvider")
public class AProviderImpl implements AProvider { ... }
#Component("myBProvider")
#DependsOn("myAProvider")
public class BProviderImpl implements BProvider { ... }
#Component("myCProvider")
#DependsOn("myBProvider")
public class CProviderImpl implements CProvider { ... }
This works, but I read elsewhere that this is a code smell and should be avoided because it introduces implicit dependencies. Currently, this is all local to one module, so it is no problem there, but later my model will grow and I will have model elements and providers spread over multiple modules, so I cannot use #DependsOn until kingdom come.
Is there a better way to tackle this?
You can use the #Order annotation, this will enable to prioritize Bean loading and doesn't pollute your loading hierarchy as with #DependsOn. With this you can certainly modularize your design later without a problem. Lowest order value has highest priority.
#Component("myAProvider")
#Order(1)
public class AProviderImpl implements AProvider { ... }
#Component("myBProvider")
#Order(2)
public class BProviderImpl implements BProvider { ... }
#Component("myCProvider")
#Order(3)
public class CProviderImpl implements CProvider { ... }
I found another workaround: Lazy initialization. Since initialization of my XProviders are not long-running, I just added the #Lazy annotation. That way, Spring creates uninitialized instances and adds them to the registry, and when at a later point an injected dependency is accessed, it is initialized.
I don't know if this is the best solution, but I think it is better than using #DependsOn and it should be working over module boundaries.
Related
I'm fiddling around with Dependency Injection in Java using simple JUnit tests and javax.inject-Annotations.
I have the following scenario: There's a "top-level"-class (SomeObject) with two dependencies (SomeObjDepA and SomeObjDepB). SomeObjDepB has a dependency to SomeObjDepA too. And this should be the same instance of SomeObjDepA as in the SomeObject-instance. But SomeObjDepA must not be a Singleton, since different SomeObj-instances shall have different instances of SomeObjDepA (and SomeObjDepB). This is where I am stuck.
To be more clear, here's some basic code without any configuration:
public class SomeObject {
#Inject
private SomeObjDepA someObjDepA;
#Inject
private SomeObjDepB someObjDepB;
public SomeObjDepA getSomeObjDepA() {
return someObjDepA;
}
public SomeObjDepB getSomeObjDepB() {
return someObjDepB;
}
}
public class SomeObjDepA {
}
public class SomeObjDepB {
#Inject
private SomeObjDepA someObjDepA;
public SomeObjDepA getSomeObjDepA() {
return someObjDepA;
}
}
public class DependencyInjectionTest {
#Inject
private Provider<SomeObject> someObjProvider;
#Test
public void instancesTest() {
final SomeObject someObjInst1 = this.someObjProvider.get();
final SomeObject someObjInst2 = this.someObjProvider.get();
Assertions.assertNotEquals(someObjInst1, someObjInst2);
Assertions.assertNotEquals(someObjInst1.getSomeObjDepA(), someObjInst2.getSomeObjDepA());
Assertions.assertNotEquals(someObjInst1.getSomeObjDepB(), someObjInst2.getSomeObjDepB());
Assertions.assertEquals(someObjInst1.getSomeObjDepA(), someObjInst1.getSomeObjDepB().getSomeObjDepA());
Assertions.assertEquals(someObjInst2.getSomeObjDepA(), someObjInst2.getSomeObjDepB().getSomeObjDepA());
}
}
Question: How to setup dependency injection to build up a scenario like this? I am looking for a annotation or Java based configuration (if possible)
I am currently using CDI 2.0 (Weld 3.1.5), and JUnit 5 for testing. I prefer a solution using CDI, but any other solution using Spring, Guice, etc. would be nice to.
Many thanks in advance
Depending on what you're looking for, you want to make use of scopes and/or qualifiers.
You can think of a scope as a lifespan. If you don't specify a scope (you don't anywhere above), then the default scope is "create a new one whenever one is called for", which is known as dependent scope. (This is because the thing being injected's lifespan is dependent on the thing that is housing it.)
As #Glains points out above, #ApplicationScoped is one way of indicating that a bean should be in "application scope", which is basically singleton scope with extra goodies. So you can put that on any class that meets the requirements to indicate that its lifespan should be that of the application as a whole.
Next, you talk about distinguishing between two otherwise indistinguishable occurrences of a given object, both of which might be singletons (SomeObjDepA). Qualifiers let you do this.
Let's say that you have a producer method that makes a "yellow" SomeObjDepA and another one that makes a "red" SomeObjDepA. To do this in CDI, you'll need qualifier annotations that express the "red" and "yellow" bits. Then apply them at the site of production. For example:
#ApplicationScoped // producer methods need to be "housed" in a bean
public class Host {
#Produces
#Red // you define this annotation following the spec's rules for qualifier annotations
#ApplicationScoped // ...or whatever scope is called for
public SomeDepA produceRedDepA() {
return new SomeDepA();
}
#Produces
#Yellow // you define this annotation following the spec's rules for qualifier annotations
#ApplicationScoped // ...or whatever scope is called for
public SomeDepA produceYellowDepA() {
return new SomeDepA();
}
}
Here we have two producer methods that will be called by the container appropriately and will "satisfy" relevant injection points elsewhere. For example, in SomeObject, you might have:
#Inject
#Red
private SomeDepA red;
#Inject
#Yellow
private SomeDepA yellow;
I have to make me #Component #Lazy as it is used rarely and creates circular dependency problem
I have to make it Optional<T> because feature it represents can be disabled on startup (#ConditionalOnProperty) so it might not be available at runtime
Problem:
When I use Optional<T> as injection point, bean is initialized eagerly.
So the questions:
Is it possible to make it work like that?
Can I replace Optional<T> with Provider<T>? will it simply return null if feature is disabled or it will throw exception?
Can it be replaced with ObjectProvider<T>?
I would like to stick to #Resource or #Inject annotation so #Autowired(required=false) will be last resort for me.
There is no code to share here actually (as it would be class and field declarations as those are relevant onl IMHO)
Since you do not belive me the code is worthless here, let me share :)
#Comonent
#Lazy
public class MyType{
}
injection point
#Lazy
#Autowired
private Optional<MyType> myType;
usage
MyType instance=myType.getOrThrow(()->throw something)
Iv tested Optional and debugger hits MyType upon application startup. It is skipped when I use plain field, provider or object provider.
In situations like this I do not wire the Component directly, but lazily. There are different options:
Go through the ApplicationContext and retrieve MyType when you need it. You would only retrieve it, when you know it is enabled:
#Autowire
private ApplicationContext context;
...
MyType instance = context.getBean(MyType.class);
Provider or Factory approach, where you have an autowired service which provides you an instance of MyType. This service is also only called when the feature is enabled.
#Autowire
private MyTypeFactory factory;
...
MyType instance = factory.getMyType();
Using the Provider would require you to define a bean in your configuration, so it might be easier to just have a POJO service on which you can slap #Service, that does the same.
Let me present an alternative Point of View. I think that using Optional dependency for this is not justified.
The class that has an Autowired MyType probably counts on this dependency (notwithstanding the fact that usage of Optional for data fields if a kind of bad practice).
The reason for Laziness of the component also seems to be more "hack" than intention (circular dependency is never a good thing).
So, if we'll pretend that this class makes something "Optionally available", one way is to provide an additional no-op implementation for this MyType problematic bean:
interface MyType {
void doSomeHeavyStuff();
}
public class MyTypeRegularImpl() implements MyType {
public void doSomeHeavyStuff() {
....work..work..work..
}
}
public class NoOpMyType implements MyType {
public void doSomeHeavyStuff() {
// do nothing here
}
}
Now the trick is to provide two mutually exclusive conditions and make sure that only one bean out of these two loads (otherwise it will produce an ambiguity in beans and probably fail during the application startup).
So the class that uses MyType won't need Optional at all.
Now regarding the Laziness.
In general, Lazy beans only get ini
Lazy Bean can still be used since the bean will be initialized during the first call in a class that has that lazy dependency.
For no-op beans it won't matter at all.
Suppose I'm building a car and I have several Brake beans with different implementations
class Car {
#Inject
Car(#BrakeType(value="abs")Brake frontBrake, #BrakeType(value="nonabs")Brake rearBrake) { }
}
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
public #interface BrakeType {
String value();
}
interface Brake {}
#BrakeType(value="abs")
class AbsBrakeImpl implements Brake {
#Inject AbsBrakeImpl() {}
}
#BrakeType(value="nonabs")
class BrakeImpl implements Brake {
#Inject BrakeImpl() {}
}
why does my CarModule have to define #Provides for the specific Brake types? Shouldn't the custom annotation type #BrakeType be enough to determine which impl to inject? Or would that require using reflection, which dagger2 does not use?
#Module
public class CarModule {
#Provides #BrakeType("abs")
public Brake absBrake() {
return new AbsBrakeImpl();
}
#Provides #BrakeType("nonabs")
public Brake nonabsBrake() {
return new BrakeImpl();
}
}
Dagger doesn't look at qualifier annotations on classes, only on #Provides or #Binds methods. So the #BrakeType(value="abs") annotations on your classes don't have any effect.
A more canonical way of writing your code is:
class AbsBrakeImpl implements Brake {
#Inject AbsBrakeImpl() {}
}
class BrakeImpl implements Brake {
#Inject BrakeImpl() {}
}
#Module
abstract class CarModule {
#Binds #BrakeType("abs")
abstract Brake absBrake(AbsBrakeImpl impl);
#Binds #BrakeType("nonabs")
abstract Brake nonabsBrake(BrakeImpl impl);
}
Note that since you have #Inject on the constructors of your implementations, you can simply use Dagger's #Bind to bind the implementations directly to the appropriately qualified interface.
Reflection is probably not a big issue here because it would happen at compile time.
I did not look through the source code, but dagger is but an annotation processor—it registers to be called whenever a set of given annotations is used. While the qualifier alone would probably be enough to find out what you intended, I can think of the following reasons why this could not be the best solution.
javax.inject.Qualifier is part of a bigger API, and might also be used by other libraries in different context. So you might not want dagger to generate code for a method, just because it is annotated with a qualifier.
Another reason could be that since there is the possibility to create custom qualifiers, dagger would have to check every annotation on every method in every module and then in turn determine whether that annotation itself is annotated with #Qualifier to see if the method is of some interest to it. This is rather an unnecessary overhead.
There might be more reasons, but those 2 listed here seem enough to just make users of dagger use some sort of contract: #Provides.
Annotations don't affect the performance of the code, and having an addtional annotation won't do any harm, so there is more to gain than to lose by handling it the way they do.
For the record, you can use your own qualifier annotations (as BrakeType), or just use #Named from Dagger.
Using this last one, your code will look something like:
#Inject #Named("abs") Brake frontBrake;
#Inject #Named("nonabs") Brake rearBrake;
And on your module:
#Provides #Named("abs") static Brake provideAbsBrake() {
return new AbsBrakeImpl();
}
#Provides #Named("nonabs") static Brake provideNonAbsBrake() {
return new BrakeImpl();
}
Remember to use Dagger name conventions (like provide prefix) to get most of it. And on your modules try to use all #Provides methods static, doing so the resultant implementation does not need to instantiate it.
In short, Provides and Qualifiers work together so you need both.
Source: Dagger users guide.
#Inject constructor means provide a type that class itself, in your case, which mean you provide the AbsBrakeImpl type and BrakeImpl type, so when you try to inject with Brake, dagger can not found the provider.
Qualifier in #Inject constructor is not work, because class type is unique, we don't need to add a qualifier to.
So, in your case, or you have to use CarModule to tell Dagger explicitly, or change your constructor with
class Car {
#Inject
Car(AbsBrakeImpl frontBrake, BrakeImpl rearBrake) { }
}
I am using spring dependency injection,where i can inject object dependency through some external xml file.
My question is :
Is it fine to use spring DI without using interfaces?
Because with DI,we want to achieve one thing :
If a class is being replaced by some other class having same methods but different definitions,then we don't need to make any change in code where this class is being referenced.
This is fine if i am using interface as interface can point any class which is implementing this interface but if i am directly injecting class object through DI then there is no meaning of DI because in this case if class get replaced,i have to change my code also where it is being referenced.
Please let me correct if something is wrong.
Let's say i have
Class Datasource{
String url;
String user;
String database;
}
Now i am using it without DI as
Class Abc{
Datasource datasource = new Datasource();
}
what's the problem in this and what are the benefits i can get if i use DI.
Is getting singleton object only goal of DI?
Dependency Injection isn't about interfaces or classes or enums or... It is about Inversion of Control.
Imagine the following class.
public class PersonService {
private PersonRepository repository = new PersonRepository();
}
Apparently there is nothing wrong with this. However what if PersonRepository needs other dependencies, what if it takes another complex object as construct argument. Suddenly the PersonService is burdend with the logic on how to construct an object and all of its dependencies. Whereas it only wants to use the object.
public class PersonService {
private PersonRepository repository;
public PersonService() {
InitialContext ctx = new InitialContext();
repository = ctx.lookup("java:comp/env/repositories/person");
}
}
The code above is tied to JNDI, how are you going to test it (easily) of course you can construct your own Mock JNDI service and pre configure that with a constructed or mocked repository but that is quite cumbersome.
public class PersonService {
private final PersonRepository repository;
public PersonService(PersonRepository repository) {
this.repository=repository;
}
}
The above makes basically everything possible, there is no burder on the PersonService on how to construct the PersonRepository it is just handed one, where it comes from it doesn't matter. Is it the actual class or a (class-based) proxy, is doesn't care.
Hence dependency injection, you want to hand the PersonRepository to use to the PersonService it shouldn't matter to it where it comes from, how it is constructed or if it is a proxy to an actual object. It just needs a PersonRepository.
Suppose you have one interface
public interface A {
public void doSomething();
}
and two implementation classes
#Component(value="aImpl1")
public class AImpl1 implements A {
}
#Component(value="aImpl2")
public class AImpl2 implements A{
}
And finally a class that will use an "A" implementation:
#Component
public class MyClass {
#Autowire
A a;
}
Now if I want to inject AImpl1 I add the #Qualifier("aImpl1") while if I want to inject AImpl2 I add #Qualifier("aImpl2")
The question is: Is it possible to instruct spring somehow to look up all implementations of "A" in this case AImpl1 and AImpl2 and use some application specific conventions to choose the most appropriate implementation? for example in this case my convention could be use the implementation with the greatest suffix (i.e. AImpl2)?
EDIT: the class MyClass should not be aware at all about the implementation lookup logic, it should just find its property "a" set with an object of AImpl2.
You can inject all implentations as List:
#Autowired
List<A> as;
or as Map with bean name as key:
#Autowired
Map<String, A> as;
and then choose proper implementation manually (perhaps, in a setter method):
#Autowired
public void setAs(Map<String, A> as) {
this.a = ...;
}
Assuming you already have hundreds of interfaces and implementations (as you said in a comment), and you do not want to refactor all the code... then is a tricky problem... and this is a tricky solution:
You could create a custom BeanDefinitionRegistryPostProcessor and implement either the method postProcessBeanDefinitionRegistry or postProcessBeanFactory.
This way you have access to all bean definitions before they are instantiated and injected. Do your logic to find which is the preferred implementation for each one of your interfaces, and then, set that one as primary.
#Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry) throws BeansException {
// this method can be used to set a primary bean, although
// beans defined in a #Configuration class will not be avalable here.
}
#Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
// here, all beans are available including those defined by #configuration, #component, xml, etc.
// do some magic to somehow find which is the preferred bean name for each interface
// you have access to all bean-definition names with: beanFactory.getBeanDefinitionNames()
String beanName = "aImpl2"; // let's say is this one
// get the definition for that bean and set it as primary
beanFactory.getBeanDefinition(beanName).setPrimary(true)
}
}
The hard part is to find the bean name, it depends of the specifics of your application. I guess that having a consistent naming convention will help.
Update:
It seems that both methods in the interface BeanDefinitionRegistryPostProcessor can be used for this purpose. Having in mind that in the postProcessBeanDefinitionRegistry phase, beans configured through #configuration classes are not yet available, as noted in the comments below.
On the other hand they are indeed available in postProcessBeanFactory.
If you have a Configuration class you could use a method in that to make the decision of which implementation of A to return. Then the autowired will inject the appropriate instance for that class.
#Configuration
public class ApplicationConfiguration {
#Bean
A getA() {
// instantiate the implementation of A that you would like to have injected
// or you could use reflection to find the correct class from the classpath.
// return the instance
}
}
This assumes you always want to use the same instance everywhere you are injecting A. If not, then you could have different #Bean annotated methods with names to get different versions.
You can try to use Spring Profiles.