3

I need to load bean definitions from XML. The file is in a remote location (http) which is configured by properties. The properties should also be loaded from a remote location (a spring cloud config server)

constraints:

  • Spring 4.3.14 (not boot)
  • should be in runtime and after my properties already loaded
  • beans defined in xml are referencing properties in context
  • server URI (to fetch the xml from) should be in properties and not environment variable or profile depandant

The current setup I have works well when MY_XML_URI is passed as environment variable:

${SPRING_CONFIG_URI}/master/application-${spring.profiles.active}.properties

<import resource="${MY_XML_URI}/myBeans.xml"/>

And in the remote location, myBeans.xml with lots of beans e.g.

<bean name="mySpecialBean" class="com.example.MyGenericBean">
        <constructor-arg value="mySpecialBean"/>
        <constructor-arg value="${special.bean.config.expression}"/>
</bean>

However trouble starts when I want to get MY_XML_URI from the properties context, it doesn't resolve …

I have tried several approaches e.g:

  • java configuration class with @ImportResource({"${xml.server.uri}"}) but the properties are not loaded yet so it not converting to real value of xml.server.uri .

    @Configuration
    @ImportResource({"${xml.server.uri:http://localhost:8888}/myBeans.xml"})
    public class MyConfiguration {}
    
  • expose dummy bean which fetch xml as resource and load the beans to parent applicationcontext - i must have it available to other beans dependant on those beans defined in xml. This solution was not injecting the properties context to my beans so failed to init them.

    @Configuration
    public class RiskConfig {
    
            @Value("${xml.server.uri}")
            private String xmlUri;
    
            @Autowired
            @Bean
            public Object myBean(ApplicationContext applicationContext) {
                    Resource resource = applicationContext.getResource(xmlUri + "myBeans.xml");
    
    //              not working since its not loading the beans to the main context
    //              GenericApplicationContext genericApplicationContext = new GenericApplicationContext(applicationContext);
    //              XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(genericApplicationContext);
    //              reader.loadBeanDefinitions(resource);
    
                    AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
                    BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory;
    
                    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
                    reader.loadBeanDefinitions(resource);
    
                    return new Object();
            }
    }
    

Finally - is there a way to load the beans from xml programmatically to parent application context (which is already exist) though they are injected with properties.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
Yoni
  • 375
  • 3
  • 19
  • placeholders in `import` elements are only resolved from the system properties or the environment. Not from loaded property files. Loading property files and contexts isn't a multi pass operation, so what you want isn't possible. At least not possible without coding something up yourself. – M. Deinum Jul 19 '18 at 08:38
  • @m-deinum i don't mind coding something, do you have any specific suggestion or some spring hook to implement for this ? – Yoni Jul 19 '18 at 19:32
  • Did you manage to make this work? If so, would you mind providing an Answer below so others can benefit? Thanks. – Jamie Bisotti Mar 08 '22 at 17:30
  • @JamieBisotti couldn't find a way to do exactly as I wanted, programmatically or load the URI from the configuration. I kept the solution as written above where I set the remote URI, aka MY_XML_URI, as an environment variable. The deployment script prepares the env variables responsible to fetch the real value of MY_XML_URI from our configuration server. – Yoni Mar 13 '22 at 09:17

0 Answers0