Static Fields + Autowiring in Spring - spring

Can we autowire static fields in spring controller ?
eg:
#Autowired
public static JNDIEMailSender jNDIEmailSender;

No, I don't think that will work. You can add a setter method, annotate it with #Autowired and set the static field in the setter.
#Autowired
void setJNDIEmailSender(JNDIEmailSender jndiEmailSender) {
ClassName.jNDIEmailSender = jndiEmailSender
}

Spring doesnt autowire static fields

Related

what is the purpose of spring boot autowired annotation on a constructor?

what is the purpose of #Autowired annotation on a constructor? What is the difference between non-annotated and annotated constructor? Thank you.
Autowiring feature enables you to inject the object dependency implicitly.
Without autowiring you have to initiate the object like:
public class SomeOperation() {
private CarService carService;
public SomeOperation() {
carService = new CarServiceImpl();
}
}
But if you annotate with #Autowired you don't have to initiate the object. The framework will bring the class which implements the carService and initiate your object with it.
public class SomeOperation() {
private CarService carService;
#Autowired
public SomeOperation(CarService carService) {
this.carService = carService;
}
}
What is the difference between non-annotated and annotated
constructor?
In Spring 3 or below, the annotation on the constructor is mandatory to make Spring consider the constructor as the way to instantiate the bean and inject dependencies provided in parameters.
Spring 4 and above versions don't require the annotation to do that.
You just need to declare the constructor with any parameter to achieve that.
So in recent Spring versions, don't clutter the code with the annotation :
public Foo(Bar bar){
this.bar = bar;
}

Can I change one annotation to another annotation in Spring?

Can someone explain can we replace annotation to another annotation in Spring?
I searched about it so I only found that #Autowired and #Inject we can replace but still its having a difference.
I think we can't replace annotation with other annotation?
Is it correct?
I think you won't have a problem by replacing one another. As #Inject was introduced in JSR-330.
For example you have the component:
#Component
public class ArbitraryDependency {
private final String label = "Arbitrary Dependency";
public String toString() {
return label;
}
}
injecting the bean like:
#Inject
ArbitraryDependency arbitraryDependency;
will have no difference by injecting it like:
#Autowired
ArbitraryDependency arbitraryDependency;
More about key differences

Field injection works but constructor injection returns NullPointerException

While looking at an existing Spring application, I stumbled upon a class with field injection, which we all know isn't recommended for various reasons. I have then decided to refactor it to make use of a more appropriate approach: constructor based DI.
Before refactoring
#Component
public class MaintenanceModeInterceptor implements HandlerInterceptor {
private static final String MAINTENANCE_MODE_VIEW = "common/maintenanceMode";
#Autowired
private ApplicationObject applicationObject;
public MaintenanceModeInterceptor() {
// Required by Spring
}
...
}
After refactoring
#Component
public class MaintenanceModeInterceptor implements HandlerInterceptor {
private static final String MAINTENANCE_MODE_VIEW = "common/maintenanceMode";
private ApplicationObject applicationObject;
public MaintenanceModeInterceptor() {
// Required by Spring
}
#Autowired
public MaintenanceModeInterceptor(ApplicationObject applicationObject) {
this.applicationObject = applicationObject;
}
...
}
Maybe it is related to the fact that a default constructor is present. However, if I remove it, I end up having this exception:
Caused by: java.lang.NoSuchMethodError: my.application.web.interceptor.MaintenanceModeInterceptor: method <init>()V not found
So my understanding is that Spring requires a default constructor for interceptors.
Is there any way to achieve construtor based DI in this scenario?
Thank you.
I think you should remove the non #Autowired constructor and do perform a clean build on your project.

Spring autowired using constructor

I want to create a object using few properties, how can I achieve that using Spring #Autowired ?
E.g.-
public class Person{
private String fname;
private String lname;
public Person(String fname, String lname){
this.fname = fname;
this.lname = lname;
}
}
How can I create a object using #Autowired of Person class by passing these properties at runtime.
Atul
Do you really want to autowire the variables? Or do you want to set them explictly when getting the bean?
In the later case, you can simply call ApplicationContext.getBean(Class<T> clz, Object ... arguments), in your case...
Person person = context.getBean(Person.class, "Henry", "Miller");
Obviously that doesn't have anything to do with #Autowired. Or do you want to autowire some strings into it? In that case you normally would use the #Value annotation. Autowired is used to inject beans, which you can do via field injection...
#Autowired
private MyService service;
...via constructor injection...
#Autowired
public Person(MyService service) { ... }
...via setter injection...
#Autowired
public void setMyService(MyService service) {..}
But normally you only autowire beans that way. Strings are no beans, so you have to use #Value...
#Autowired
public Person(#Value('${app.some.property}') final String firstName) {...}
This would inject the configured property of app.some.property into that bean. Of course, this only is good if you actually want to inject something from the application context. If you want to create the Person dynamically, you can use the method above.

Does a Spring annotated controller necessarily need a default constructor

I have a spring controller that uses annotations. I gave this controller a constructor that takes two arguments. I want both ways of initializing the controller: constructor injection and setter injection.
#Controller("viewQuestionController")
#RequestMapping("/public/viewQuestions")
public class ViewQuestionController
{
#Resource(name="questionService")
private QuestionService questionService;
/*public ViewQuestionController()
{
int i=0;
i++;
}
*/
public ViewQuestionController(#Qualifier("questionService") QuestionService questionService)
{
this.questionService = questionService;
}
#Resource(name="questionService")
public void setQuestionService(QuestionService questionService)
{
this.questionService = questionService;
}
}
When I uncomment the default constructor, the controller is initiated correctly. However, if I don't, I get a BeanInstantiationException, No default constructor found; nested exception is java.lang.NoSuchMethodException.
So, is my configuration for the annotated constructor wrong or does a completely annotated controller in spring always need a default constructor?
If you want to configure constructor injection via annotations, you need to put the corresponding annotation on the constructor. I'm not sure how it can be done with #Resource, but #Autowired and #Inject support it:
#Autowired
public ViewQuestionController(#Qualifier("questionService") QuestionService questionService)
or
#Inject
public ViewQuestionController(#Named("questionService") QuestionService questionService)
I think Controller beans need a default constructor as they are initialized by the framework but there is no way to tell the framework hot to provide the dependency.
On second thought why not you autowire your question service and Spring will take care of it.
The following code should be good
#Controller("viewQuestionController")
#RequestMapping("/public/viewQuestions")
public class ViewQuestionController
{
#Autowired
private QuestionService questionService;
//Not providing any constructor would also be fine
public ViewQuestionController(){}
questionService will be initialized properly by Spring

Resources