Kotlin : Optional Dependency Injection Using Spring - spring

What is the kotlin alternative for
#Autowired(required=false)
private DependencyC dependencyC;
and
private Optional<HelloService> optionalHelloService;
public HelloController(Optional<HelloService> helloService) {
this.optionalHelloService = helloService;
}

You should make that property nullable then:
class HelloController(
#Autowired(required = false) val helloService: HelloService?
)

The accepted answer is outdated. Spring uses the type information to infer whether a bean is optional. See
https://docs.spring.io/spring/docs/current/spring-framework-reference/languages.html#kotlin-annotations, specifically
In a similar fashion, Spring bean injection with #Autowired, #Bean, or #Inject uses this information to determine if a bean is required or not.
Because #Autowired is optional for constructor parameters, the shortest Kotlin alternative is
class HelloController(private val optionalHelloService: HelloService?)

Related

Dependency injection against a private property

But what about this:
#Service
public class DatabaseAccountService implements AccountService {
private final RiskAssessor riskAssessor;
public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
// ...
}
This example is from the documentation:
https://docs.spring.io/spring-boot/docs/2.0.x/reference/html/using-boot-spring-beans-and-dependency-injection.html
Maybe I have not understood even the question. Could you comment?
In Spring there are at least 2 different ways for dependency injection: constructor injection and field injection. (leaving setter injection aside for now)
Constructor injection is the recommended way to do dependency injection:
#Service
public class DatabaseAccountService {
private final RiskAssessor riskAssessor;
#Autowired // annotation is not required in recent Spring versions
public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
}
The referenced Spring documentation also shows an example for constructor injection, simply because it's the recommended way.
Field injection is used to inject dependencies directly into fields/properties as mentioned in the question.
#Service
public class DatabaseAccountService {
#Autowired // don't do this at home or work
private RiskAssessor riskAssessor;
public DatabaseAccountService() {
// RiskAssessor does not appear as constructor parameter
}
}
With the question in video "Can you use dependency injection against a (private) property?" they want to point exactly to field injection maybe to show the possibilities of Spring.
However, they also say that this is bad practice. The blog post Why field injection is evil explains why this is bad practice.

Difference between #Autowired and #Required with setter injection in Spring

I know a lot had been written about #Autowired and #Required annotations.
But I have a very basic question as below -
What is the difference between the below two mechanism of setter injection.
I haven't yet got a complete satisafactory answer for this.
The reason is :
1)#Autowired without any extra information like - #Autowired(required=false) is same as #Required
2)What are we gaining from #Required additionally ?
3)Why #Required is recommend over #Autowired on setter injection ?
class MyClass {
private MyService myService;
#Autowired
public void setMyService(MyService val) {
this.myService = val;
}
}
class MyClass {
private MyService myService;
#Required
public void setMyService(MyService val) {
this.myService = val;
}
}
#Autowired is not the same as #Required.
The #Required-Annotation is specialized for telling Spring that this property has to be injected by the information given in the XML-configuration-file (eager) and not through annotations. And that doesn't matter when you use the #Autowire-Annotation.
The #Autowire-Annotation (as in your code-example), tells the ApplicationContext (a.k.a the Spring-IoC-Containter) to inject the desired dependency. (No matter how, if its by using annotations or the XML-File of the ApplicationContext).
The #Required-Annotation, tells the ApplicationContext that this property has to be mentioned in the XML-file (The XML-File of the ApplicationContext), but the Annotation on its own doesn't tell to inject the dependency. So it is used to check if it is in the XML-configuration file, but not to inject a dependency. The injection is done because the property is mentioned in the XML-file.
So in the end it tells that the injection has to be done because of a configuration in the XML-File. But again: The annotation doesn't tell that the dependency has to be injected, but that it has to be mentioned in the XML-File - which then lets the dependency be injected.
With mentioning the property in a XML-File I mean such a configuration for instance:
<bean id="MyClass" class="com.myclasses.common.MyClass">
<property name="someProperty" value="ValueThatHasToBeInjected" />
</bean>
So why should I use it over the #Autowired-Annotation?
You should use it when the dependency has to be injected due to the informatoin given in the XML-configuration file.
Can you give me an example?
Well, there is already a very good example on this website. where this is also explained.
1) You can think of #Required as a check that the property has been eagerly initialised. In other words it requires that it's been injected via configuration (xml or annotation). If annotation is used then you'll see it alongside #Autowired. If the Bean injected does not exist the application fails to startup with a runtime exception.
2) Nothing more nothing less. #Required is very specific in what it's meant to be: a) only applicable on methods, b) requires the bean or else application runtime error on startup. Again, you need dependency injection either via annotation or xml.
3) Most likely you want to know at startup if a Bean is failed to be injected and for that reason you can have #Required along with #Autowired for expressiveness. Functionality-wise you don't need it if you have #Autowired.
Extra notes:
#Autowired has more functionality on the other side of the coin that is - when you want to achieve laziness. So on a setter method:
as you mentioned #Autowired(required = false)
Can also be paired with #Lazy
you can have #Autowired (without required = false) on a setter method whose param is Java 8's Optional achieving the same effect.

Spring Boot Constructor based Dependency Injection

I'm a beginner with Spring Boot and Dependency Injection and I can't get my head around Constructor based Dependency Injection in Spring Boot. I have class called ParameterDate that look like this:
public class ParameterDate {
private Date parameterDateUnadjusted;
private Date parameterDateAdjusted;
private Date parameterDateAdded;
private Date parameterDateChanged;
}
I have another class where I want to use ParameterDate. Normally I would do Field based Injection with
#Autowired
ParameterDate parameterDate;
And where ever needed I just use parameterDate.
How would I do this with Constructor based Injection?
public MyClazzRequiringParameterDate(ParameterDate parameterDate){
this.parameterDate = parameterDate;
}
Since Boot 1.4 #Autowired has been optional on constructors if you have one constructor Spring will try to autowire it. You can just tag the constructor with #Autowired if you want to be explicit about it.
Generally speaking you should favour Constructor > Setter > Field injection. Injecting directly to the field misses the point of DI, it also means your tests are reliant on Spring to inject dependencies into rather than just being able to pass mocks or stubs directly to it. Jurgan Holler has stated that he would remove field injection if at all possible.
#Component
public class ParameterDate {
private Date parameterDate;
#Autowired
public ParameterDate(Date parameterDate){
this.parameterDate = parameterDate;
}
}
Above is an example of constructor injection.
Note that you can use #Autowired annotation also on property's setter method, and since there is no difference between setter method (except of course it's purpose, logic it contains) and any other method, you can use #Autowired on just about any method of the class.
Since autowiring and component scanning go hand in hand, you should mark your class with #Component annotation. This tells Spring that a bean should be created for this class.

Autowiring doubts in spring?

After going thru autowiring concept
i have got some questions. These are:-
If i need to autowire below class byType or byName , is it mandatory to have setStudent() method in class College?
public class College {
private Student student1;
private String registration1;
}
<bean id="student1" class="Student"/> - in case of byname it will look into id attribute and in case of bytype it will look for class attribute in above
Stetement. Right? If incase it finds two bean dean tags for the same type it will throw fatal error in case of bytype. Correct?
autodetect Scenario chooses constructor or byType through introspection of the bean class. If a default constructor is found, the byType mode
will be applied.
My question here if default constructor is not found and constructor with argument is found then autowire by constructor
will be applied. Correct?
Do we need to specify #Autowired somewhere in College to apply the autowiring. As i can see this in this example
but nothing is specified here
1), 4) There are two separate ways of autowiring in Spring: XML-based and annotaion-based.
XML-based autowiring is activated from XML config, as described here. In the end, it will call setter method, so setStudent() method is required here.
Annonation-based autowiring, on the other hand, is performed via reflection magic. It attempts to fill everything you mark with #Autowired annotation. In fact, it can set private field with no accessors, as in
public class Foo {
#Autowired private Thingy thing; // No getThing or setThing methods
private void doStuff() {
// thing is usable here
}
}
For #Autowired annotaion to work, you will need to define corresponding bean post-processor; it is done by adding the following line to xml config:
<context:annotation-config/>
Note, that these two autowiring methods are independant, and it is possible(but not recommended) to use them simultaneously. In that case, xml autowiring will override annotations.
2) In general, autowiring will fail, if it cannot find one and only one candidate for injection. So, in your case, it will fail with exception upon container creation. There are some fallback quirks, but in general it works reliably.
3) Yes, documentaion says so.
About byName and byType autowiring. While byName autowiring simply tries to match bean name (can be specified with id attribute), byType is a bit more complex than class attribute lookup. It searches beans by type, and it will match interfaces. Example:
public interface SomeService {
void doStuff();
}
public class SomeServiceImpl implements SomeService {
#Override public void doStuff() {
// Implementation
};
}
public class ServiceUser {
#Autowired
private SomeService someService; // SomeServiceImpl instance goes here
}
P.S. You are referencing two different versions of Spring in your question, 2.5 and 3.0. Autowiring behavior is same in both.
In Addition if you are using #Autwired annotation you need to mark the classes as candidates for autowiring. It should be done by using one of these annotations:
#Repository
#Service
#Component
#Controller
and of cause you can configure it in different scopes:
#Scope("prototype")
#Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
Hope it makes it more clear.

#Autowire default mode

How does Spring #Autowire beans: byName or byType? If one is not possible, is a second trial done using another mode?
If annotated with #Autowired it will inject the bean with the matching type (An exception will be thrown if there are more than one of a type). To specify a name use the #Qualifier annotation.
Springs #Autowire wires by type. For wiring by name you can also use
#Resource(name = "id")
The default mode of the #Autowired is byType.
Autowired annotation on variable or setters method is equivalent to xml attribute autowire="byType"
XML attribute autowire is defaut as no
"no":
The traditional Spring default. No automagical wiring. Bean references
must be defined in the XML file via the <ref/> element (or "ref"
attribute). We recommend this in most cases as it makes documentation
more explicit.
These are no, byName, byType, constructor, and autodetect. The default mode is no i.e. by default autowiring is turned off in traditional XML based configuration.
Using #Autowired annotation-
1) #Autowired on properties:
When #Autowired is used on properties, it is equivalent to autowiring by byType in configuration file.
2) #Autowired on property setters:
When #Autowired is used on setters, it is also equivalent to autowiring by byType in configuration file.
3) #Autowired on constructors:
When #Autowired is used on bean’s constructor, it is also equivalent to autowiring by constructor in configuration file.
Use #Qualifier for conflict in dependency resolution
As we learned that if we are using autowiring in byType mode and dependencies are looked for property class types. If no such type is found, an error is thrown. But, what if there are two or more beans for same class type.
In this case spring will not be able to choose correct bean to inject into property, and you will need to help the container using qualifiers.
To resolve a specific bean using qualifier, we need to use #Qualifier annotation along with #Autowired annotation and pass the bean name in annotation parameter.
I just checked out the source code of the spring-beans-5.2.7.RELEASE.jar. It contains class DefaultListableBeanFactory with the method
#Nullable
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
As we can see it tries to autowire by type. If no success it tries to autowire by name in this line
matchesBeanName(candidateName, descriptor.getDependencyName()))

Resources