din_oops
din_oops

Reputation: 708

springboot issues reading from properties file

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

Answers (2)

Ananthapadmanabhan
Ananthapadmanabhan

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

fap
fap

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

Related Questions