当前位置: 首页 > 知识库问答 >
问题:

在将CXF与Apache Camel一起使用时,如何设置WS-Addressing MessageId标头?

隆功
2023-03-14

我正在调用一个需要WS-Addressing SOAP头的web服务。我使用Apache Camel和CXF来调用web服务。当我用web服务的WSDL配置CXFendpoint时,自动添加WS-addressing-SOAP头已经足够聪明了,但我需要设置一个自定义MessageId。

以下是当前正在发送的消息:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
    <soap:Header>
        <ws:international xmlns:ws="http://www.w3.org/2005/09/ws-i18n">
            <ws:locale xmlns:ws="http://www.w3.org/2005/09/ws-i18n">en_CA</ws:locale>
        </ws:international>
        <fram:user wsa:IsReferenceParameter="true" xmlns:fram="http://wsbo.webservice.ephs.pdc.ibm.com/Framework/" xmlns:wsa="http://www.w3.org/2005/08/addressing">BESTSystem</fram:user>
        <Action soap:mustUnderstand="true" xmlns="http://www.w3.org/2005/08/addressing">http://webservice.ephs.pdc.ibm.com/Client/QueryHumanSubjects</Action>
        <MessageID soap:mustUnderstand="true" xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:945cfd10-9fd2-48f9-80b4-ac1b9f3293c6</MessageID>
        <To soap:mustUnderstand="true" xmlns="http://www.w3.org/2005/08/addressing">https://panweb5.panorama.gov.bc.ca:8081/ClientWebServicesWeb/ClientProvider</To>
        <ReplyTo soap:mustUnderstand="true" xmlns="http://www.w3.org/2005/08/addressing">
            <Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
        </ReplyTo>
    </soap:Header>
    <soap:Body>
        <ns2:queryHumanSubjectsRequest xmlns:ns2="http://wsbo.webservice.ephs.pdc.ibm.com/Client/" xmlns:ns3="http://wsbo.webservice.ephs.pdc.ibm.com/FamilyHealth/">
            <!-- stuff -->
        </ns2:queryHumanSubjectsRequest>
    </soap:Body>
</soap:Envelope>

如您所见,MessageId值为“urn: uuid: 945cfd10-9fd2-48f9-80b4-ac1b9f3293c6”。我需要设置一个自定义值。

我尝试添加MessageId头,就像添加其他头(如“international”和“user”)一样,但框架的某些部分覆盖了该值。

// Note this doesn't work! Something overrides the value. It works for other headers.
@Override
public void process(Exchange exchange) throws Exception {

    Message in = exchange.getIn();
    List<SoapHeader> headers = CastUtils.cast((List<?>) in.getHeader(Header.HEADER_LIST));

    SOAPFactory sf = SOAPFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
    QName MESSAGE_ID_HEADER = new QName("http://www.w3.org/2005/08/addressing", "MessageID", "wsa");
    SOAPElement messageId = sf.createElement(MESSAGE_ID_HEADER);
    messageId.setTextContent("customValue");
    SoapHeader soapHeader = new SoapHeader(MESSAGE_ID_HEADER, messageId);
    headers.add(soapHeader);
}

CXF网站有一些关于如何设置WS-寻址标头的留档,但我没有看到如何将其应用于Apache Camel。Apache Camel CXF留档也没有特别提到WS-寻址。

共有2个答案

姬正文
2023-03-14

如果您的问题没有解决,我建议您将您的cxf服务与自定义拦截器相结合。它很容易处理您的肥皂消息。像这样:

<bean id="TAXWSS4JOutInterceptorBean" name="TAXWSS4JOutInterceptorBean" class="com.javainuse.beans.SetDetailAnswerInterceptor " />
<cxf:cxfEndpoint id="CXFTest" address="/javainuse/learn"
                 endpointName="a:SOATestEndpoint" serviceName="a:SOATestEndpointService"
                 serviceClass="com.javainuse.SOATestEndpoint"
                 xmlns:a ="http://javainuse.com">
    <cxf:binding>
        <soap:soapBinding mtomEnabled="false" version="1.2" />
    </cxf:binding>

    <cxf:features>
        <wsa:addressing  xmlns:wsa="http://cxf.apache.org/ws/addressing"/>
    </cxf:features>
    <cxf:inInterceptors>

        <ref bean="TAXWSS4JInInterceptorBean" />            

    </cxf:inInterceptors>
    <cxf:inFaultInterceptors>

    </cxf:inFaultInterceptors>
    <cxf:outInterceptors>
        <ref bean="TAXWSS4JOutInterceptorBean" />
    </cxf:outInterceptors>
    <cxf:outFaultInterceptors>

    </cxf:outFaultInterceptors>
</cxf:cxfEndpoint>

在拦截器中,可以如下设置soap头:

public class SetDetailAnswerInterceptor extends WSS4JOutInterceptor {

public SetDetailAnswerInterceptor() {

}

@Override
public void handleMessage(SoapMessage mc) {
    AttributedURIType value = new AttributedURIType();
    value.setValue("test");
    ((AddressingProperties) mc.get("javax.xml.ws.addressing.context.outbound")).setMessageID(value);
}
}
程和畅
2023-03-14

您发布的留档链接实际上确实包含您需要的信息,尽管如何将其应用于Camel还不清楚。

CXF文档说明:

CXForg.apache.cxf.ws.addressing.impl.AddressingProperty tiesImpl对象可用于控制WS-Addting的许多方面,包括回复:

AddressingProperties maps = new AddressingPropertiesImpl();
EndpointReferenceType ref = new EndpointReferenceType();
AttributedURIType add = new AttributedURIType();
add.setValue("http://localhost:9090/decoupled_endpoint");
ref.setAddress(add);
maps.setReplyTo(ref);
maps.setFaultTo(ref);
((BindingProvider)port).getRequestContext()
        .put("javax.xml.ws.addressing.context", maps);

请注意,它在“RequestContext”上设置寻址属性。

Apache Camel文档指出:

如何传播camel-cxfendpoint的请求和响应上下文

CXF客户端API提供了一种使用请求和响应上下文调用操作的方法。如果您使用camel-cxfendpoint生产者调用外部Web服务,您可以使用以下代码设置请求上下文并获取响应上下文:

CxfExchange exchange = (CxfExchange)template.send(getJaxwsEndpointUri(), new Processor() {
    public void process(final Exchange exchange) {
        final List<String> params = new ArrayList<String>();
        params.add(TEST_MESSAGE);
        // Set the request context to the inMessage
        Map<String, Object> requestContext = new HashMap<String, Object>();
        requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, JAXWS_SERVER_ADDRESS);
        exchange.getIn().setBody(params);
        exchange.getIn().setHeader(Client.REQUEST_CONTEXT , requestContext);
        exchange.getIn().setHeader(CxfConstants.OPERATION_NAME, GREET_ME_OPERATION);
    }
});

上面的示例有一些我们不需要的东西,但重要的是它向我们展示了如何设置CXF请求上下文。

把它们放在一起,你会得到:

java prettyprint-override">@Override
public void process(Exchange exchange) throws Exception {
    AttributedURIType messageIDAttr = new AttributedURIType();
    messageIDAttr.setValue("customValue");

    AddressingProperties maps = new AddressingProperties();
    maps.setMessageID(messageIDAttr);

    Map<String, Object> requestContext = new HashMap<>();
    requestContext.put(JAXWSAConstants.CLIENT_ADDRESSING_PROPERTIES, maps);
    exchange.getIn().setHeader(Client.REQUEST_CONTEXT, requestContext);
}

// org.apache.cxf.ws.addressing.JAXWSAConstants.CLIENT_ADDRESSING_PROPERTIES = "javax.xml.ws.addressing.context"
// org.apache.cxf.endpoint.Client.REQUEST_CONTEXT = "RequestContext"

警告:在我的路径中,我按顺序调用多个不同的web服务。我发现,在如上所示设置RequestContext之后,Camel开始对所有web服务使用相同的RequestContext,这导致了一个错误:“表示消息寻址属性的标头无效,无法处理消息”。这是因为在第一次调用之后,所有web服务调用都使用了错误的“Action”头。

我使用“RequestContext”交换属性将其追溯到Apache Camel,该属性与我们设置的头分开,显然优先于头。如果在调用后续web服务之前删除此属性,CXF会自动填写正确的操作标头。

 类似资料:
  • 我尝试使用“契约优先”模式为现有的web服务构建一个基于CXF的客户端应用程序。 XSD 非常复杂,所以我正在寻找一种利用 SDO 的方法,避免为 WSDL 生成代码。WSDL2贾瓦工具可以创建20K线类。我已经在 IBM WebSphere ESB 中使用了 SDO,我希望我能重用我以前的代码。 我找不到用CXF做这件事的方法,只有这个:http://cxf.apache.org/docs/sd

  • 我有一个问题:我们正在尝试用Apache CXF实现WS-Addressing。我可以设置一些标题,如to或Action,但无法设置其他标题,如From、ReplyTo或FaultTo。 有人知道怎么做吗?

  • 我正在使用apache camel cxf开发一个Web服务(肥皂),我遇到了这个错误。 Java . lang . illegalargumentexception:Part { http://blue print . camel . ngt . TN/}返回的类型应为[ltn . ngt . camel . blue print . WB _ subscriptions;,而不是org . A

  • 问题内容: 我只是开始看一下Mattt出色的新Alamofire快速联网库,并且不确定如何将其与自定义标头一起使用。 我正在尝试从AFNetworking转换为Alamofire的代码是这样的: 问题答案: 根据官方文档,不建议修改会话配置: 不建议将其用于Authorization或Content- Type标头。而是分别使用URLRequestConvertible和ParameterEnco

  • 问题内容: 我需要一个游标用于以下查询,以便可以循环访问以获取/更新/插入一些其他数据。有人可以帮我吗? 我尝试了很多方法,但是没有找到任何可行的方法。 我正在使用 还是我出错了 问题答案: 只需将其放在通用表表达式之前即可: (但是,插入关于游标的通常的警告几乎总是会成为错误的工作工具。如果您可以找到一种以基于集合的方式完成整个操作的方法,则通常是更可取的,并且可能会表现得更好(或者至少会更好)

  • 我在为我的React本机应用程序设置testID和accessibilityLabel时遇到了一个奇怪的问题,其目的是让Appium Inspector(Appium Desktop)可以看到iOS和Android应用程序上的“accessibility id”,问题如下: 如果testID是设置在一起的辅助标签,iOS的应用程序不显示"辅助ID"的组件,但android的应用程序。 如果我只设置