#Autowired on methods - spring

I have a code containing the below snippet running:
class MyNewReader implements ItemReader<MyBean>, ItemStream{
#Resource
SingleItemPeekableItemReader<MyBean> myBeanPeekableReader;
#Resource
public void setDelegate(MyJdbcReader myJdbcReader){
myBeanPeekableReader.setDelegate(myJdbcReader);
}
I don't have any property delegate in my class MyNewReader.
But still the annotation #Resource is working on setDelegate method and is working fine.
Can someone tell that is it not necessary to have a property in the class to let annotation on setter method(having that property in its name) work...Is this not working as setter injection?

myBeanPeekableReader.setDelegate(myJdbcReader) gets its jdbcReader injected as parameter to the method you have annotated.
Yes, setter injection.

Related

resilience4j annotations not working on chlid class

I am using resilience4j with SpringBoot. I see that the resilience4j annotations work only if they are placed in the class which throws the exception. If the class is extended by another class & the parent class has the annotation then the retries do not work.
Resilience4j Config
resilience4j.retry:
instances:
service:
maxRetryAttempts: 5
waitDuration: 1000
retryException:
- com.common.exception.RetriableException
Parent Class
#Retry(name = "service")
#Component
public class httpClient extends client{
// This method is invoked from outside
public HttpResponse<T> getResponse(
String url, Class<T> responseType) {
return super.getResponse(url, requestEntity, responseType);
}
}
Child Class
#Retry(name = "service") // Without this line, the retries don't work, even though it is present in the parent class
#Component
public class client{
public HttpResponse<T> getResponse(
String url, Class<T> responseType) {
//Impl which throws RetriableException
}
}
Is this the expected behaviour ? Can you let me know if I am missing something
I never used Resilience4j before, but what I can tell you about Java annotations in general is:
An overridden method in a subclass never inherits annotations from the original parent class method.
In a class implementing an interface an implementing method never inherits annotations from the corresponding interface method.
A classes implementing an interface never inherits annotations from the interface itself.
An interface extending another interface also never inherits any type or method level annotations.
By default not even a subclass inherits annotations from its parent class.
There is a single exception to this "annotations are never inherited" rule: A type level annotation (something like #Foo class Base, can also be abstract) can be inherited by a subclass (something like class Sub extends Base) if and only if the annotation class itself carries the meta annotation #Inherited.
Having said that and looking at the #Retry annotation, you will notice that there is no #Inherited annotation there, so it also cannot work in your case.
If there is another way (e.g. via reflection) to get this done in Resilience4j, I do not know because, as I said, I never used it before.

Not able to inject values in a field

#Component
#PropertySources({ #PropertySource("classpath:mail.properties") })
public class A implements B {
#Value("${mail.team.address}")
private String teamAddress;
// has getter and setters .not shown for brevity.
Now when i call the class i get the value of teamAddress as NULL .But in the property file mail.team.address has some value.
My property file is present under src/main/resource folder
Making a call
A a = new A ();
a.someMethodinClassA();
You can not create instance of class by yourself when you want Spring to resolve #Value annotation.
See documentation:
Note that actual processing of the #Value annotation is performed by a BeanPostProcessor which in turn means that you cannot use #Value within BeanPostProcessor or BeanFactoryPostProcessor types. Please consult the javadoc for the AutowiredAnnotationBeanPostProcessor class (which, by default, checks for the presence of this annotation).
Simple solution for you: just annotate class with any #Component annotation and let Spring to create an instance of your class.
You can't create (with a "new" keywoard) for spring bean. If you do it like this, spring doesn't participate in the object creation and configuration, which means that there is no autowiring, the bean is not in Application Context, etc. And of course, #Value annotation won't be processed among other things
The better way is to inject the class A to the code that you used in your example:
A a = new A ();
a.someMethodinClassA();
Show become:
#Component
public class SomeClass {
private final A a;
public SomeClass(A a) {
this.a = a;
}
public void foo() {
a.someMethodinClassA();
}
}
You should read some basics around spring dependency injection. The class that you have autowired with #Component is scanned via component scanning and its object is created by spring container for you.
that is the reason you should not create the object yourself using new keyword.
wherever in your new class you want to use your class A object you can autowire it as below:
#Component
public class TestC{
private A a; // this object will be injected by spring for you
}

Creating service instance when needed

I have a Controller class that maps request urls. I have an instance of class annotated with #Service. For example;
#Controller
class MainController{
#Autowired
private UserService userService;
...
}
As I know, this instance is created automatically by Spring container, because I added #Autowired but I use this instance when condition is met in the method. If the condition is not met, I do not need this instance. Thus, this declaration is overhead. I mean, I may not use it even though it is created.
I would like to create the object when it is needed. How can I do this in the code? I probably will not use #Autowired because I need a dynamic object creation. What else do I need to do?
You can use Setter injection. The #Autowired annotation can be used on setter methods. In the below example, when the annotation is used on the setter method, the setter will be called with the instance of FooFormatter when FooService is created:
public class FooService {
private FooFormatter fooFormatter;
#Autowired
public void setFooFormatter(FooFormatter fooFormatter) {
this.fooFormatter = fooFormatter;
}
}
In this way you can inject you service when you call the setter method explicitly :) Hope this will help you :)
LATER EDIT
I've just found a way that might resolve your problem, it's named #Lazy.
You can use #Lazy annotation like this:
On your service class, put #Lazy annotation before the public Class XXX definition;
When declaring/autowiring a Service type in your controller context, put #Lazy annotation with #Autowired annotation on top of the declared attribute like
#Lazy
#Autowired
private FooFormatter fooFormatter;
for more info, check the link: http://www.baeldung.com/spring-lazy-annotation
You need to use #Lazy annotation with a combination of Bean Life Cycle annotations. But one thing you need to consider is the performance of your controller if you will re-create your service each time you need it, then you degradates the performance.

Spring Bean: Is autowired attribute initialised before constructor?

#Component
public class BeanA {
...
}
#Component
public class BeanB {
#Autowired
BeanA beanA;
public BeanB() {
// Use beanA
beanA.method();
}
}
Can we assume BeanA is created and initialized before BeanB constructor is called? (I know we can pass BeanA as constructor arg to BeanB, this is more of curiosity question to understand spring/java initialisation sequence)
Take a look at http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-autowired-annotation-qualifiers
Setting properties on bean would happen after it is constructed by means of a constructor or a factory method. By default, beans are autowired by name and values are set using setter methods. So in your case the field will be set after constructor.
This is because
#Autowired
BeanA beanA;
really means that you want to autowire the field of that class instance. beanA in your case is not really a constructor arg.
(Well, here is a quick question, are the constructor argument names retained after compilation? Is there any debug flag related to this?)
As this example from spring documentation says, you can apply #Autowired to constructors and fields:
public class MovieRecommender {
#Autowired
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
#Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
Let me know if you need any more help with this.
Oh, and just a minor point. You seem to be calling method() on beanA in your constructor. It is not a good idea, if the method can be overridden. I know it is just an example you jotted down here, but just a word of caution.
No, the autowiring is handled by a BeanPostProcessor that will run after the constructor of the newly created bean. If, for some reason, you need to autowire some fields and then run some initialisation you can use a #PostConstruct annotated method. It will be called after all dependencies are injected. In most cases #Autowiring a constructor (and, perhaps, making the object immutable) is still the best option.
No, spring is very clever, but not that magical ... Internally, spring :
creates an instance
set instances properties
stores eventually the bean in relevant scope (exept for prototype beans) and/or gives it to caller
But the creation uses a constructor and at the time it is called properties have not been set.
In short, you can access #Autowired in your method marked with #PostConstruct.

How to inject object into setter that declared final in parent class with using just annotations?

How to inject object by using just annotations in parent class by using getter/setter method which declared like public final someSetter()?
As far I understand if that method would declared just public
I can do like this...
#Override
#Autowired
public void setSomeObject(SomeClass someObject) {...}
But method declared like final and I cannot override it.
Anyone have some ideas?
If you can't modify the parent, you may be out of luck if you can only use annotations.
You could create a different setter, annotate it, and call the parent setter, though.

Resources