问题
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