如果不存在,如何将唯一的消息ID添加到soap 1.2请求?

我们的web服务由未正确发送消息ID的系统使用. (根本不在soap请求中!)我正在寻找如何添加消息ID的方法
出现在实际通话中.如果不存在,则整个调用因未存在所需属性而失败.

有没有一种简单的方法来实现这一目标?

解决方法:

找到了解决方案here,但这似乎不起作用.

想出了这个适用于我的解决方案:创建一个拦截器来检查MessageID头并将其添加到消息中(如果它不存在):

package my.package;

import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.headers.Header;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Element;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class HeaderInterceptor extends AbstractPhaseInterceptor<Message> {

    private static final String SOAP_HEADER_KEY = "org.apache.cxf.headers.Header.list";
    private static final String NAMESPACE_URI   = "http://www.w3.org/2005/08/addressing";
    private static final String QUALIFIED_NAME  = "wsa:MessageID";
    private static final String LOCAL_NAME      = "MessageID";

    public HeaderInterceptor() {
        // phases: http://cxf.apache.org/docs/interceptors.html
        // 'pre protocol' seems to be the best moment to check the header, if we do it earlier the headers don't exist in the message object so we can't re-use the 'owner document'
        // if we do it later the unmarshalMAPs method (in MAPCodec.java) will already have processed the headers and will not process our added header
        super(Phase.PRE_PROTOCOL);
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        ArrayList<SoapHeader> headers = (ArrayList<SoapHeader>) message.get(SOAP_HEADER_KEY);

        // if the header doesn't exist and we have at least one header to access 'owner document' we can create and add our own MessageID header
        if(!messageIdHeaderExists(headers) && headers.size() > 0) {
            Element existingHeaderElement = (Element) headers.get(0).getObject();

            // use the existing header element to create our own MessageID header with random UUID
            Element element = existingHeaderElement.getOwnerDocument().createElementNS(NAMESPACE_URI, QUALIFIED_NAME);
            element.appendChild(existingHeaderElement.getOwnerDocument().createTextNode("uuid:" + UUID.randomUUID().toString()));

            QName qname = new QName(NAMESPACE_URI, LOCAL_NAME);
            SoapHeader header = new SoapHeader(qname, element);

            // by default a SoapHeader is created with 'direction out'
            header.setDirection(Header.Direction.DIRECTION_IN);

            headers.add(header);
        }
    }

    /**
     * Checks if the MessageID header exists in the list of headers.
     *
     * @param headers list of headers
     * @return true if the MessageID header exists, false if not
     */
    private Boolean messageIdHeaderExists(ArrayList<SoapHeader> headers) {
        for(SoapHeader header:headers) {
            if(header.getName().getLocalPart().equalsIgnoreCase(LOCAL_NAME)) {
                return true;
            }
        }
        return false;
    }        

}

在Spring上下文中定义拦截器:

<bean id="headerInterceptor" class="my.package.HeaderInterceptor" />

<jaxws:endpoint implementor="#service" address="/ws">
    <jaxws:inInterceptors>
        <ref bean="headerInterceptor" />
    </jaxws:inInterceptors>
</jaxws:endpoint>

使用CXF 2.6.1版进行测试.
关于拦截器的更多信息:http://cxf.apache.org/docs/interceptors.html

上一篇:java – 如何减少JAXB上下文开销?


下一篇:java – 如何使用Apache CXF从classpath加载truststore?