Apache Camel CXF 在更新元素列表时难以调用 RPC/Encoded WSDL
Apache Camel CXF difficulty calling an RPC/Encoded WSDL when updating list of elements
虽然没有官方支持,但通过对 WSDL 的一些小修改,我能够成功地为 WSDL 生成 CXF 对象,并让 Camel CXF 与 RPC/Encoded WSDL 端点对话。代码非常简单,大多数 request/responses 工作没有问题,除了尝试发送元素列表的更新。以下是服务的预期:
<elements arrayType="UpdateElement">
VS 这是正在发送的内容:
<elements>
我需要将 arrayType 添加到传出消息中。我研究了多种方法:
1) CXF 发送 SOAP 消息之前的拦截器,然后使用 XPath 添加元素,但我不清楚如何使用 Apache Camel + Camel CXF 完成此操作。如何从 Camel 上下文中检索 CXF 客户端?
MyService client = ???
2) 通过 WSDL 修复它?是否可以将此元素添加到 WSDL,以便它作为 CXF 对象的一部分生成?目前是这样定义的:
<message name="wsdlElementRequest">
<part name="elements" type="tns:UpdateElements" /></message>
'message' 和 'part' 来自 http://schemas.xmlsoap.org/wsdl/.
如有任何想法或建议,我们将不胜感激。谢谢!
万一有人遇到类似问题,我自己解决了。我能够通过 CamelContext 检索 CxfEndpoint:
camelContext.getEndpoint(endpointUrl, CxfEndpoint.class);
然后我可以添加我创建的拦截器:
public class MyCxfInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
...
使用 CxfEndpoint 方法:
cxfEndpoint.getOutInterceptors().add(new MyCxfInterceptor());
在我的拦截器中,我还合并了另一个拦截器 SAAJOutInterceptor,它将 SOAP 转换为易于使用的对象:
private List<PhaseInterceptor<? extends Message>> extras = new ArrayList<>(1);
public MyCxfInterceptor() {
super(Phase.USER_PROTOCOL);
extras.add(new SAAJOutInterceptor());
}
public Collection<PhaseInterceptor<? extends Message>> getAdditionalInterceptors() {
return extras;
}
使用 SOAP 消息的简单方法:
@Override
public void handleMessage(SoapMessage soapMessage) throws Fault {
SOAPMessage msg = soapMessage.getContent(SOAPMessage.class);
try {
SOAPBody soapBody = msg.getSOAPBody();
然后使用 XPATH 对传出的 SOAP 消息进行更正是一件简单的事情。
private XPath xpath = XPathFactory.newInstance().newXPath();
...
NodeList nodeList = soapBody.getElementsByTagName("tagName");
for (int x = 0; x < nodeList.getLength(); x++) {
Node node = nodeList.item(x);
((Element) node).setAttribute("missingAttributeName", "missingAttributeValue");
}
我希望这对使用具有挑战性的 SOAP 服务的任何人有所帮助!
感谢博客,它在使我能够实施此解决方案方面发挥了重要作用:https://xceptionale.wordpress.com/2016/06/26/message-interceptor-to-modify-outbound-soap-request/
虽然没有官方支持,但通过对 WSDL 的一些小修改,我能够成功地为 WSDL 生成 CXF 对象,并让 Camel CXF 与 RPC/Encoded WSDL 端点对话。代码非常简单,大多数 request/responses 工作没有问题,除了尝试发送元素列表的更新。以下是服务的预期:
<elements arrayType="UpdateElement">
VS 这是正在发送的内容:
<elements>
我需要将 arrayType 添加到传出消息中。我研究了多种方法:
1) CXF 发送 SOAP 消息之前的拦截器,然后使用 XPath 添加元素,但我不清楚如何使用 Apache Camel + Camel CXF 完成此操作。如何从 Camel 上下文中检索 CXF 客户端?
MyService client = ???
2) 通过 WSDL 修复它?是否可以将此元素添加到 WSDL,以便它作为 CXF 对象的一部分生成?目前是这样定义的:
<message name="wsdlElementRequest">
<part name="elements" type="tns:UpdateElements" /></message>
'message' 和 'part' 来自 http://schemas.xmlsoap.org/wsdl/.
如有任何想法或建议,我们将不胜感激。谢谢!
万一有人遇到类似问题,我自己解决了。我能够通过 CamelContext 检索 CxfEndpoint:
camelContext.getEndpoint(endpointUrl, CxfEndpoint.class);
然后我可以添加我创建的拦截器:
public class MyCxfInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
...
使用 CxfEndpoint 方法:
cxfEndpoint.getOutInterceptors().add(new MyCxfInterceptor());
在我的拦截器中,我还合并了另一个拦截器 SAAJOutInterceptor,它将 SOAP 转换为易于使用的对象:
private List<PhaseInterceptor<? extends Message>> extras = new ArrayList<>(1);
public MyCxfInterceptor() {
super(Phase.USER_PROTOCOL);
extras.add(new SAAJOutInterceptor());
}
public Collection<PhaseInterceptor<? extends Message>> getAdditionalInterceptors() {
return extras;
}
使用 SOAP 消息的简单方法:
@Override
public void handleMessage(SoapMessage soapMessage) throws Fault {
SOAPMessage msg = soapMessage.getContent(SOAPMessage.class);
try {
SOAPBody soapBody = msg.getSOAPBody();
然后使用 XPATH 对传出的 SOAP 消息进行更正是一件简单的事情。
private XPath xpath = XPathFactory.newInstance().newXPath();
...
NodeList nodeList = soapBody.getElementsByTagName("tagName");
for (int x = 0; x < nodeList.getLength(); x++) {
Node node = nodeList.item(x);
((Element) node).setAttribute("missingAttributeName", "missingAttributeValue");
}
我希望这对使用具有挑战性的 SOAP 服务的任何人有所帮助!
感谢博客,它在使我能够实施此解决方案方面发挥了重要作用:https://xceptionale.wordpress.com/2016/06/26/message-interceptor-to-modify-outbound-soap-request/