howto modify a webservice request using CXF interceptors with org.w3c.dom.Node

女生的网名这么多〃 提交于 2021-02-04 15:53:35

问题


Using a CXF Interceptor I'd like to append some Node to the xml being sent out to the server. I've created a interceptor (see below) that picks up the message as DOM Node, modifies it and writes it back to the message object.

Unfortunately the code does not work as expected - the XML sent to the server does not contain the 'magicWord'. IMHO I'm using the wrong phase for this.

So the question is: how can I modify an outgoing webservice request using the org.w3c.dom.Node syntax?

package dummy;

import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

class DummyInterceptor extends AbstractPhaseInterceptor {

    String magicWord = "abc";

    public DummyInterceptor() {
        super(Phase.PRE_PROTOCOL);
    }

    public void handleMessage(Message message) {
        Document document = (Document) message.getContent(Node.class);
        NodeList nodes = document.getElementsByTagName("wsse:Security");
        if (nodes.getLength() == 1) {
            Node wsseSecurityNode = nodes.item(0);
            wsseSecurityNode.appendChild(document.createTextNode(magicWord));
        }
        message.setContent(Node.class, document);
    }
}

回答1:


Finally I've found out myself how to do this.

  • the interceptor must use 'Phase.PRE_PROTOCOL'
  • the interceptor must use addAfter(SaajOutInterceptor) - SaajOutInterceptor provides the Node in the Message
  • interceptor class should derive from AbstractSoapInterceptor
  • interceptor's handleMessage does not do the dirty work of modifying the DOM itself, rather it adds a new interceptor to the message using message.getInterceptorChain().add(...).
  • the freshly added interceptor is then supposed to modify the DOM



回答2:


If you want to modify the body of a request using the DOM api in a cxf interceptor the correct Phase is USER_PROTOCOL

The SAAJOutInterceptor creates the DOM structure, so your interceptor must be run after that, this means that you might have to add it to the interceptors chain since it is not always added by cxf for performance reasons.

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Node;

import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;

abstract public class SoapNodeModifierInterceptor extends AbstractSoapInterceptor {
    SoapNodeModifierInterceptor() { super(Phase.USER_PROTOCOL); }

    @Override public void handleMessage(SoapMessage message) throws Fault {
        try {
            if (message == null) {
                return;
            }
            SOAPMessage sm = message.getContent(SOAPMessage.class);
            if (sm == null) {
                throw new RuntimeException("You must add the SAAJOutInterceptor to the chain");
            }

            modifyNodes(sm.getSOAPBody());

        } catch (SOAPException e) {
            throw new RuntimeException(e);
        }
    }

    abstract void modifyNodes(Node node);
}

to add the interceptors:

import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
import org.apache.cxf.endpoint.Client;

/*[...]*/
client.getOutInterceptors().add(new SAAJOutInterceptor())
client.getOutInterceptors().add(new MySoapNodeModifierInterceptor())


来源:https://stackoverflow.com/questions/7494314/howto-modify-a-webservice-request-using-cxf-interceptors-with-org-w3c-dom-node

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!