Java Camel:如何根据配置有条件地构建路由?
我有一个Java Camel:如何根据配置有条件地构建路由?,java,spring,apache-camel,Java,Spring,Apache Camel,我有一个RouteBuilder子类,用于设置骆驼路线。它是由春天建造的。最初看起来是这样的: @Override public void configure() throws Exception { from(...) .process(...) .to(...) } 我想做的是根据配置添加一个额外的端点路由。Spring使用一个属性文件来创建RouteBuilderbean,它设置的一个字段是boolean addAnotherEndpoint。如果此布尔值为真,我
RouteBuilder
子类,用于设置骆驼路线。它是由春天建造的。最初看起来是这样的:
@Override
public void configure() throws Exception {
from(...)
.process(...)
.to(...)
}
我想做的是根据配置添加一个额外的端点路由。Spring使用一个属性文件来创建RouteBuilder
bean,它设置的一个字段是boolean addAnotherEndpoint
。如果此布尔值为真,我想向添加另一个。如果它是假的,我希望它回到目前的行为。所以我把它改成:
@Override
public void configure() throws Exception {
from(...)
.process(...)
.to(...)
.choice()
when(constant(addAnotherEndpoint)).to(...)
.endChoice();
}
虽然这似乎具有所需的行为,但我在为其编写单元测试时遇到了问题(因为它从属性文件中提取addAnotherEndpoint
的值,即使我试图在测试中覆盖它)。有没有更好的处理方法?我目前的方法会有任何意外的副作用吗
编辑:
我正在使用CamelSpringTestSupport
子类(使用JUnit测试)进行测试。在@Before
方法中,我创建了一个AdviceWithRouteBuilder
,它用mock替换所有端点。在我的@Test
中,我试图覆盖从属性文件中获取的addAnotherEndpoint
的值:
@Test
public void testConditionalRouting() throws Exception {
context.start();
MyRouteBuilder routeBuilder = (MyRouteBuilder) applicationContext.getBean("myRouteBuilder");
routeBuilder.setAddAnotherEndpoint(true);
getMockEndpoint("myMockEndpoint").expectedMessageCount(1);
sendMockMessage();
assertMockEndpointsSatisfied();
context.stop();
}
有一个相应的测试将addAnotherEndpoint
设置为false
,并断言收到了0条消息。问题是重写此变量的值似乎不起作用。一个测试通过,另一个测试失败,这取决于我的属性文件是否说明该值应为true
或false
。这对我来说意味着路由是在覆盖设置之前构造的(因此也是在上下文启动之前)。我签入了调试器,设置被正确覆盖。这似乎没有任何影响
编辑2:
从我对RouteBuilder的建议中:
@Override
public void configure() throws Exception {
replaceFromWith(MOCK_FROM_ENDPOINT);
interceptSendToEndpoint(FIRST_TO_ENDPOINT)
.skipSendToOriginalEndpoint().to(MOCK_FIRST_TO_ENDPOINT);
weaveById(MY_PROCESSOR_ENDPOINT).replace()
.to(MOCK_MY_PROCESSOR_ENDPOINT);
weaveById(SECOND_TO_ENDPOINT).replace()
.to(MOCK_SECOND_TO_ENDPOINT);
}
这将使用模拟端点替换每个EIP。我有4个测试依赖于这些,它们似乎按照预期工作,唯一的问题是条件路由
除了JUnit注释外,我的测试类上唯一的注释是isUseAdviceWith()
(返回true)上的@Override
,以及createApplicationContext()
,它返回一个新的Spring应用程序上下文
我在没有context.start()
的情况下运行了测试,唯一通过的测试是断言收到了0条消息的测试(如果路由没有启动,这是有意义的)。因此,我不认为上下文是自动启动的。以下是最终起作用的内容:
我的测试很好,但我不得不重新思考我是如何建立我的路线的。发生的事情发生在创建Spring上下文时,路线正在构建中。它当时检查了addAnotherEndpoint
的值,并根据该值设置常量。但是boolean
是一个基本值,这意味着它是通过值传递的。为什么这很重要?因为constant()
函数只是根据构建路由时该常量的值来设置路由。后来通过Spring对其进行更改没有影响,因为该值已经被读取。我需要做的是让它以谓词的形式传递一个对象,这样我以后就可以将同一个对象作为bean进行操作
此外,我还按照建议将choice()
更改为filter()
。这是成品:
@Override
public void configure() throws Exception {
from(...)
.process(...)
.to(...)
.choice()
when(myBooleanPredicate).to(...)
.endChoice();
}
我的自定义谓词可以通过Spring进行操作:
public class BooleanPredicate implements Predicate {
private boolean value;
@Override
public boolean matches(Exchange exchange) {
return value;
}
public void setValue(boolean value) {
this.value = value;
}
此布尔谓词
的内部值
设置为addAnotherPredicate
。每次运行路由时都会重新读取它,因为布尔谓词
是通过引用传递的。我刚刚发现
.when(exchange-> foo()==true)
足够了。我觉得这是一条非常正常的路线。我想唯一的问题是你测试它的方式。在现场环境中,这条路线应该可以。你能分享一下你是如何测试它的吗?然后我们也可以解决这个问题。顺便说一句,如果你使用一个过滤器,而不是只有一个条件的选择,会更简单。谢谢你的建议。我正在使用CamelSpringTestSupport
子类来测试它。我将更新此问题以包含此内容。我还可以看看您对RouteBuilder block的建议吗?另外,您的测试类是否有任何注释?还可以删除context.start();从测试开始,运行它们以查看上下文是否自动启动?如果是这样,问题就在那里…再次更新问题。您在那里做了很好的分析。如果不是我,我相信其他人会帮你的。在您做出选择之前,如果您记录addanTheEndpoint,您会看到什么?因为这是我唯一没有解决的问题,你能告诉我你是如何覆盖这个属性的吗?