Using Spring Boot & Spring Integration with database backed Configuration

折月煮酒 提交于 2020-01-02 10:19:13

问题


For spring boot + integration application, I'm attempting to load configuration from database, allow it to be accessible to Spring's Environment & inject-able via @Value annotation and be override-able by externalized configurations as described in the spring boot reference documentation under the Externalized Configuration Section.

The problem I'm having is that my spring Integration XML contains ${input} property placeholders that can not be resolved, because I can't get the database backed configuration to be loaded before Spring attempts to load the XML configurations.

The entry point to the application:

@SpringBootApplication
public class TestApplication {
   public static void main(String[] args) {
      SpringApplication.run(TestApplication.class, args);
   }
}

How database configuration would be loaded:

 @Configuration
 public class DbPropertiesConfig {

    @Autowired
    private org.springframework.core.env.Environment env;

    @PostConstruct
    public void initializeDatabasePropertySourceUsage() {
        MutablePropertySources propertySources = ((ConfigurableEnvironment) env).getPropertySources();
       try {
          // The below code will be replace w/ code to load config from DB
          Map<String,Object> map = new HashMap<>();
          map.put("input-dir","target/input");
          map.put("output-dir","target/output");
          DbPropertySource dbPropertySource = new DbPropertySource("si",map);
          propertySources.addLast(dbPropertySource);
       } catch (Exception e) {
           throw new RuntimeException(e);
       }
    }
 }

How Spring Integration config is loaded:

 @Profile("IN")
 @Configuration
 @ImportResource({"si-common-context.xml","si-input-context.xml"})
 public class SiInputAppConfig {
 }

The Spring Integration XML configurationsi-input-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:int="http://www.springframework.org/schema/integration"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:int-file="http://www.springframework.org/schema/integration/file"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                  http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://www.springframework.org/schema/integration
                  http://www.springframework.org/schema/integration/spring-integration.xsd
                  http://www.springframework.org/schema/integration/file
                  http://www.springframework.org/schema/integration/file/spring-integration-file.xsd" default-lazy-init="true">


    <int-file:inbound-channel-adapter channel="input2" directory="${input-dir}" filename-pattern="*">
        <int:poller fixed-rate="500"/>
    </int-file:inbound-channel-adapter>

       <int:service-activator input-channel="input2" ref="sampleEndpoint" method="hello" output-channel="output2"/>

    <int:channel id="output2"/>

    <int-file:outbound-channel-adapter channel="output2" directory="${output-dir}"/>

</beans:beans>

The error I get:

2015-10-28 17:22:18.283  INFO 3816 --- [           main] o.s.b.f.xml.XmlBeanDefinitionReader      : Loading XML bean definitions from class path resource [si-common-context.xml]
2015-10-28 17:22:18.383  INFO 3816 --- [           main] o.s.b.f.xml.XmlBeanDefinitionReader      : Loading XML bean definitions from class path resource [si-mail-in-context.xml]
2015-10-28 17:22:18.466  INFO 3816 --- [           main] o.s.b.f.config.PropertiesFactoryBean     : Loading properties file from URL [jar:file:/C:/Users/xxx/.m2/repository/org/springframework/integration/spring-integration-core/4.1.6.RELEASE/spring-integration-core-4.1.6.RELEASE.jar!/META-INF/spring.integration.default.properties]
2015-10-28 17:22:18.471  INFO 3816 --- [           main] o.s.i.config.IntegrationRegistrar        : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created.
2015-10-28 17:22:18.604  INFO 3816 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; ...
2015-10-28 17:22:18.930  WARN 3816 --- [           main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt

org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean#0.source' defined in null: Could not resolve placeholder 'si.in-input' in string value "${si.in-input}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'input-dir' in string value "${input-dir}" ...

Spring loads DbPropertiesConfig after XML configuration is attempted to be loaded.

How can I resolve this issue?

Thanks in advance

AP


回答1:


Yes, I can confirm by my home tests that XML definitions are loaded before the annotation stuff. It's enough complicated to determine why it is, but I'm sure that @Import* resources are more important by premise than an internal @Configuration logic.

Therefore your @PostConstruct isn't good for mix with XML.

One solution is to move all Spring Integration configuration to the Annotation style and even consider to use Spring Integration Java DSL.

Another solution is to follow with Spring Boot's Externalized Configuration recommendation:

  1. Default properties (specified using SpringApplication.setDefaultProperties).

That means you have to read properties from your DB before the starting Spring Application. Yes, if you were going to use DataSource on the matter from the same application, it won't be possible. From other side let's take a look to your goal one more time! You are going to load properties for the application from DB as an external configuration, so, what is the point to do that from the application itself? Of course, it would be more safe to load and feed properties before application start.

Hope I am clear.



来源:https://stackoverflow.com/questions/33403056/using-spring-boot-spring-integration-with-database-backed-configuration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!