Reputation: 708
I am trying to read property values in a Util
class.
I tried Environment
and @Value
. But its getting Null
value for these fields.
@SpringBootApplication
@EnableJpaAuditing
public class EmployeeApplication {
@PostConstruct
private void init() {
System.out.println("AppInitializator initialization logic ...");
new Util().getTime();
}
public static void main(String[] args) throws Exception {
SpringApplication.run(EmployeeApplication.class, args);
}
}
public class Util {
@Autowired
private Environment env;
@Value("${defaultTimeFormat}")
private String defaultTimeFormat;
public void getTime(){
System.out.println(defaultTimeFormat);
System.out.println(env.getProperty("defaultTimeFormat"));
// method logic here
}
}
I solved the issue by making Util as @Service
class and injected its dependency in EmployeeApplication
as follows.
@SpringBootApplication
@EnableJpaAuditing
public class EmployeeApplication {
@Autowired
Util util;
@PostConstruct
private void init() {
System.out.println("AppInitializator initialization logic ...");
util.getTime();
}
public static void main(String[] args) throws Exception {
SpringApplication.run(EmployeeApplication.class, args);
}
}
@Service
public class Util {
@Autowired
private Environment env;
@Value("${defaultTimeFormat}")
private String defaultTimeFormat;
public void getTime(){
System.out.println(defaultTimeFormat);
System.out.println(env.getProperty("defaultTimeFormat"));
// method logic here
}
}
But is the right way in spring-boot
? Do I need to make it Service/Component/Repository
to read from property file?
Upvotes: 1
Views: 901
Reputation: 6226
For starters , using @Value
to directly inject the property values to the needed class is discouraged as it reduces maintainability. As the number of your injected values increases it becomes difficult to keep track of them. Instead using a AppConfiguration
class to map these values to initially is appreciated.This means you could accumulate all your configurations at a single place and use it later in your code where-ever needed.
As @fap said, inorder to autowire or inject a value from yml/property using the @Value
annotation , the bean creation for the class needs to be managed by Spring .In your Util
class even though you are autowiring beans and using the @Value
annotation to inject the value of defaultTimeFormat
, you are not providing spring the control to create the bean for the class.
Spring handles dependency injection during the bean creation stage and hence since that control is not provided to spring , the value is not getting resolved. What you can do is create a bean for the Util class using either @Component
annotation or @Bean
annotation so that spring has the control of the bean creation like :
Method 1 :
@Configuration
class GeneralConfiguration {
@Bean
public Util returnUtilBean() {
return new Util();
}
}
or like @fab suggested use the @Component
annotation so that spring automatically creates a bean for your Util class :
Method 2 :
@Component
public class Util {
@Autowired
private Environment env;
@Value("${defaultTimeFormat}")
private String defaultTimeFormat;
public void getTime(){
System.out.println(defaultTimeFormat);
System.out.println(env.getProperty("defaultTimeFormat"));
// method logic here
}
}
The @Service
annotation is a stereotyped specialization of the @Component
annotation, that is why it worked for you.
Property values can be injected directly into your beans by using the @Value annotation, accessed through Spring’s Environment abstraction, or be bound to structured objects through @ConfigurationProperties.
Upvotes: 1
Reputation: 683
Yes, you need to annotate the class with @Component
or one of the other annotations so it gets instantiated by Spring Boot.
Only objects that have their life cycle controlled by Spring get values injected by Spring, which is what's happening if you add a @Value
annotation.
During application start Spring fills the application context with singleton instances of the classes that you've annotated.
Only these classes will get values injected via @Autowired
or @Value
.
Upvotes: 2