JAX-WS 响应消息中的可选部分

Optional part in JAX-WS response message

TL;DR: 我怎样才能在 wsdl 服务的响应 中有一个可选的

我是:

问题: 根据服务的版本,响应正文元素中可能会有一个附加元素。

通过以下服务定义,我可以将服务的 v1 作为目标:

  <message name="CreateResponse">
    <part name="ResourceCreated" element="ns7:ResourceCreated" />
  </message>

这一个适用于服务的 v2:

  <message name="CreateResponse">
    <part name="ResourceCreated" element="ns7:ResourceCreated" />
    <part name="Shell" element="ns8:Shell" />
  </message>

问题: 如何使用相同的服务定义来定位两个版本?我真的不需要第二个元素,所以忽略它就可以了。

详情:

我不相信有一个干净的解决方案来解决这个问题 - 不可能将 中的 元素标记为可选。

这种情况下的解决方法是在附加元素到达 JAX-WS 解析器之前将其剥离。这可以通过创建 CXF 拦截器或 JAX-WS 处理程序并操纵响应 XML.

来完成

创建 JAX-WS 处理程序:

public class StripHandler implements SOAPHandler<SOAPMessageContext> {

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        boolean isResponse = Boolean.FALSE.equals(context.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY));
        if (isResponse) {
            QName action = (QName) context.get(SOAPMessageContext.WSDL_OPERATION);
            if ("Create".equals(action.getLocalPart())) {
                Iterator<?> childIter = getBodyChildren(context);
                while(childIter.hasNext()) {
                    SOAPElement el = (SOAPElement) childIter.next();
                    if ("Shell".equals(el.getLocalName())) {
                        childIter.remove();
                    }
                }
            }
        }
        return true;
    }

    private Iterator<?> getBodyChildren(SOAPMessageContext context) {
        try {
            SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
            SOAPBody body = envelope.getBody();
            return body.getChildElements();
        } catch (SOAPException e) {
            throw new IllegalStateException(e);
        }
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {return true;}
    @Override
    public void close(MessageContext context) {}
    @Override
    public Set<QName> getHeaders() {return null;}

}

注册 JAX-WS 处理程序:

声明式

在服务接口旁边创建 handlers.xml 文件:

<handler-chains xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee">
    <handler-chain>
        <handler>
            <handler-name>StripHandlerr</handler-name>
            <handler-class>fully.qualified.StripHandler</handler-class>
        </handler>
    </handler-chain>
</handler-chains>

并使用注释 @HandlerChain(file = "handlers.xml")

将其附加到服务定义

以编程方式

这是一种替代方法,不需要额外的 xml 文件。

((BindingProvider)service).getBinding().setHandlerChain(Arrays.<Handler>asList(new StripHandler());