Как установить заголовок WS-Addressing MessageId при использовании CXF с Apache Camel? - PullRequest
0 голосов
/ 09 января 2019

Я вызываю веб-сервис, которому требуются заголовки SOAP WS-Addressing. Я использую Apache Camel с CXF для вызова веб-службы. Когда я настраиваю конечную точку CXF с WSDL веб-службы, он достаточно умен, чтобы автоматически добавлять заголовки SOAP для WS-Adressing, но мне нужно установить собственный идентификатор сообщения.

Вот сообщение, которое в данный момент отправляется:

<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-Addressing, но я не вижу, как применить его к Apache Camel. Документация Apache Camel CXF также не упоминает WS-Addressing.

Ответы [ 2 ]

0 голосов
/ 04 июля 2019

если ваша проблема не решена, я предлагаю вам объединить ваш сервис 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>

и в перехватчике вы можете установить мыльные заголовки так:

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);
}
}
0 голосов
/ 09 января 2019

Ссылки на документацию, которые вы опубликовали, на самом деле содержат необходимую информацию, хотя не сразу понятно, как применить ее к Camel.

Документация CXF гласит:

Объект CXF org.apache.cxf.ws.addressing.impl.AddressingPropertiesImpl может использоваться для управления многими аспектами WS-адресации, включая Reply-To:

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-cxf

Клиентский API CXF предоставляет способ вызова операции с контекстом запроса и ответа. Если вы используете производителя конечных точек camel-cxf для вызова внешнего веб-сервиса, вы можете установить контекст запроса и получить контекст ответа с помощью следующего кода:

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.

Соедините их вместе, и вы получите:

@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"


Предупреждение. На своем маршруте я последовательно вызываю несколько различных веб-сервисов. Я обнаружил, что после установки RequestContext, как показано выше, Camel начал использовать один и тот же RequestContext для всех веб-служб, что привело к ошибке: «Заголовок, представляющий свойство адресации сообщения, недействителен, и сообщение не может быть обработано». Это связано с тем, что неправильный заголовок «Действие» использовался для всех вызовов веб-службы после первого.

Я проследил это до Apache Camel, используя «RequestContext» Свойство Exchange , отдельное от установленного нами заголовка, который, очевидно, имеет приоритет над заголовком. Если я удалю это свойство до вызова последующих веб-служб, CXF автоматически заполнит правильный заголовок действия.

...