Results 1 to 3 of 3

Thread: adding PropertySources to Environment - how to ensure refresh() called after?

  1. #1

    Default adding PropertySources to Environment - how to ensure refresh() called after?

    I have a Properties object that I'd like add as PropertySource to be used in interpolation throughout my app. ie in any bean within my app I would like to be able to do this:
    Code:
    ctx.getEnvironment.resolvePlaceholders("${myProp}); //myProp is in the above Properties object
    From Environment JavaDoc:
    When an Environment is being used by an ApplicationContext, it is important that any such PropertySource manipulations be performed before the context's refresh() method is called.
    How can the above be accomplished? - within WebApp contexts but also within unit-test env?

    I tried creating a bean that would add PropertySource and calling ctx.refresh() but a unit test with config below seems to use GenericXmlApplicationContext which does not support (repeat) calls to refresh()

  2. #2

    Default

    I am not sure I am clear on what you are trying to accomplish. But if you add a PropertySource to the PropertySourcesPlaceholderConfigurer you can access those properties through Spring's Environment. If you want refreshable properties take a look at ReloadableResourceBundleMessageSource.

  3. #3
    Join Date
    Nov 2007
    Posts
    10

    Default Profiles with properties files

    I really don't now if is this user case apply, but I saw a lot of people with the some problem: how to set a active profile without messing with bash variables or java system.properties?
    The most common case: you have a "jndi" connection to your database in your production code, but the integration tests runs with a local driver.
    Until now (Spring 3.1) you have a lot of xml files and with some profiles in Maven (don't confuse them with Spring profiles) you copy the desired one to the default if you are in production, or in dev, etc.
    When I read about profiles in Spring I thought that mess is over. A simple property file with my active profile et voilá. Well not so fast.

    A sample test file with context in @Configuration classes
    Code:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = {MongoTemplateConfig.class, LazVirtualMongoConfig.class, ProductionMongoConfig.class})
    public class MongoTest {
    
        @Autowired
        private MongoTemplate mongoTemplate;
    
        @Test
        public void crudTest() {
    
            mongoTemplate.dropCollection(PersonTrack.class);
           ...
    The configuration classes
    Ex:
    Code:
    @Configuration
    @Profile("dev")
    public class LazVirtualMongoConfig implements MongoConfig {
    
        @Override
        public @Bean
        MongoFactoryBean mongo() {
            MongoFactoryBean mongo = new MongoFactoryBean();
            mongo.setHost("lazvirtual.iol.pt");
            mongo.setWriteConcern(WriteConcern.SAFE);
            return mongo;
        }
    }
    are annotated with different profiles and everything works fine if I put the @ActiveProfile("dev") or @ActiveProfile("prd") in the test class.

    But that gives me again a hard coded configuration!
    What I need is the possibility of reading a external property file and set my active profile before the AnnotationConfigContextLoader registries the configuration classes.
    After reading everything Google gives me about the subject I find the solution in... the javadoc of AbstractGenericContextLoader:
    Code:
              /**
    	 * Prepare the {@link GenericApplicationContext} created by this<code>ContextLoader</code>.
    	 * Called <i>before</i> bean definitions are read.
    	 * <p>The default implementation is empty. Can be overridden in subclasses to
    	 * customize <code>GenericApplicationContext</code>'s standard settings.
    	 * @param context the context that should be prepared
    	 * @see #loadContext(MergedContextConfiguration)
    	 * @see #loadContext(String...)
    	 * @see GenericApplicationContext#setAllowBeanDefinitionOverriding
    	 * @see GenericApplicationContext#setResourceLoader
    	 * @see GenericApplicationContext#setId
    	 * @since 2.5
    	 */
    	protected void prepareContext(GenericApplicationContext context) {
    	}
    The AnnotationConfigContextLoader extends this class and mine become:

    Code:
    public class MyAnnotationConfigContextLoader extends AnnotationConfigContextLoader{
    
        
        @Override
        protected void prepareContext(GenericApplicationContext context){
            try {
                context.getEnvironment().getPropertySources().addFirst(new ResourcePropertySource("classpath:env.properties"));
            } catch (IOException ex) {
                
            }
            context.getEnvironment().setActiveProfiles(context.getEnvironment().getProperty("env"));
        }
    
    }
    And it works like a champion.
    The only thing we have to do is change the annotation to
    Code:
    @ContextConfiguration(loader = MyAnnotationConfigContextLoader.class, classes = {MongoTemplateConfig.class, LazVirtualMongoConfig.class, ProductionMongoConfig.class})
    If someone has a better aproach....
    Last edited by fsoares; Feb 28th, 2012 at 07:46 AM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •