Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring-boot properties not @Autowired

I am trying to get a Spring-boot application going and I am not sure what I am doing wrong here. I have a application.properties file at src/main/resources & src/test/resources. I have an @Bean for my ConfigurationSettings so that I can use them throughout my application:

@Component
public class ConfigurationSettings {

private String product;
private String version;
private String copyright;
private String appName;
private String appDescription;
... 
// getters and setters

}

Here is how I kick the application off:

@Configuration
@EnableJpaRepositories
@EnableAutoConfiguration
@EnableConfigurationProperties
@PropertySources(value = {@PropertySource("classpath:application.properties")})
@ComponentScan(basePackages = "com.product")
@EnableScheduling
public class OFAC {

public static void main(String[] args) {
    ApplicationContext ctx = SpringApplication.run( OFAC.class, args );        
}

And here is my configuration class:

@Configuration
@ComponentScan(basePackages = {"com.product"})
@PropertySources(value = {@PropertySource("classpath:application.properties")})
public class OFAConfiguration {

     @Autowired
     private Environment env;

     @Bean
     public ConfigurationSettings configurationSettings() {
         ConfigurationSettings configurationSettings = new ConfigurationSettings();
         configurationSettings.setAppDescription( env.getRequiredProperty("app.description" ) );
         configurationSettings.setAppName( env.getRequiredProperty( "app.name" ) );
         configurationSettings.setServerPort( env.getRequiredProperty( "server.port" ) );
         return configurationSettings;
    }

I am trying to use it in a controller:

@RestController
public class AboutController {

   @Autowired
   private ConfigurationSettings configurationSettings;

   @RequestMapping(value = "/about", method = RequestMethod.GET)
   public About index() {

     String product = configurationSettings.getProduct();
     String version = configurationSettings.getVersion();
     String copyright = configurationSettings.getCopyright();
    return new About( product, version, copyright );
   }
}

However, when step thru this, all the values of ConfigurationSettings are null. I do have a test that successfully loads the values:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {OFAConfiguration.class})
public class OFAConfigurationTest {
  @Autowired
  private Environment environment;

  @Autowired
  private ConfigurationSettings configurationSettings;

  @Test
  public void testConfigurationLoads() {
    assertNotNull(environment);
    Assert.assertNotNull(configurationSettings);
  }

  @Test
  public void testConfigurationSettingValues() {
     assertEquals("Product Name", configurationSettings.getProduct());
    assertEquals("0.0.1", configurationSettings.getVersion());
    assertEquals("2014 Product", configurationSettings.getCopyright());
 }

Can anyone see why the ConfigurationSettings are not being populated in my Controller?

like image 681
sonoerin Avatar asked Oct 02 '22 10:10

sonoerin


1 Answers

Your configuration leads to 2 instances of the ConfigurationSettings class and probably one instance overrides the other.

The 'ConfigurationSettings' has the @Component annotation as you are scanning for components (@ComponentScan) this will lead to an instance. You also have a @Bean annotated method which also leads to an instance. The latter is overridden with the first.

In short remove the @Component annotation as that isn't needed because you already have a factory method for this class.

public class ConfigurationSettings { ... }

You should also remove the @PropertySource annotations as Spring-Boot will already load the application.properties for you.

Finally you should not use the @ContextConfiguration annotation on your test class but the @SpringApplicationConfiguration and pass in your application class (not your configuration class!).

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes=OFAC.class)
public class OFAConfigurationTest {

    @Autowired
    private Environment environment;

    @Autowired
    private ConfigurationSettings configurationSettings;

    @Test
    public void testConfigurationLoads() {
        assertNotNull(environment);
        assertNotNull(configurationSettings);
    }

    @Test
    public void testConfigurationSettingValues() {
        assertEquals("Product Name", configurationSettings.getProduct());
        assertEquals("0.0.1", configurationSettings.getVersion());
        assertEquals("2014 Product", configurationSettings.getCopyright());
    } 

This will fix your runtime configuration problems and will let your test use the power of Spring Boot to configure your application.

like image 162
M. Deinum Avatar answered Oct 05 '22 12:10

M. Deinum