【问题标题】:Spring boot Failed to load applicationcontextSpring Boot 加载应用上下文失败
【发布时间】:2019-02-15 19:37:27
【问题描述】:

有一个 springboot 应用程序,它使用 file-inbound-adapter 从源目录读取文件。为其编写 junit 测试用例。 Junit 测试用例在我的本地 Eclipse 中成功执行。但是从部署在另一台机器上的竹子/詹金斯运行它时遇到问题。

在执行 spring boot junit 测试用例时无法加载应用程序上下文。 'filesInChannel.adapter.source' 原因:java.lang.IllegalArgumentException:源目录 [/filepath] 不存在。

这是什么原因造成的。对此有何建议/建议?是因为竹子部署机器的一些权限问题吗?

已经为测试用例编写了单独的配置。但不确定为什么它指向原始 xml 以在执行测试用例时加载应用程序上下文。

错误:

   java.lang.IllegalStateException: Failed to load ApplicationContext
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'filesInChannel.adapter': Cannot resolve reference to bean 'filesInChannel.adapter.source' while setting bean property 'source'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'filesInChannel.adapter.source': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Source directory [/filepath] does not exist.
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'filesInChannel.adapter.source': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Source directory [/filepath] does not exist.
    Caused by: java.lang.IllegalArgumentException: Source directory [/filepath] does not exist.

file-process.xml 源代码:

<file:inbound-channel-adapter id="filesInChannel"
        directory="/filepath/" auto-startup="false" scanner="recursiveScanner" auto-create-directory="true">
                <integration:poller id="poller" max-messages-per-poll="${max.messages.per.poll}" fixed-rate="${message.read.frequency}" task-executor="pollingExecutor">
            <integration:transactional transaction-manager="transactionManager" />
        </integration:poller>       
    </file:inbound-channel-adapter>

测试用例:

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = TestConfig.class)
public class FileApplicationTests {

    @Test
    public void contextLoads() {
    }

}

测试配置:

@Configuration
@ImportResource({ "classpath:test-file-process.xml" })
public class TestConfig {

}

test-file-process.xml源码:

<file:inbound-channel-adapter id="filesInChannel"
        directory="file:${java.io.tmpdir}/filepath/" auto-startup="false" scanner="recursiveScanner" auto-create-directory="true">
                <integration:poller id="poller" max-messages-per-poll="${max.messages.per.poll}" fixed-rate="${message.read.frequency}" task-executor="pollingExecutor">
            <integration:transactional transaction-manager="transactionManager" />
        </integration:poller>
    </file:inbound-channel-adapter>

日志:

018-09-11 14:54:39.893  INFO 9224 --- [           main] c.o.i.f.h.ErrorHandlerTest               : Starting ErrorHandlerTest on pc226116 with PID 9224 (started by test in D:\Repo\file-handler)
2018-09-11 14:54:39.896  INFO 9224 --- [           main] c.o.i.f.h.ErrorHandlerTest               : No active profile set, falling back to default profiles: default
2018-09-11 14:54:39.901  INFO 9224 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@22dc59b2: startup date [Tue Sep 11 14:54:39 IST 2018]; root of context hierarchy
2018-09-11 14:54:39.910  INFO 9224 --- [           main] o.s.b.f.x.XmlBeanDefinitionReader        : Loading XML bean definitions from class path resource [test-file-process.xml]
2018-09-11 14:54:40.158  INFO 9224 --- [           main] o.s.i.c.IntegrationRegistrar             : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created.
2018-09-11 14:54:40.161  INFO 9224 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'configurationValidator' with a different definition: replacing [Generic bean: class [com.interfaces.file.handler.ConfigurationValidator]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [D:\Repo\file-handler\target\classes\com\interfaces\file\handler\ConfigurationValidator.class]] with [Generic bean: class [com.interfaces.file.handler.ConfigurationValidator]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=init; destroyMethodName=null; defined in class path resource [test-file-process.xml]]
2018-09-11 14:54:40.164  INFO 9224 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'cacheManager' with a different definition: replacing [Generic bean: class [com.interfaces.file.handler.CacheManager]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [D:\Repo\file-handler\target\classes\com\interfaces\file\handler\CacheManager.class]] with [Generic bean: class [org.springframework.cache.support.SimpleCacheManager]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [test-file-process.xml]]
2018-09-11 14:54:40.167  INFO 9224 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'headerEnricher' with a different definition: replacing [Generic bean: class [com.interfaces.file.handler.HeaderEnricher]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [D:\Repo\file-handler\target\classes\com\interfaces\file\handler\HeaderEnricher.class]] with [Generic bean: class [com.interfaces.file.handler.HeaderEnricher]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [test-file-process.xml]]
2018-09-11 14:54:40.182  INFO 9224 --- [           main] .f.x.DefaultBeanDefinitionDocumentReader : Skipped XML bean definition file due to specified profiles [aws] not matching: class path resource [test-file-process.xml]
2018-09-11 14:54:40.548  INFO 9224 --- [           main] o.s.b.f.x.XmlBeanDefinitionReader        : Loading XML bean definitions from class path resource [file-process.xml]
2018-09-11 14:54:40.795  INFO 9224 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'transactionManager' with a different definition: replacing [Generic bean: class [org.springframework.integration.transaction.PseudoTransactionManager]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [test-file-process.xml]] with [Generic bean: class [org.springframework.integration.transaction.PseudoTransactionManager]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [file-process.xml]]

【问题讨论】:

  • 您可以在测试运行时分享日志输出吗?我猜想您的测试的入站通道适配器首先被定义,然后被file-process.xml 中定义的适配器覆盖。
  • 是的,正确。你能为此提供解决方案吗?已将日志附加到其覆盖的位置
  • 在下面查看我的答案。

标签: spring-boot spring-integration spring-boot-test spring-junit spring-integration-aws


【解决方案1】:

我认为&lt;file:inbound-channel-adapter&gt; 的问题实际上创建了几个bean,其中一个是FileReadingMessageSource,条件如下:

Assert.isTrue(this.directory.exists(),
            "Source directory [" + this.directory + "] does not exist.");

就在其afterPropertiesSet() 中,独立于auto-startup="false"

恐怕这个 bean 并没有被覆盖,只是因为它的 id 是自动生成的。

这就是另一个配置没有帮助的原因。

我建议你看看 profiles 支持:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-definition-profiles

然后将 &lt;file:inbound-channel-adapter&gt; 包装成类似这样的东西:

<beans:beans profile="!test">
</beans:beans>

【讨论】:

  • 尝试了将代码包装在 beans:bean profile 中的解决方案。但是在添加 bean 定义后也出现了异常。 xmlns:beans=“springframework.org/schema/beans”。异常:SaxParseException:找不到元素“bean”的声明
  • 哦!那必须是&lt;beans:beans&gt;。好吧,如果您为xmlns="http://www.springframework.org/schema/beans" 使用beans 前缀。否则只是&lt;beans profile="!test"&gt;
  • Sorry Artem...打字错误...仅尝试 .. 但发生异常。我们是否需要在 schemalocation 中添加任何版本。 xmlns="springframework.org/schema/beans/spring-beans-4.3.xsd?
  • 嗯,这个来自 Spring XML 配置的根目录。你绝对应该在你的配置中有这样一个schemaLocation。如果你不在那里使用它,你只需要重复你的配置的根标签,带有前缀或完全没有它。
  • 我提出了解决方案来简化生活:github.com/spring-projects/spring-integration/pull/2562
最近更新 更多