title: Setting up Spring 4.1 profile environment using YAML instead of Properties and @Profile
body: <p>I'm trying to set up my profiles using YAML configuration files. Rather than having different <code>@Configuration</code> classes annotated with <code>@Profile</code> for different ones (or even a same <code>@Configuration</code> class with different annotated <code>@Beans</code>), i would like to have one <code>@Configuration</code> class using Placeholder with YAML configuration file.  </p>
  
  <p>Taking a look at <a href="http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-yaml" rel="nofollow noreferrer">Spring boot documentation</a>, <a href="http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/YamlPropertiesFactoryBean.html" rel="nofollow noreferrer">YamlPropertiesFactoryBean javadoc</a> and <a href="https://stackoverflow.com/questions/28303758/how-to-use-yamlpropertiesfactorybean-to-load-yaml-files-using-spring-framework-4/28829727#28829727">this Stackoverflow topic</a>, i've came up with the following code:</p>
  
  <p>A simple YAML file: <code>application-default-config.yml</code></p>
  
  <pre><code>foo: myFoo
  </code></pre>
  
  <p>A <code>@Configuration</code> file:</p>
  
  <pre><code>import org.springframework.beans.factory.annotation.Value;
  import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
  import org.springframework.core.io.ClassPathResource;
  
  @Configuration
  public class ApplicationConfig {
  
    @Bean
    public static PropertySourcesPlaceholderConfigurer ymlProperties() {
      PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer =
          new PropertySourcesPlaceholderConfigurer();
  
      YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
      yaml.setResources(new ClassPathResource("config/application-${spring.profiles.active:default}-config.yml"));
          propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
  
      return propertySourcesPlaceholderConfigurer;
    }
  
    @Value("${foo}")
    private String fooValue;
  
    @Bean
    public String fooValue() {
      return fooValue;
    }
  }
  </code></pre>
  
  <p>A test file:</p>
  
  <pre><code>import org.junit.Assert;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.core.env.Environment;
  import org.springframework.test.context.ContextConfiguration;
  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  
  @RunWith(SpringJUnit4ClassRunner.class)
  @ContextConfiguration(classes = ApplicationConfig.class)
  public class ApplicationConfigTest {    
  
    @Autowired
    Environment environment;
  
    @Autowired
    String fooValue;
  
    @Test
    public void testFooViaEnvironment() {
      Assert.assertEquals("myFoo", environment.getProperty("foo"));
    }
  
    @Test
    public void testFooViaWiredValue() {
      Assert.assertEquals("myFoo", fooValue);
    }
  }
  </code></pre>
  
  <p>And, finally, a main file:</p>
  
  <pre><code>import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
  import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  import org.springframework.core.env.ConfigurableEnvironment;
  import org.springframework.core.env.PropertiesPropertySource;
  import org.springframework.core.io.ClassPathResource;
  
  public class Application {
    public static void main(String[] args) {
      AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
  
      ctx.register(ApplicationConfig.class);
  
      YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
      yaml.setResources(new ClassPathResource("config/application-${spring.profiles.active:default}-config.yml"));
  
      ConfigurableEnvironment environment = ctx.getEnvironment();
      environment.getPropertySources()
          .addFirst(new PropertiesPropertySource("custom", yaml.getObject()));
  
      ctx.refresh();
  
      String fooViaWiredValue = (String) ctx.getBean("fooValue");
  
      System.out.println(String.format("fooViaEnvironment=%s", environment.getProperty("foo")));
  
      System.out.println(String.format("fooViaWiredValue=%s", fooViaWiredValue));
  
    }
  }
  </code></pre>
  
  <p>I've noticed that in my test class, i can access the 'foo' property via <code>@Value</code> annotation but not via <code>Environment</code>.
  As well explained in some Stackoverflow topics like <a href="https://stackoverflow.com/questions/21100729/propertysourcesplaceholderconfigurer-not-registering-with-environment-in-a-sprin/21106326#21106326">this</a> and <a href="https://stackoverflow.com/questions/14169834/spring-3-1-environment-does-not-work-with-user-property-files/14170198#14170198">that</a>, annotating a <code>PropertySourcesPlaceholderConfigurer</code> as a <code>@Bean</code> is not enough to tight it with the <code>Environment</code>. It is necessary to do it programmatically as i did in <code>Application</code> class. In contrast, annotated <code>@Value</code>s are wired accordingly. </p>
  
  <p>My questions are, in fact, about best practices working with Spring.
  I would prefer using <code>Environment</code> rather than <code>@Value</code> annotation.
  Is there any way to load my YAML configuration files into Spring application context inside a test environment without needing to do it programmatically as i did in <code>Application</code> class ?</p>
  
  <p>Is there any reason i should prefer using <code>@Value</code> (or any other profile configuration) over <code>Environment</code> +  YAML configuration files ? As i said, i would like to have a unique <code>@Bean</code> using placeholders rather than multiples <code>@Bean</code>s annotated with <code>@Profile</code>s. </p>