Spring @Value annotation always evaluating as null?
See my answer here.
I ran into the same symptoms (@Value
-annotated fields being null
) but with a different underlying issue:
import com.google.api.client.util.Value;
Ensure that you are importing the correct @Value
annotation class! Especially with the convenience of IDEs nowadays, this is a VERY easy mistake to make (I am using IntelliJ, and if you auto-import too quickly without reading WHAT you are auto-importing, you might waste a few hours like I did).
The correct import is:
org.springframework.beans.factory.annotation.Value
I had similar issues but was a newbie to Spring. I was trying to load properties into an @Service, and tried to use @Value to retrieve the property value with...
@Autowired
public @Value("#{myProperties['myValue']}") String myValue;
I spend a whole day trying various combinations of annotations, but it always returned null. In the end the answer as always is obvious after the fact.
1) make sure Spring is scanning your class for annotations by including the package hierachy In your servlet.xml (it will scan everything below the base value you insert.
2) Make sure you are NOT 'new'ing the class that you just told Spring to look at. Instead, you use @Autowire in the @Controller class.
Everything in Spring is a Singleton, and what was happening was Spring loaded the values into its Singleton, then I had 'new'ed another instance of the class which did not contain the newly loaded values so it was always null.
Instead in the @Controller use...
@Autowired
private MyService service;
Debugging... One thing I did to find this was to extend my Service as follows...
@Service
public class MyService implements InitializingBean
Then put in debug statements in...
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
LOGGER.debug("property myValue:" + myValue);
}
Here I could see the value being set on initialization, and later when I printed it in a method it was null, so this was a good clue for me that it was not the same instance.
Another clue to this error was that Tomcat complained of Timeouts trying to read from the Socket with Unable to parse HTTPheader... This was because Spring had created an instance of the service and so had I, so my one was doing the real work, and Spring was timing out on its instance.
If instances of Config
are being instantiated manually via new
, then Spring isn't getting involved, and so the annotations will be ignored.
If you can't change your code to make Spring instantiate the bean (maybe using a prototype
-scoped bean), then the other option is to use Spring's load-time classloader weaving functionality (see docs). This is some low-level AOP which allows you to instantiate objects as you normally would, but Spring will pass them through the application context to get them wired up, configured, initialized, etc.
It doesn't work on all platforms, though, so read the above documentation link to see if it'll work for you.