在我们的应用程序中,我们在camel-cdi EAP7.1环境中使用带有JBoss组件的Apache。在Apache升级到实际版本之后,应用程序开始在并行执行中不正确地运行。
我发现,bean组件总是调用同一个实例。据我理解,带@Dependent作用域的bean应该始终是每个CDI查找的新实例。
我尝试过端点参数cache=false,它应该是默认的,但是行为保持不变。还尝试指定@Dependent,这也应该是默认的。
附加MCVE,在Apache 2.20.0和更新程序上失败。在2.19.5和更高版本中工作得很好。完全可复制的项目论吉乌布。
@ApplicationScoped
@Startup
@ContextName("cdi-context")
public class MainRouteBuilder extends RouteBuilder {
public void configure() throws Exception {
from("timer:test")
.to("bean:someDependentBean?cache=false");
}
}
@Named
//@Dependent //Dependent is default
public class SomeDependentBean implements Processor {
private int numOfInvocations = 0;
private static Logger log = LoggerFactory.getLogger(SomeDependentBean.class);
public void process(Exchange exchange) throws Exception {
log.info("This is: "+toString());
numOfInvocations++;
if (numOfInvocations!=1){
throw new IllegalStateException(numOfInvocations+"!=1");
} else {
log.info("OK");
}
}
}在我们的应用程序中,我能做些什么来改变这种行为并使用Apache的实际版本吗?
编辑:
删除标记camel-cdi和jboss-weld。我创建了单元测试,以模拟这种情况,而不依赖于camel-cdi和Weld。此测试包含用于测试JndiRegistry#lookup的断言,该断言返回正确的实例。根据这个测试,我认为问题在于bean组件本身。使用版本>=2.20.0失败,并与<=2.19.5传递
public class CamelDependentTest extends CamelTestSupport {
private Context context;
private JndiRegistry registry;
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:in")
.to("bean:something?cache=false");
}
};
}
@Override
protected JndiRegistry createRegistry() throws Exception {
JndiRegistry registry = super.createRegistry();
registry.bind("something", new SomeDependentBean());
this.context = registry.getContext();
this.registry = registry;
return registry;
}
@Test
public void testFreshBeanInContext() throws Exception{
SomeDependentBean originalInstance = registry.lookup("something", SomeDependentBean.class);
template.sendBody("direct:in",null);
context.unbind("something");
context.bind("something", new SomeDependentBean()); //Bind new instance to Context
Assert.assertNotSame(registry.lookup("something"), originalInstance); //Passes, the issue is not in JndiRegistry.
template.sendBody("direct:in",null); //fails, uses cached instance of SameDependentBean
}
}发布于 2018-07-08 11:05:24
根据骆驼-12610的说法,Processor应该是单例范围。这种行为是在版本2.20.0中引入的。不要实现Processor接口,而是将可调用方法注释为@Handler。
取代
@Named
public class SomeDependentBean implements Processor {
public void process(Exchange exchange) throws Exception {
}
}与
@Named
public class SomeDependentBean {
@Handler
public void process(Exchange exchange) throws Exception {
}
}如果你不能像我这样,因为它破坏了我们的应用程序扩展的行为,我已经实现了简单的组件。这个组件没有缓存,允许直接从注册表调用Processor。
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");
}
}
}CdiComponent类
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;
}
}使用
public void configure() throws Exception {
getContext().addComponent("cdi", new CdiComponent());
from("direct:in")
.to("cdi:something");
}https://stackoverflow.com/questions/51108913
复制相似问题