Home » Java » java – Spring boot autowiring: strange case of property value being populated-Exceptionshub

java – Spring boot autowiring: strange case of property value being populated-Exceptionshub

Posted by: admin February 25, 2020 Leave a comment

Questions:

I’ve been blown away by something and my sleep is nowhere after finding out that my code is working from last 2 years when clearly it shouldn’t!
So it’s a Spring boot application. The application has some controllers. One of the classes I’m using extends WebServiceGatewaySupport, so requires that I @Autowire this. The class name is AClient. Now, this class needs 4 properties to work. Three of them are coming from properties file, e.g.

@Value("${a.userName}")String userName; 

So three properties are obviously picked from application.properties file. Now the fourth property had me blown away. It is NOT being fetched as rest three, but is being copied from constructor parameter. So we have only one constructor in the class:

public AClient(String d){
    this.d=d;
}

Now this property is being used in one of the methods this class has

public String getSomeData(){
// This method gets Data based on property d
}

And interestingly and surprisingly, this property’s value is present everytime this bean is accessed! The bean is @Autowired at one place only, inside the Controller class. I haven’t marked the property value to be fetched from application.properties file. I haven’t provided this class any clue where to get the value of d from. I haven’t provided any public methods for other classes to set this value. Yet the code is working and I can even place a debug pointer in method getSomeData() and see that the value of d is present!

Now I understand I might be missing something obvious, but what? Is there a way I can get into Spring container when @Autowired objects are being instantiated and debug from that point to see where this value is coming from? I’ve checked the code multiple times. Run hundreds of query on Google to find something like Spring boot does some magic stuff to map the missing String properties. But the variable name in properties file is different from what it is in AClient class. So how can it even map? This is truly killing me now!

Addition:
Less relevant, but the code is being accessed in a standard way:

@Autowired
AClient aClient;

public someOtherMethod(){
    aClient.getSomeData();
}

So when I place a debugger on first line of someOtherMethod() and hover over aClient, it shows variable d value populated, same as in application.properties file!

Edit:Here’s what I missed:

@Configuration
public class someConfig{
@Bean
   public AClient aClient(){
    // Someone else fetched property from application.properties file, created an object of AClient class using argument constructor and returned that object here. So now Spring is using @Autowire reference for this object I guess
 }
}
How to&Answers:

So basically, your @Configuration class looks similar to this?

@Configuration
public class SomeConfig {

    @Value("${a-client.important-value-d}")
    private String importantValueDFromApplicationProperties;

    @Bean
    public AClient aClient() {
        return new AClient(importantValueDFromApplicationProperties);
    }

}

If yes, then Spring will the aClient for every @Autowired requesting it. Therefore the value of importantValueDFromApplicationProperties will be present in this certain instance.

Another note:
I would recommend using Spring Boot’s @ConfigurationProperties instead of @Value. Take a look.