我必须创建一个发布/订阅客户端。 因此,此客户端需要在启动时发送注册调用,之后才会侦听已发布的更新。发布者是第三方软件,只能通过TCP / IP进行通信,因此使用JMS是没有选择的。
我的第一个想法是创建两条路线,一条用于发送请求,另一条用于接收结果。
// configure clientMode
String rtServerUri = "netty4:tcp://localhost:30600?clientMode=true&decoders=#length-decoder,#string-decoder&encoders=#length-encoder,#string-encoder";
from("quartz://gs/provider?trigger.repeatInterval=15000&trigger.repeatCount=-1")
.process(exchange -> System.out.println("Trigger registration!"))
.setBody(constant(registrationBody))
.to(ExchangePattern.OutOnly, rtServerUri)
;
from(rtServerUri)
.process(exchange -> System.out.println("Incoming message!"))
.to("file:test/output?fileName=updates.xml&fileExist=Append")
;
不幸的是,这不起作用,因为建立了两个独立的连接:
有没有人有想法,如何解决这个问题?
答案 0 :(得分:0)
你是对的,你需要两条路线。但是你不需要同时创建两者。你可以做的是禁用第二条路线,这样它就不会自动启动。然后,一旦第一条路线实际发送了消息,它将触发对第二条路线的呼叫启动。你将有两个我认为不是问题的联系。您只需要在发送注册呼叫后启动监听器。
答案 1 :(得分:0)
我找到了一种似乎对我有用的方法。
解决方案是创建一个扩展NettyComponent的自定义组件。 相应的端点将引用已使用的侦听器通道(Consumer)。
@Override
protected void doStart() throws Exception
{
super.doStart();
Field nettyServerBootstrapFactory = GsPblConsumer.class.getSuperclass().getDeclaredField("nettyServerBootstrapFactory");
nettyServerBootstrapFactory.setAccessible(true);
Object nsbf = nettyServerBootstrapFactory.get(this);
Field channel = nsbf.getClass().getDeclaredField("channel");
channel.setAccessible(true);
channelToShare = (Channel) channel.get(nsbf);
getEndpoint().setSharedChannel(channelToShare);
}
此频道将用于制作人发送消息。
@Override
public boolean process(Exchange exchange, AsyncCallback callback)
{
...
// get a channel from the pool
Channel existing;
try {
if (getConfiguration().isShareChannel() && getEndpoint().hasChannelToShare())
existing = getEndpoint().getSharedChannel();
else
existing = pool.borrowObject();
if (existing != null) {
LOG.trace("Got channel from pool {}", existing);
}
} catch (Exception e) {
exchange.setException(e);
callback.done(true);
return true;
}
...
}
如果有人知道更好的解决方案,请告诉我。
在第一个路由发送请求之后,outOnly将在侦听器处理结果消息后停止。
public class DisableRegisterRoutePolicy extends RoutePolicySupport
{
@Override
public void onExchangeDone(Route route, Exchange exchange)
{
CamelContext camelContext = exchange.getContext();
Iterator<InflightRepository.InflightExchange> iterator = camelContext.getInflightRepository().browse().iterator();
while (iterator.hasNext()) {
InflightRepository.InflightExchange inflight = iterator.next();
String id = inflight.getExchange().getExchangeId();
camelContext.getInflightRepository().remove(inflight.getExchange());
}
Route regRoute = camelContext.getRoute("gs-registration-route");
try
{
camelContext.stopRoute(regRoute.getId());
} catch (Exception e)
{
e.printStackTrace();
}
}
}
更多细节可以在这里找到:http://camel.465427.n5.nabble.com/publish-subscribe-with-camel-netty4-tp5801431.html
谢谢, Jörg