#Autowired in Spring MVC #Controller does not work on a private field - spring

I have a Spring MVC Controller in a very XML-slimmed application, we use a lot of annotations and as little config as possible. The Controller is working and it also has a number of resource values injected. But I've experienced a really strange behavior with this controller; annotated private fields referencing other components will not be injected.
This will not work.
#Controller
public class EntranceUnitController {
#Value("${remote.baseUrl}")
private String baseUrl = "http://localhost";
#Value("${remote.port}")
private String pushPort = "8080";
#Autowired
private HttpClientFactory httpClientFactory;
...
It seems that the httpClientFactory isn't there yet when the private fields are set, if I set a break point to inspect the value there is of course null set when the controller is created.
BUT, if I make a setter for the component and annotate the set-method instead of the private field the controller works as expected.
#Controller
public class EntranceUnitController {
#Value("${remote.baseUrl}")
private String baseUrl = "http://localhost";
#Value("${remote.port}")
private String pushPort = "8080";
private HttpClientFactory httpClientFactory;
#Autowired
public void setHttpClientFactory(HttpClientFactory httpClientFactory) {
this.httpClientFactory = httpClientFactory;
}
...
To me this is really annoying. Isn't the auto wiring injection for annotated values happening at the same time regardless injection point? I.e. why does it matter that the object is injected with a setter? I thought that private field injections are directly followed by constructs and setters, me start to think I'm wrong in that case...

Seems like your dependencies are in fact injected, you are just putting a breakpoint in the wrong moment (too early) and the dependencies aren't injected yet, despite class being already created.
Remember that, unless you are using constructor injection, the first place where you can use injected dependencies is #PostConstruct method:
#Controller
public class EntranceUnitController {
#Autowired
private HttpClientFactory httpClientFactory;
#PostConstruct
public void init() {
httpClientFactory //should not be null
}

Related

#Autowire on field vs #Autowired on Construcor

I am developing a SpringBoot application. Can anyone help me understand what is the difference between the below piece of code. I am working on a restful service and I saw constructor being autowired. I can understand its Constructor Injection. Usually I autowire a field. So I am unable to understand the difference between two.
Scenario 1:
#RestController
public class SomeServiceController {
#Autowired
private ASerice aService;
#Autowired
private BService bService;
}
Scenario 2:
#RestController
public class SomeServiceController {
private ASerice aService;
private BService bService;
#Autowired
public SomeServiceController (AService aService, BService bService)
{
this.aService = aService;
this.bService = bService;
}
}
The difference is that with the constructor injection, the class SomeServiceController can only be created if with this constructor.
So you could even instantiate the class to test it.
With field injection, this is not possible. To instantiate the class for a test, you must use reflection to set the two private services.
It's highly recommended to use constructor expression.
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-collaborators

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.

#Autowired in static classes

This is an Spring MVC project with Hibernate.
I'm, trying to make a Logger class that, is responsible for inputting logs into database.
Other classes just call proper methods with some attributes and this class should do all magic.
By nature it should be a class with static methods, but that causes problems with autowiring dao object.
public class StatisticLogger {
#Autowired
static Dao dao;
public static void AddLoginEvent(LogStatisticBean user){
//TODO code it god damn it
}
public static void AddDocumentEvent(LogStatisticBean user, Document document, DocumentActionFlags actionPerformed){
//TODO code it god damn it
}
public static void addErrorLog(Exception e, String page, HashMap<String, Object> parameters){
ExceptionLogBean elb=new ExceptionLogBean();
elb.setStuntDescription(e);
elb.setSourcePage(page);
elb.setParameters(parameters);
if(dao!=null){ //BUT DAO IS NULL
dao.saveOrUpdateEntity(elb);
}
}
How to make it right? What should I do not to make dao object null?
I know that I could pass it as a method parameter, but that isn't very good.
I'm guessing that autowired can't work on static objects, because they are created to early to autowiring mechanism isn't created yet.
You can't #Autowired a static field. But there is a tricky skill to deal with this:
#Component
public class StatisticLogger {
private static Dao dao;
#Autowired
private Dao dao0;
#PostConstruct
private void initStaticDao () {
dao = this.dao0;
}
}
In one word, #Autowired a instance field, and assign the value to the static filed when your object is constructed. BTW, the StatisticLogger object must be managed by Spring as well.
Classical autowiring probably won't work, because a static class is not a Bean and hence can't be managed by Spring. There are ways around this, for example by using the factory-method aproach in XML, or by loading the beans from a Spring context in a static initializer block, but what I'd suggest is to change your design:
Don't use static methods, use services that you inject where you need them. If you use Spring, you might as well use it correctly. Dependency Injection is an Object Oriented technique, and it only makes sense if you actually embrace OOP.
I know this is an old question but just wanted to share what I did,
the solution by #Weibo Li is ok but the problem it raises Sonar Critical alert about assigning non static variable to a static variable
the way i resolved it with no sonar alerts is the following
I change the StatisticLogger to singlton class (no longer static)
like this
public class StatisticLogger {
private static StatisticLogger instance = null;
private Dao dao;
public static StatisticLogger getInstance() {
if (instance == null) {
instance = new StatisticLogger();
}
return instance;
}
protected StatisticLogger() {
}
public void setDao(Dao dao) {
this.dao = dao;
}
public void AddLoginEvent(LogStatisticBean user){
//TODO code it god damn it
}
public void AddDocumentEvent(LogStatisticBean user, Document document, DocumentActionFlags actionPerformed){
//TODO code it god damn it
}
public void addErrorLog(Exception e, String page, HashMap<String, Object> parameters){
ExceptionLogBean elb=new ExceptionLogBean();
elb.setStuntDescription(e);
elb.setSourcePage(page);
elb.setParameters(parameters);
if(dao!=null){
dao.saveOrUpdateEntity(elb);
}
}
I created a service(or Component) that autowire the service that i want and set it in the singlton class
This is safe since in spring it will initialize all the managed beans before doing anything else and that mean the PostConstruct method below is always called before anything can access the StatisticLogger
something like this
#Component
public class DaoSetterService {
#Autowired
private Dao dao0;
#PostConstruct
private void setDaoValue () {
StatisticLogger.getInstance().setDao(dao0);
}
}
Instead of using StatisticLogger as static class I just use it as StatisticLogger.getInstance() and i can access all the methods inside it
You can pass the DAO to StatisticLogger from where you call it.
public static void AddLoginEvent(LogStatisticBean user, DAO dao){
dao.callMethod();
}
It might be too late to put an answer to this question, especially when a question is already having an accepted answer. But it might help others in case they face the same issue.
inside the StatisticLogger class create an instance of the Dao service.
public static Dao daoService = new Dao();
then, auto-wire the service instance through the constructor of the StatisticLogger class.
#Autowired
public functionName(Dao daoService0) {
this.daoService = daoService0;
}
//use this service as usual in static class
daoService.fun();
I think this is the simplest solution for the problem.

How to re-inject a transient #ManagedProperty at deserializing?

I'm using Spring and JSF 2 to create a web application.
The business objects are kept in the Spring container, and I inject them in the Managed Beans using the #ManagedProperty, like this:
#ManagedBean
#ViewScoped
public class SomeMB implements Serializable {
private static final long serialVersionUID = 1L;
#Getter #Setter
#ManagedProperty("#{someService}")
private SomeService someService;
// ...
The problem is, I keep getting a NotSerializableException for a class from Spring (ServiceLocatorFactoryBean) that it's being used by the SomeService bean.
If I make it transient, how could I do the re-injection of it after deserializing?
Or, what would be other ways to solve this problem?
I've been reading several other questions similar here, but couldn't find any that dealt exactly with this problem.
Instead of injecting the Spring beans via EL in a #ManagedProperty annotation (executed on the ManagedBean initialization), obtain the beans evaluating the EL at runtime.
With this approach, this is what the JSF beans should look like:
#ManagedBean
#ViewScoped
public class SomeMB implements Serializable {
private static final long serialVersionUID = 1L;
private static SomeService someService() {
return SpringJSFUtil.getBean("someService");
}
// ...
And the utility class SpringJSFUtil.java that gets the bean via EL:
import javax.faces.context.FacesContext;
public class SpringJSFUtil {
public static <T> T getBean(String beanName) {
if (beanName == null) {
return null;
}
return getValue("#{" + beanName + "}");
}
#SuppressWarnings("unchecked")
private static <T> T getValue(String expression) {
FacesContext context = FacesContext.getCurrentInstance();
return (T) context.getApplication().evaluateExpressionGet(context,
expression, Object.class);
}
}
This eliminates the Spring bean property (at the cost of doing a few more EL evaluations), thus avoiding all the serialization issues of having the property in first place.
The same approach, using OmniFaces:
In my actual code, I use the evaluateExpressionGet(String expression) method of an utility class available from OmniFaces. So, for those of you who use it too, this is what my code really look like:
import static org.omnifaces.util.Faces.evaluateExpressionGet;
#ManagedBean
#ViewScoped
public class SomeMB implements Serializable {
private static final long serialVersionUID = 1L;
private static SomeService someService() {
return evaluateExpressionGet("#{someService}");
}
// ...
Notice that here the method gets the full EL ("#{expression}"), not just the Spring bean name (or you would get a ClassCastException).
Try #Scope(value = BeanDefinition.SCOPE_SINGLETON, proxyMode = ScopedProxyMode.INTERFACES) on your Spring #Service. This should inject a serializable proxy object into your managed bean that will relocate the service upon access after deserialization.
For those to follow - I had a similar problem with an injected ResourceBundle. Using part of BalusC's answer, I did the following:
#ManagedProperty(value="#{myBundle}")
private transient ResourceBundle myBundle;
private Object readResolve() {
myBundle = FacesContext.getCurrentInstance().getApplication()
.evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{myBundle}",
ResourceBundle.class);
return this;
}
This way, the EL is evaluated only when the managed bean is deserialized.
Well keep this in mind from the Spring manual ( link to spring):
Constructor-based or setter-based DI?
Since you can mix both, Constructor- and Setter-based DI, it is a good rule of thumb to use constructor arguments for mandatory dependencies and setters for optional dependencies. Note that the use of a #Required annotation on a setter can be used to make setters required dependencies.
The Spring team generally advocates setter injection, because large numbers of constructor arguments can get unwieldy, especially when properties are optional. Setter methods also make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is a compelling use case.
Some purists favor constructor-based injection. Supplying all object dependencies means that the object is always returned to client (calling) code in a totally initialized state. The disadvantage is that the object becomes less amenable to reconfiguration and re-injection.
Use the DI that makes the most sense for a particular class. Sometimes, when dealing with third-party classes to which you do not have the source, the choice is made for you. A legacy class may not expose any setter methods, and so constructor injection is the only available DI.

Resources