我正在编写一个接收Camel Exchange
的组件(端点),如下所示:
from("file|activemq|whatever").to(myEndpoint);
收到后,我希望它将交换传递给一组子程序,这些子程序可以异步工作,最终决定它们已经完成,可能在Exchange
的Out消息中组成一个响应。所有这些都可能发生在Camel Context之外,我只使用Exchange
对象。
然后我的子例程应该调用一些东西来告诉Camel它应该传回响应,根据源和中间组件要求做其他事情(例如,如果它是file:/
,重命名文件)并考虑本交易所完成的路由。
我在想我会调用Exchange
的工作done
方法。
不幸的是,我注意到Camel仍然试图在错误的时间和状态下自行结束交换。例如,对于文件源,它无法重命名已经删除的文件。
以下是我的一些代码:
这里我定义了一个端点:
_proceeder = new DefaultEndpoint() {
private final String _defaultUri = "rex:producer-" + UUID.randomUUID().toString();
@Override
protected String createEndpointUri() {
return _defaultUri;
}
@Override
public Producer createProducer() throws Exception {
return new DefaultAsyncProducer(this) {
@Override
public boolean process(final Exchange exchange1, final AsyncCallback callback) {
final ExchangeWrapper exchange = new ExchangeWrapper(_uri, exchange1, MessageSystem.this);
_LOG.debug("Got input for {}. Processing...", _uri);
exchange._taken(); // 1. all subsequent will increase by 1
/// some majick....
final boolean done = exchange._released(); // if all were released immediately, itll be 0 and sent back now. otherwise the last to release will send it back.
if (done) {
_LOG.debug("Processed input for {} synchronously", _uri);
//callback.done(true);
} else {
_LOG.debug("Processed input for {} asynchronously, awaiting response", _uri);
//exchange1.addOnCompletion(new Synchronization() {
// @Override
// public void onComplete(Exchange exchange) {
// onFailure(exchange);
// }
//
// @Override
// public void onFailure(Exchange exchange) {
// callback.done(false);
// }
//});
}
return done;
}
};
}
@Override
public Consumer createConsumer(Processor processor) throws Exception {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public boolean isSingleton() {
return true;
}
};
_proceeder.setCamelContext(context);
毋庸置疑,我不明白为什么在我的DefaultAsyncProducer.process()
方法中给出了AsyncCallback;无论我调用它的done()
方法,系统都不会看到这个并且仍然会再次结束交换。但这不是问题。
这是ExchangeWrapper _released
和_done
方法:
private void _done() throws Exception {
UnitOfWork uow = _exchange.getUnitOfWork();
uow.done(_exchange);
//try{
// uow.stop();
//}catch(Exception e){
//
//}
_exchange.setUnitOfWork(null);
}
private boolean _released() {
final boolean ret;
final int cnt;
final int trancnt;
synchronized (_exchange) {
cnt = _exchange.getProperty("rex.takenCount", Integer.class) - 1;
_exchange.setProperty("rex.takenCount", cnt);
trancnt = _exchange.getProperty("rex.takenAsTransient", Integer.class);
}
if (_LOG.isDebugEnabled()) {
_LOG.debug("Input for {} released. {} times left, {} transient", new Object[]{_exchange.getProperty("rex.uri", String.class), cnt, trancnt});
}
if (cnt <= 0 || cnt <= trancnt) {
if (_LOG.isDebugEnabled()) {
_LOG.debug("Message for {} is processed by all non-transient receivers. Setting done...", new Object[]{_exchange.getProperty("rex.uri", String.class)});
}
_done();
ret = true;
if (_LOG.isDebugEnabled()) {
_LOG.debug("Message for {} is set done", new Object[]{_exchange.getProperty("rex.uri", String.class)});
}
} else {
ret = false;
}
return ret;
}
所以基本上我将Exchange
包装起来以保持状态并决定何时停止处理。
在深入了解Camel内部结构时,我看到了一些类似的计数器,可以跟踪Exchange
处理的次数,但是我想控制它,因此我自己的包装器。
那么我该怎么称呼而不是
_exchange.getUnitOfWork().done(_exchange);
告诉Camel内部处理器和其他人没有必要标记交换,因为我这样做了吗?
我的最新发现是打电话给uow.stop();
,以便它清除所有'后'处理器等,但我突然明白我可能会尝试自己攻击骆驼很长一段时间,但最好还是问一下那些人没有尝试和猜测就知道该做什么。
这些是我的路线的例子:
RouteBuilder rb = new RouteBuilder(_context) {
@Override
public void configure() throws Exception {
if (_tokenizer != null) {
from(_uri).split().method(_tokenizer, "tokenizeReader").streaming().to(_proceeder);
} else {
from(_uri).to(_proceeder);
}
}
};
如果我可以避免构建路由,实例化端点和生产者,以及使用独立处理器,我很乐意这样做,但我不想抛弃奇妙的Camel项目在拆分,流式传输,编组方面所提供的功能。等等;所有这些似乎都建立在路线上。
答案 0 :(得分:0)