Announcement Announcement Module
Collapse
No announcement yet.
overrule PropertyOverrideConfigurer bean in code Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • overrule PropertyOverrideConfigurer bean in code

    I have a PropertyOverrideConfigurer bean in one of my Spring xml configuration files/contexts.

    In some cases, I want to reuse this Spring context, but overrule the PropertyOverrideConfigurer from the XML with one that I define in my Java code as follows:

    Code:
    PropertyOverrideConfigurer cfg = new PropertyOverrideConfigurer();
    cfg.setLocation(new ClassPathResource(propertyOverriderLocation));
            aContext.addBeanFactoryPostProcessor(cfg);
            aContext.refresh();
    This code has no effect though. The PropertyOverrideConfigurer from the XML keeps being used.

    I tested this with a PropertyPlaceholderConfigurer in the XML and then it did override the properties with those defined by the Java code, but that is not what I'm looking for. The PropertyOverrideConfigurer in the XML already overrides a PropertyPlaceholderConfigurer from another XML... I want to override it a 3th time, via code, without changing any of the other XMLs.

  • #2
    Try setting the ordered property of your override configurer (to something lower than the others)?

    Comment


    • #3
      That sounded like a good idea!

      I added
      Code:
      <property name="order" value="1"  />
      to the PropertyOverrideConfigurer in my XML and
      Code:
      cfg.setOrder(0);
      in my Java code.

      Unfortunately, it still takes the properties from the PropertyOverrideConfigurer defined in XML

      I switched the priority numbers as well, but to no avail.

      Comment


      • #4
        I made a small proof of concept to isolate the issue from the rest of my code: see attachment. The main class is OverridePropertiesPoc.

        Comment


        • #5
          The problem may be that BeanFactoryPostProcessors registered with

          Code:
          aContext.addBeanFactoryPostProcessor(cfg);
          always take prescedence over the regular beans in a bean factory. Try

          Code:
          aContext.registerSingleton("overrideBeanPropertiesOverride", cfg);
          instead.

          Comment


          • #6
            registerSingleton is not available on ClassPathXmlApplicationContext?

            Comment


            • #7
              I think it's actually on the BeanFactory.
              http://www.springframework.org/docs/...anFactory.html

              Comment


              • #8
                Digging this one back up...

                I tried your solution, but now it returns me the value I put in the context XML and not the one from overridePropertiesPoc.properties. Is there something I forgot?

                Code:
                        XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("/org/springframework/poc/context.xml", getClass()));
                        
                //        ClassPathXmlApplicationContext aContext = new ClassPathXmlApplicationContext(
                //                SPRING_CONTEXT_PATHS, false);
                        PropertyOverrideConfigurer cfg = new PropertyOverrideConfigurer();
                        String propertyOverriderLocation = "/org/springframework/poc/dev/overridePropertiesPoc.properties";
                        System.out.println("propertyOverriderLocation = "
                                + propertyOverriderLocation);
                        cfg.setLocation(new ClassPathResource(propertyOverriderLocation));
                //        cfg.setOrder(0);
                //        aContext.addBeanFactoryPostProcessor(cfg);
                //        aContext.refresh();
                //        PocBean pocBean = (PocBean) aContext.getBean(BEAN_ID, PocBean.class);
                        xmlBeanFactory.registerSingleton("overrideBeanPropertiesOverride", cfg);
                        PocBean pocBean = (PocBean) xmlBeanFactory.getBean(BEAN_ID, PocBean.class);
                        // should be "value from dev properties" but is "value from local
                        // properties"
                        System.out.println("pocBean name = " + pocBean.getName());
                Enabling or disabling the order setting has no impact.
                Last edited by Snow; May 24th, 2007, 08:41 AM.

                Comment


                • #9
                  If you use a "raw" BeanFactory the post processors are not called by default. I think a better approach would be to go back to ClassPathXmlApplicationContext. Sorry for getting the API wrong. Try something like this:

                  Code:
                  // create the context and make sure it is not refreshed...
                  aContext.getBeanFactory().registerSingleton("overrideBeanPropertiesOverride", cfg);
                  aContext.refresh();
                  Last edited by Dave Syer; May 24th, 2007, 11:21 AM. Reason: forgot brackets on method call!

                  Comment


                  • #10
                    ok, so when I put my ClassPathXmlApplicationContext back in place like this:
                    Code:
                    ClassPathXmlApplicationContext aContext = new ClassPathXmlApplicationContext(
                                    SPRING_CONTEXT_PATHS, false);
                    false, to make sure that it is not refreshed on initialization.

                    and set the following:
                    Code:
                    aContext.getBeanFactory().registerSingleton("overrideBeanPropertiesOverride", cfg);
                    aContext.refresh();
                    it gives me an exception on the registerSingleton line:
                    Code:
                    java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext
                    	at org.springframework.context.support.AbstractRefreshableApplicationContext.getBeanFactory(AbstractRefreshableApplicationContext.java:120)
                    	at org.springframework.poc.OverridePropertiesPoc.method2(OverridePropertiesPoc.java:43)
                    	at org.springframework.poc.OverridePropertiesPoc.main(OverridePropertiesPoc.java:54)
                    When I initialize my ClassPathXmlApplicationContext with refresh = true, there is no error, but then I get the values from the local properties again (the propertyOverrideConfigurer from the XML).

                    Comment


                    • #11
                      This works for me (with your configuration from the poc archive you posted):

                      Code:
                              GenericApplicationContext context = new GenericApplicationContext();
                              XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context);
                              reader.loadBeanDefinitions(new ClassPathResource(SPRING_CONTEXT_PATH));
                              PropertyOverrideConfigurer cfg = new PropertyOverrideConfigurer();
                              cfg.setLocation(new ClassPathResource(ClassUtils.addResourcePathToPackagePath(OverridePropertiesPocTests.class, "dev/overridePropertiesPoc.properties")));
                              cfg.setOrder(2);
                              context.getBeanFactory().registerSingleton("override", cfg);
                              context.refresh();
                              PocBean pocBean = (PocBean) context.getBean(BEAN_ID, PocBean.class);
                              assertEquals("value from dev properties", pocBean.getName());
                      But maybe it should be easier. Remind me: why do you need to do the override programmatically?

                      Comment


                      • #12
                        Genius, it works! Thx for the effort.

                        We set this programmatically at runtime to reuse the same Spring config for different behaviours.

                        Comment


                        • #13
                          But if all you are doing is switching the location of a properties file at runtime you can do that with a simple PropertyPlaceholderConfigurer?

                          Comment


                          • #14
                            The poc example doesn't show the full context of our situation here where several Spring config files come into play. There's already a PropertyPlaceHolder in one of the configs, overriden by a PropertyOverrider in another config and we wanted to override that once more.

                            We couldn't change any of the included Spring config files, because they belong to another API.

                            Comment

                            Working...
                            X