如何使用JAX-WS客户端指定WS-Addressing版本?

时间:2014-06-09 19:37:13

标签: java soap jax-ws ws-addressing

我使用wsimport(JDK 1.7)生成了一个SOAP 1.2 Web服务客户端。我需要它明确使用WS-Addressing 2004/08而不是2005/08。 我能找到最接近客户端的是

import MyService.*;
import javax.xml.ws.BindingProvider;

public class test {

    public static void main(String[] args) {
        MyService service = new MyService();  
        IMyService proxy = service.getMyService(new javax.xml.ws.soap.AddressingFeature(true, true) );  
        ((BindingProvider)proxy).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://192.168.0.5:1234/services/MyService");
        proxy.Ping("Foo");
      }
}

重要的是

MyService service = new MyService();
IMyService proxy = service.getMyService(new javax.xml.ws.soap.AddressingFeature(true, true));

不幸的是,这导致2005/08解决。不为getMyService()提供参数导致不使用WS-Addressing。

我可以在Google上找到的唯一一个强制2004/08解决使用Axis2的例子(我希望JAX-WS离开Axis2的全部原因)

电线上的差异是 (2004/08)

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing">
    <s:Header>
        <a:Action s:mustUnderstand="1">http://www.example.com/schemas/service/myservice/IMyService/Ping</a:Action>
        <a:MessageID>urn:uuid:87727401-b1a0-4667-9ef0-c64e58800ff6</a:MessageID>
        <a:ReplyTo>
            <a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
        </a:ReplyTo>
        <a:To s:mustUnderstand="1">https://192.168.0.5:1234/services/MyService</a:To>
    </s:Header>
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <Ping xmlns="http://www.example.com/schemas/service/myservice">
            <Message>Foo</Message>
        </Ping>
    </s:Body>
</s:Envelope>

(2005/08)

<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
    <S:Header>
        <To xmlns="http://www.w3.org/2005/08/addressing">https://192.168.0.5:1234/services/MyService</To>
        <Action xmlns="http://www.w3.org/2005/08/addressing" xmlns:S="http://www.w3.org/2003/05/soap-envelope" S:mustUnderstand="true">http://www.example.com/schemas/service/myservice/IMyService/Ping</Action>
        <ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
            <Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
        </ReplyTo>
        <MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:87727401-b1a0-4667-9ef0-c64e58800ff6</MessageID>
    </S:Header>
    <S:Body>
        <Ping xmlns="http://www.example.com/schemas/service/myservice">
            <Message>Foo</Message>
        </Ping>
    </S:Body>
</S:Envelope>

这里有任何想法吗?

2 个答案:

答案 0 :(得分:4)

我找到了一种方法,但我不相信它是最好的解决方案。

它涉及创建自定义SOAPHandler并手动注入Addressing头并剥离HTTP头soapaction

public static class Addressing2004SoapHandler implements SOAPHandler<SOAPMessageContext>
{
    private String mEndpoint;

    public Addressing2004SoapHandler(String endpoint) {
        super();
        mEndpoint = endpoint;
    }

    public Set<QName> getHeaders()
    {
        Set<QName> retval = new HashSet<QName>();
        retval.add(new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing", "Action"));
        retval.add(new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing", "MessageID"));
        retval.add(new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing", "ReplyTo"));
        retval.add(new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing", "To"));
        return retval;
    }

    public boolean handleMessage(SOAPMessageContext messageContext)
    {
        Boolean outboundProperty = (Boolean)messageContext.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);

        if (outboundProperty.booleanValue()) {
            try {
                messageContext.put(MessageContext.HTTP_REQUEST_HEADERS, Collections.singletonMap("Content-Type",Collections.singletonList("application/soap+xml; charset=utf-8")));
                SOAPMessage message = messageContext.getMessage();
                if(message.getSOAPPart().getEnvelope().getHeader() == null) {
                        message.getSOAPPart().getEnvelope().addHeader();
                }
                SOAPHeader header = message.getSOAPPart().getEnvelope().getHeader();
                SOAPHeaderElement actionElement = header.addHeaderElement(new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing", "Action"));
                actionElement.setMustUnderstand(true);
                String action = (String)messageContext.get("javax.xml.ws.soap.http.soapaction.uri");
                messageContext.put("javax.xml.ws.soap.http.soapaction.uri", null);
                actionElement.addTextNode(action);
                header.addHeaderElement(new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing", "MessageID")).addTextNode("uuid:" + UUID.randomUUID().toString());
                SOAPHeaderElement replyToElement = header.addHeaderElement(new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing", "ReplyTo"));
                SOAPElement addressElement = replyToElement.addChildElement(new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing", "Address"));
                addressElement.addTextNode("http://www.w3.org/2004/08/addressing/anonymous");
                SOAPHeaderElement toElement = header.addHeaderElement(new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing", "To"));
                toElement.setMustUnderstand(true);
                String endpoint = (String)messageContext.get("javax.xml.ws.service.endpoint.address");
                toElement.addTextNode(endpoint);
            }
            catch(SOAPException ex) {
            }
        }

        return true;
    }

    public boolean handleFault(SOAPMessageContext messageContext)
    {
            return true;
    }
    public void close(MessageContext messageContext)
    {
    }
}

这是更新的测试类

public class test {
    public static void main(String[] args) {
        MyService service = new MyService();  
        IMyService proxy = service.getMyService();  
        javax.xml.ws.Binding binding = ((BindingProvider)proxy).getBinding();
        List<Handler> handlerList = binding.getHandlerChain();
        handlerList.add(new Addressing2004SoapHandler(endpoint));
        binding.setHandlerChain(handlerList);
        Map<String, Object> requestContext = ((BindingProvider)proxy).getRequestContext();
        requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://192.168.0.5:1234/services/MyService");
        proxy.Ping("Foo");
    }
}

有副作用,我还没弄清楚如何解决,这导致&lt;?xml version =&#34; 1.0&#34;?&gt; xml声明与HTTP Content-type冲突。当我发现这一点时,我会发布更新。

答案 1 :(得分:0)

我使用了jaxws-rt

中的MemberSubmissionAddressingFeature

IMyService proxy = service.getMyService(new com.sun.xml.ws.developer.MemberSubmissionAddressingFeature(true, true) );

这是maven http://mvnrepository.com/artifact/com.sun.xml.ws/jaxws-rt/2.2.7

的pom文件依赖项