Is it possible to use @Value
inside a class that extends another class?
Below are the relevant code snippets. In the Lo_Controller
class it works perfectly, but in the Lo_DisplayHandler
always returns null
. The only reason I can think of is because it depends on another class, which is not annotated with @Component
. If that is the cause, what is the recommended option to read a value from properties file similar to @Value
?
Just to test it out, I changed from @Component
to @Controller
in Lo_DisplayHandler
to see, if they are somehow related to each other, however it returns null
as well.
This works:
package com.ma.common.controller;
imports ...
@Controller
@RequestMapping("/log")
public class Lo_Controller {
@Value("${log.display.lastpage}")
private String lastPageUrl;
...
This always returns null
:
package com.ma.log.handler;
imports ...
@Component
public class Lo_DisplayHandler extends Lo_Handler {
public Lo_DisplayHandler() {
super();
}
@Value("${log.display.lastpage}")
private String lastPageUrl;
...
mvc-dispatcher-servlet.xml
<context:component-scan base-package="com.ma.common.controller, com.ma.log.handler" />
<context:property-placeholder location="classpath:restServices.properties"/>
<mvc:annotation-driven />
<mvc:resources mapping="/**" location="/" />
@Component
public class Lo_DisplayHandler extends Lo_Handler {
@Value("${log.display.lastpage}")
private String lastPageUrl;
public void anyOtherMethod(){
String _a = lastPageUrl; //FAIL - always null
}
@PostConstruct
public void initIt() throws Exception {
String _a = lastPageUrl; //OK - when the application is deployed and started for the first time
}
@PreDestroy
public void cleanUp() throws Exception {
String _a = lastPageUrl; //OK - when the application is stopped
}
web.xml
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Three possible problems here:
First, I disencourage to extends classes as Spring works better autowiring dependencies. But it should work Second, you have to focus on the lifecycle of a bean. The property will be set after the instanciation. @PostConstruct to validate the content. Third, The visibility in hierarchical context of the property holder is not straight forward. So if you define @value in the root applicationContext, it will not set by your dispatcherServlet context. To test it, please inject the dependency of the bean defined at root level, you will see that your @Value will be take in account.
The lastPageUrl property will be accessible from a bean within the same context (by push creation or pull creation). In case of push creation, if another bean autowire the Lo_DisplayHandler bean and call your method anyOtherMethod(), it will get the value.
Other way is to pull the bean from ObjectFactory.