1
votes

I'm trying to read the content in my application.properties file using the @Value annotation. But it will always return null back.

**Sample Java code**

    @Component    
    public class SampleClass() implements Runnable{
        @Value("${profile.name}")
        private String name;
    
        @Override
        public void run(){
            System.out.println("Name: " + name);
            ...
        }
    }

**Application.properties**

    profile.name=myname

**Pom.xml**

    <profiles>
    	<profile>
    		<id>dev</id>
    		<properties>
    			<activatedProperties>dev</activatedProperties>
    		</properties>
    	</profile>
    	<profile>
    		<id>stag</id>
    		<properties>
    			<activatedProperties>stag</activatedProperties>
    		</properties>
    	</profile>
    	<profile>
    		<id>prod</id>
    		<properties>
    			<activatedProperties>prod</activatedProperties>
    		</properties>
    	</profile>
    </profiles>
    ....
    <build>
        <resources>
            <resource>
        		<directory>src/main/resources</directory>
        		<filtering>true</filtering>
        		<includes>
        			<include>**/*.properties</include>
        		</includes>
        	</resource>
        </resources>
    </build>

I've even tried giving a default value to the variable and it still returning null.

@Value("${profile.name:'samplename'}")

Why??

Update

I managed to retrieve the profile.name value in my SampleClass() now. But i'm not really sure if the way I did was the correct way. SampleClass1 will call SampleClass2.

Sample Java 1 Code

@Component    
public class SampleClass1(){
    @Autowired
    SampleClass2 sampleClass2;

    @Value("${profile.name}")
    private String profileName;

    sampleClass2.setName(profileName);
    //Invoke SampleClass2
}

Sample Java 2 Code

@Component    
public class SampleClass2() implements Runnable{
    private String profileName;

    public void setName(String profileName){
        this.profileName= profileName;
    }
    @Override
    public void run(){
        System.out.println("Name: " + profileName);
        ...
    }
}
3
What about the client code that uses the run() method? It looks like the instance of the SampleClass is not created by Spring.Daniel Olszewski
Simply put it cannot be null, you either have a default value or your application blows up when starting. So you are probably using new SampleClass() instead of using the spring configured instance. Also the fact that you are using maven profiles and resource filtering with spring boot worries me a little (in short you don't need it nor should want it, use the Spring Boot support with profiles).M. Deinum
@M.Deinum @StanislavL. Yes, the class was called using new SampleClass(). what should be the correct way to deal with this?NatureWonder
You should inject it instead of creating a new instance.M. Deinum
Where's your Application.properties file located in your project?carlspring

3 Answers

0
votes

Your SampleClass must be a Bean. Add annotation to your class e.g. @Component to let Spring find it during scan and assign the value.

0
votes

Just to be clear.

@Component
@Getter
public class SampleComponentClass {

  @Value("${profile.name}")
  private String profileName;

}

@Component
Class SomeOtherClass{
    @Autowired
     SampleComponentClass sampleComponentClass;

    public void someMethod(){
     System.out.println(sampleComponentClass.getProfileName()); // prints testprofile
     SampleComponentClass sampleComponentClass1 = new SampleComponentClass();
     System.out.println(sampleComponentClass1.getProfileName()); // prints null
    }
}

In application.properties

profile.name=testprofile
0
votes

Injecting value in a config class and using instance of this component with autowired annotation could be a better approach.

@Configuration
public class SomeConfig {
    @Value("${profile.name}")
    private String profileName;

    @Bean
    public SampleClass1 sampleClass1(){
        SampleClass1 sampleClass1 = new Sampleclass1();
        // This approach, you can make additional control and configuration here 
        sampleClass1.setProfileName(profileName);
        return sampleClass1;
    }
    @Bean
    public SampleClass2 sampleClass2(){
        return new SampleClass2();
    }
}

And wherever you need SampleClass1

public class SomeClass{
    @Autowired
    private SampleClass1 sampleClass1;
}