Apache Camel CXF 端点空回复
Apache Camel CXF endpoint null reply
我按照 Camel in Action 书的第 7 章实现了 CXF 路线。
<cxf:cxfEndpoint
id="orderEndpoint"
address="http://localhost:9000/order/"
serviceClass="test.order.OrderEndpoint"
wsdlURL="wsdl/order.wsdl" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<!-- Expose route as web service endpoint -->
<from uri="cxf:bean:orderEndpoint" />
<to uri="log:orderEndpoint_MsgIn" />
<to uri="seda:incomingOrders" />
<transform>
<constant>OK</constant>
</transform>
<to uri="log:orderEndpoint_MsgOut" />
</route>
<!-- test route -->
<route>
<from uri="seda:incomingOrders" />
<to uri="mock:end" />
</route>
</camelContext>
然后我实现了一个java控制台class来测试路由
public static void main(String[] args) throws Exception{
Main main = new Main();
AbstractApplicationContext context = new ClassPathXmlApplicationContext(
"META-INF/spring/cxfWsComponentTestContext.xml"
);
main.setApplicationContext(context);
main.start();
ProducerTemplate producer = main.getCamelTemplate();
List<Object> params = new ArrayList<Object>();
params.add("motor");
params.add(1);
params.add("honda");
String reply = producer.requestBody("cxf:bean:orderEndpoint", params, String.class);
LOG.info("Received reply from orderEndpoint = " + reply);
Thread.sleep(10000);
main.stop();
}
预计控制台日志应显示
"Received reply from orderEndpoint = OK"
然而,我得到了
"Received reply from orderEndpoint = null"
在控制台日志中我可以看到条目
"orderEndpoint_MsgOut INFO Exchange[ExchangePattern: InOut, BodyType: String, Body: OK]"
这意味着 Web 服务应该已经生成了回复消息 "OK",但我不确定为什么这个回复消息没有作为 requestBody() 方法的 return 值继续存在打电话...
我下载了 Camel in Action 第 7 章的示例代码和 运行 Junit 测试用例,它能够 return 结果符合预期...我尝试比较路由定义和源代码与我的代码,但到目前为止无法发现任何差异...
想看看是否有人可以提供一些线索。
--- 编辑 1 ---
我更新了路由定义,只保留如下路由
<route>
<from uri="cxf:bean:orderEndpoint" />
<transform>
<constant>OK</constant>
</transform>
<to uri="seda:incomingOrders" />
</route>
并更新了主要方法
producer.requestBody("cxf:bean:orderEndpoint", params, String.class);
ConsumerTemplate consumer = producer.getCamelContext().createConsumerTemplate();
Exchange reply = consumer.receive("seda:incomingOrders");
LOG.info("Received reply from seda:incomingOrders = " + reply);
然而,它因超时异常而失败
org.apache.camel.ExchangeTimedOutException: The OUT message was not received within: 30000 millis. Exchange[Message: OK]
at org.apache.camel.component.seda.SedaProducer.process(SedaProducer.java:144)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:129)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:448)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:118)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:80)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.component.cxf.CxfConsumer.asyncInvoke(CxfConsumer.java:95)
at org.apache.camel.component.cxf.CxfConsumer.invoke(CxfConsumer.java:75)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.run(ServiceInvokerInterceptor.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.run(ServiceInvokerInterceptor.java:126)
at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:131)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:251)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:234)
at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:70)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1129)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1065)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:497)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
at org.eclipse.jetty.io.AbstractConnection.run(AbstractConnection.java:540)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)
您正在请求 CXF 端点的正文。如果您查看您的路线,您会发现您在路线定义之后的转换标记中设置了正文的内容。因此,您因 requestBody()
而无法正常工作是合乎逻辑的。这同样适用于您的 seda 端点。我敢打赌 orderEndpoint_MsgIn
的 Logged 正文与 OK 不同。
关于您在 orderEndpoint_MsgOut
处的日志是正确的,这是因为您在转换步骤之后记录了正文。
为了收到OK,可以使用这条路线:
<route>
<from uri="cxf:bean:orderEndpoint" />
<transform>
<constant>OK</constant>
</transform>
<wireTap uri="seda:incomingOrders" />
</route>
并使用 ConsumerTemplate
和 seda 端点:
ConsumerTemplate consumer = producer.getCamelContext().createConsumerTemplate();
String reply = consumer.receive("seda:incomingOrders");
LOG.info("Received reply from seda = " + reply);
您应该在 requestBody()
和 main.stop()
之间使用此代码。
有关使用 wireTap
而不是 to
的解释,请参阅此 post
我按照 Camel in Action 书的第 7 章实现了 CXF 路线。
<cxf:cxfEndpoint
id="orderEndpoint"
address="http://localhost:9000/order/"
serviceClass="test.order.OrderEndpoint"
wsdlURL="wsdl/order.wsdl" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<!-- Expose route as web service endpoint -->
<from uri="cxf:bean:orderEndpoint" />
<to uri="log:orderEndpoint_MsgIn" />
<to uri="seda:incomingOrders" />
<transform>
<constant>OK</constant>
</transform>
<to uri="log:orderEndpoint_MsgOut" />
</route>
<!-- test route -->
<route>
<from uri="seda:incomingOrders" />
<to uri="mock:end" />
</route>
</camelContext>
然后我实现了一个java控制台class来测试路由
public static void main(String[] args) throws Exception{
Main main = new Main();
AbstractApplicationContext context = new ClassPathXmlApplicationContext(
"META-INF/spring/cxfWsComponentTestContext.xml"
);
main.setApplicationContext(context);
main.start();
ProducerTemplate producer = main.getCamelTemplate();
List<Object> params = new ArrayList<Object>();
params.add("motor");
params.add(1);
params.add("honda");
String reply = producer.requestBody("cxf:bean:orderEndpoint", params, String.class);
LOG.info("Received reply from orderEndpoint = " + reply);
Thread.sleep(10000);
main.stop();
}
预计控制台日志应显示
"Received reply from orderEndpoint = OK"
然而,我得到了
"Received reply from orderEndpoint = null"
在控制台日志中我可以看到条目
"orderEndpoint_MsgOut INFO Exchange[ExchangePattern: InOut, BodyType: String, Body: OK]"
这意味着 Web 服务应该已经生成了回复消息 "OK",但我不确定为什么这个回复消息没有作为 requestBody() 方法的 return 值继续存在打电话...
我下载了 Camel in Action 第 7 章的示例代码和 运行 Junit 测试用例,它能够 return 结果符合预期...我尝试比较路由定义和源代码与我的代码,但到目前为止无法发现任何差异...
想看看是否有人可以提供一些线索。
--- 编辑 1 ---
我更新了路由定义,只保留如下路由
<route>
<from uri="cxf:bean:orderEndpoint" />
<transform>
<constant>OK</constant>
</transform>
<to uri="seda:incomingOrders" />
</route>
并更新了主要方法
producer.requestBody("cxf:bean:orderEndpoint", params, String.class);
ConsumerTemplate consumer = producer.getCamelContext().createConsumerTemplate();
Exchange reply = consumer.receive("seda:incomingOrders");
LOG.info("Received reply from seda:incomingOrders = " + reply);
然而,它因超时异常而失败
org.apache.camel.ExchangeTimedOutException: The OUT message was not received within: 30000 millis. Exchange[Message: OK]
at org.apache.camel.component.seda.SedaProducer.process(SedaProducer.java:144)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:129)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:448)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:118)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:80)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.component.cxf.CxfConsumer.asyncInvoke(CxfConsumer.java:95)
at org.apache.camel.component.cxf.CxfConsumer.invoke(CxfConsumer.java:75)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.run(ServiceInvokerInterceptor.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.run(ServiceInvokerInterceptor.java:126)
at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:131)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:251)
at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:234)
at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:70)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1129)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1065)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:497)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
at org.eclipse.jetty.io.AbstractConnection.run(AbstractConnection.java:540)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)
您正在请求 CXF 端点的正文。如果您查看您的路线,您会发现您在路线定义之后的转换标记中设置了正文的内容。因此,您因 requestBody()
而无法正常工作是合乎逻辑的。这同样适用于您的 seda 端点。我敢打赌 orderEndpoint_MsgIn
的 Logged 正文与 OK 不同。
关于您在 orderEndpoint_MsgOut
处的日志是正确的,这是因为您在转换步骤之后记录了正文。
为了收到OK,可以使用这条路线:
<route>
<from uri="cxf:bean:orderEndpoint" />
<transform>
<constant>OK</constant>
</transform>
<wireTap uri="seda:incomingOrders" />
</route>
并使用 ConsumerTemplate
和 seda 端点:
ConsumerTemplate consumer = producer.getCamelContext().createConsumerTemplate();
String reply = consumer.receive("seda:incomingOrders");
LOG.info("Received reply from seda = " + reply);
您应该在 requestBody()
和 main.stop()
之间使用此代码。
有关使用 wireTap
而不是 to
的解释,请参阅此 post