Apache camel camelbean组件调用@Named/@Dependent bean的缓存实例
在我们的应用程序中,我们在JBoss EAP 7.1环境中使用ApacheCamel和Apache camel camelbean组件调用@Named/@Dependent bean的缓存实例,apache-camel,Apache Camel,在我们的应用程序中,我们在JBoss EAP 7.1环境中使用ApacheCamel和Camel cdi组件。将Apache Camel升级到实际版本后,应用程序在并行执行中开始表现不正确 我发现,bean组件总是调用同一个实例。根据我的理解,对于每个CDI查找,具有@Dependent作用域的bean应该始终是新实例 我尝试了端点参数cache=false,这应该是默认值,但行为保持不变。还尝试指定@Dependent,这也应该是默认值 附加MCVE,在Apache Camel2.20.0及更
Camel cdi
组件。将Apache Camel升级到实际版本后,应用程序在并行执行中开始表现不正确
我发现,bean组件总是调用同一个实例。根据我的理解,对于每个CDI查找,具有@Dependent
作用域的bean应该始终是新实例
我尝试了端点参数cache=false
,这应该是默认值,但行为保持不变。还尝试指定@Dependent
,这也应该是默认值
附加MCVE,在Apache Camel2.20.0
及更新版本上失败。适用于2.19.5
及更早版本。完全可复制的项目
在我们的应用程序中,我能做些什么来改变这种行为并使用实际版本的ApacheCamel吗
编辑:
移除标签camel-cdi
和jboss-weld
。我创建了单元测试,以模拟这种情况,而不依赖于camel cdi和Weld。此测试包含测试JndiRegistry#lookup
的断言,该断言返回正确的实例。根据这个测试,我相信问题在于bean组件本身。版本为>=2.20.0
时失败,版本为时通过,应为单例范围。此行为是在版本2.20.0
中引入的。不要实现接口,而是将可调用方法注释为
更换
@Named
public class SomeDependentBean implements Processor {
public void process(Exchange exchange) throws Exception {
}
}
public void configure() throws Exception {
getContext().addComponent("cdi", new CdiComponent());
from("direct:in")
.to("cdi:something");
}
与
@Named
public class SomeDependentBean {
@Handler
public void process(Exchange exchange) throws Exception {
}
}
如果你们不能像我一样负担得起,因为这破坏了我们应用程序扩展的行为,我已经实现了简单的组件。此组件没有缓存,允许直接从注册表调用
处理器
CdiEndpoint类
public class CdiEndpoint extends ProcessorEndpoint {
private String beanName;
protected CdiEndpoint(String endpointUri, Component component) {
super(endpointUri, component);
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
@Override
protected void onExchange(Exchange exchange) throws Exception {
Object target = getCamelContext().getRegistry().lookupByName(beanName);
Processor processor = getCamelContext().getTypeConverter().tryConvertTo(Processor.class, target);
if (processor != null){
processor.process(exchange);
} else {
throw new RuntimeException("CDI bean "+beanName+" not found");
}
}
}
public class CdiComponent extends DefaultComponent {
@Override
protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
CdiEndpoint endpoint = new CdiEndpoint(uri, this);
endpoint.setBeanName(remaining);
return endpoint;
}
}
CDI组件类
public class CdiEndpoint extends ProcessorEndpoint {
private String beanName;
protected CdiEndpoint(String endpointUri, Component component) {
super(endpointUri, component);
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
@Override
protected void onExchange(Exchange exchange) throws Exception {
Object target = getCamelContext().getRegistry().lookupByName(beanName);
Processor processor = getCamelContext().getTypeConverter().tryConvertTo(Processor.class, target);
if (processor != null){
processor.process(exchange);
} else {
throw new RuntimeException("CDI bean "+beanName+" not found");
}
}
}
public class CdiComponent extends DefaultComponent {
@Override
protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
CdiEndpoint endpoint = new CdiEndpoint(uri, this);
endpoint.setBeanName(remaining);
return endpoint;
}
}
创建JIRA问题:您应该使用带有bean的普通POJO,或者如果您使用Camel的
处理器
,那么它的单例作用域将通过进程
EIP使用。