Results 1 to 7 of 7

Thread: Runtime reconfiguration

  1. #1
    Join Date
    Feb 2005
    Posts
    9

    Default Runtime reconfiguration

    Hello,

    I am wondering if it's possible to alter an ApplicationContext at runtime. I see that some ApplicationContexts are "reloadable," and that they can have a "properties configurer." Does that mean I can at any point swap in a new "properties configurer" or change its properties, and then reload the ApplicationContext? That would be very cool.

    My goal here is to allow an admin to tweak a running application by swapping in different implementations at various points. So on reload, I give the "userManager" id a different class. Or perhaps this or that bean's "userManager" property now has a ref to id "anotherUserManager."

    Thanks!

    Paul

  2. #2
    Join Date
    Aug 2004
    Location
    Amsterdam, Netherlands
    Posts
    450

    Default

    At the moment the option you have to change an application context are very limited. Refreshing of an application context (using the refresh() method, which I the one I suppose you meant) causes the persistent context to be reloaded (in many cases XML). So you'd have to modify the XML and then reload the context (which isn't really feasible I guess).

    Either 1.2 or 1.3 will feature better support for dynamic reloading of a context and swapping out/in of beans.

    regards,
    Alef Arendsen
    Alef Arendsen
    SpringSource
    http://www.springsource.com

  3. #3
    Join Date
    Feb 2005
    Posts
    9

    Default

    If I write it, can it go in 1.2? :-)

    Seriously, compared to what I need, I imagine you'll want to do something much cleaner, writing an appropriate interface and then retrofitting classes to implement it, something like setBeanDefinition(String id, BeanDefinition def). But I am thinking that I'll copy/paste some existing ApplicationContexts so I can propgrammitcally plug in a properties configurer and then call refresh. The XML file would not change, but the values for the ${blah} properties would be different. Imagine I have this:

    <beans>
    <bean id="userManager" class="${userManagerImpl}"/>
    <bean id="myService" class="com.company.MyService">
    <property> <ref bean="userManager"/> </property>
    </bean>
    </beans>

    In that case, I need only tweak the PropertyPlaceholderConfigurer and hit refresh. Does that sound like a reasonable approach?

    Btw, thanks for the quick reply.

    Paul

  4. #4
    Join Date
    Aug 2004
    Location
    Amsterdam, Netherlands
    Posts
    450

    Default

    I'd do it programmatically. The PropertyPlaceholderConfigurer has a method (postProcessBeanFactory) you can use to do this. The thing is however that the factory will already have initialized itself after you call refresh() and when eagerly loading singletons the values you'll be providing won't have any effect. You can specify the default lazy initialization parameter at the <beans> level (default-lazy-init). It's probably work if you set this to true.

    Code:
    PropertiesPlaceholderConfigurer config;
    ConfigurableApplicationContext ctx;
    config.postProcessBeanFactory&#40;config&#41;;
    I'm not sure if all works like you want. Could you provide some feedback if it does (or doesn't)?

    Hope this helps.

    regards,
    Alef Arendsen
    Alef Arendsen
    SpringSource
    http://www.springsource.com

  5. #5
    Join Date
    Feb 2005
    Posts
    9

    Default

    Okay, it works great!

    I ended up extending PropertyPlaceholderConfigurer to override resolvePlaceholder. My class keeps its own static Properties and checks there first. If it doesn't find what it wants, then it calls super.resolvePlaceholder. This lets me set properties that will stick around even after refreshing the BeanFactory. You would get similar behavior if you looked for the properties in a database instead of a static variable. Here is the class:

    Code:
    package com.company;
    
    import org.springframework.beans.PropertyValue;
    import org.springframework.beans.MutablePropertyValues;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.config.BeanDefinition;
    import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
    
    import org.apache.log4j.Logger;
    
    import java.util.*;
    
    public class StaticPlaceholderConfigurer extends PropertyPlaceholderConfigurer &#123;
    
        private static final Logger log = Logger.getLogger&#40;StaticPlaceholderConfigurer.class&#41;;
        private static final Map    overrides = new HashMap&#40;&#41;;
    
        private String  _beanName;
        private BeanFactory _factory;
    
        public StaticPlaceholderConfigurer&#40;&#41; &#123;
            log.debug&#40;"overrides at new instance&#58; " + overrides&#41;;
        &#125;
    
        protected String resolvePlaceholder&#40;String placeholder, Properties fallback&#41; &#123;
            Properties props;
            String  ret;
    
            synchronized &#40;overrides&#41; &#123;
                props = &#40;Properties&#41;overrides.get&#40;getKey&#40;&#41;&#41;;
                log.debug&#40;"props for " + placeholder + "&#58; " + props&#41;;
                if &#40;props == null&#41; &#123;
                    return super.resolvePlaceholder&#40;placeholder, fallback&#41;;
                &#125; else &#123;
                    ret = props.getProperty&#40;placeholder&#41;;
                    if &#40;ret != null&#41; return ret;
                    else return super.resolvePlaceholder&#40;placeholder, fallback&#41;;
                &#125;
            &#125;
        &#125;
    
        public String setOverride&#40;String name, String value&#41; &#123;
            synchronized &#40;overrides&#41; &#123;
                Properties  props;
                OverrideKey key;
    
                key = getKey&#40;&#41;;
                props = &#40;Properties&#41;overrides.get&#40;key&#41;;
                if &#40;props == null&#41; &#123;
                    props = new Properties&#40;&#41;;
                    overrides.put&#40;key, props&#41;;
                &#125;
                return &#40;String&#41;props.setProperty&#40;name, value&#41;;
            &#125;
        &#125;
    
        public void setOverrides&#40;Properties props&#41; &#123;
            synchronized &#40;overrides&#41; &#123;
                overrides.put&#40;getKey&#40;&#41;, new Properties&#40;props&#41;&#41;;
            &#125;
        &#125;
    
        public void clearOverrides&#40;&#41; &#123;
            synchronized &#40;overrides&#41; &#123;
                overrides.remove&#40;getKey&#40;&#41;&#41;;
            &#125; 
        &#125;
    
        private OverrideKey getKey&#40;&#41; &#123;
            return new OverrideKey&#40;_factory, _beanName&#41;;
        &#125;
    
        public void setBeanName&#40;String name&#41; &#123;
            super.setBeanName&#40;name&#41;;
            _beanName = name;
        &#125;
        public void setBeanFactory&#40;BeanFactory f&#41; &#123;
            super.setBeanFactory&#40;f&#41;;
            _factory = f;
        &#125;
    
    &#125;
    
    class OverrideKey &#123;
    
        private final BeanFactory _f;
        private final String _beanName;
    
        public OverrideKey&#40;BeanFactory f, String beanName&#41; &#123;
            _f = f;
            _beanName = beanName;
        &#125;
    
        public int hashCode&#40;&#41; &#123;
            // return _f.hashCode&#40;&#41; + _beanName.hashCode&#40;&#41;;
            // The factory is a different instance after refresh.
            return _beanName.hashCode&#40;&#41;;
        &#125;
    
        public boolean equals&#40;Object o&#41; &#123;
            if &#40;o instanceof OverrideKey&#41; &#123;
                OverrideKey k = &#40;OverrideKey&#41;o;
    
                // return _f.equals&#40;k._f&#41; && _beanName.equals&#40;k._beanName&#41;;
                // The factory is a different instance after refresh.
                return _beanName.equals&#40;k._beanName&#41;;
            &#125; else &#123;
                return false;
            &#125;
        &#125;
    &#125;
    I then use an applicationContext.xml file like this one:

    Code:
    <beans>
        <bean id="myService" class="com.company.MyService">
            <property name="emailManager"> <ref bean="$&#123;emailManager&#125;"/> </property>
        </bean>
        <bean id="override" class="com.company.StaticPlaceholderConfigurer">
            <property name="systemPropertiesModeName"><value>SYSTEM_PROPERTIES_MODE_NEVER</value></property>
            <property name="properties">
                <props>
                    <prop key="emailManager">emailManager</prop>
                </props>
            </property>
        </bean>
        <bean id="emailManager" class="com.company.EmailManager"/>
        <bean id="mockEmailManager" class="com.company.MockEmailManager"/>
    </beans>
    When we begin, MyService has an EmailManager. But if I want to change to a MockEmailManager, I just get the override bean, call setOverride, and then refresh the ApplicationContext. Future clients of MyService will use a MockEmailManager. This is great for test code. I plan to use the same patten for all sorts of hot-swappable interfaces.

    Thanks for your help,

    Paul

  6. #6
    Join Date
    Aug 2004
    Location
    San Mateo, CA
    Posts
    1,265

    Default

    Paul

    Thanks for posting this. I'll look at this properly for the 1.3 timeframe.

    The scope of 1.2 is now fairly fixed--Hibernate 3, transaction annotations, JMX and (hopefully) an official release of TopLink support--but such "dynamic" features will hopefully go into 1.3. We're currently interested in support for configuration in JSR-170 content repositories, which should be dynamic and allow versioning.

    Rgds
    Rod
    Rod Johnson - GM, SpringSource Division, VMware
    http://www.springsource.com
    Spring From the Source

  7. #7
    Join Date
    May 2006
    Location
    Oldenburg, Germany
    Posts
    14

    Default

    Quote Originally Posted by Rod Johnson
    "dynamic" features will hopefully go into 1.3
    I'm looking for dynamic reconfiguration features. How is the current planning?

    Regards
    Dennis

Similar Threads

  1. Replies: 9
    Last Post: Oct 14th, 2005, 09:38 AM
  2. Injecting runtime constructor-arg properties
    By james.estes in forum Container
    Replies: 4
    Last Post: Oct 5th, 2005, 07:37 AM
  3. Replies: 3
    Last Post: Aug 17th, 2005, 05:44 AM
  4. Replies: 13
    Last Post: Jun 14th, 2005, 06:28 PM
  5. Authorisation using runtime data.
    By tdekeizer in forum Security
    Replies: 4
    Last Post: May 2nd, 2005, 09:19 AM

Posting Permissions

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