¿Cómo modificar el mensaje XML sin formato de una solicitud CXF saliente?

Me gustaría modificar una solicitud SOAP saliente. Me gustaría eliminar 2 nodos xml del cuerpo de la Envolvente. Me las arreglé para configurar un Interceptor y obtener el valor de Cadena generado del mensaje establecido en el punto final.

Sin embargo, el siguiente código no parece funcionar, ya que el mensaje saliente no se edita como se esperaba. ¿Alguien tiene algún código o ideas sobre cómo hacer esto?

public class MyOutInterceptor extends AbstractSoapInterceptor { public MyOutInterceptor() { super(Phase.SEND); } public void handleMessage(SoapMessage message) throws Fault { // Get message content for dirty editing... StringWriter writer = new StringWriter(); CachedOutputStream cos = (CachedOutputStream)message.getContent(OutputStream.class); InputStream inputStream = cos.getInputStream(); IOUtils.copy(inputStream, writer, "UTF-8"); String content = writer.toString(); // remove the substrings from envelope... content = content.replace("0", ""); content = content.replace("false", ""); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); outputStream.write(content.getBytes(Charset.forName("UTF-8"))); message.setContent(OutputStream.class, outputStream); } 

Tuve este problema también hoy. Después de mucho llanto y rechinar de dientes, pude alterar la clase StreamInterceptor en la demostración de configuración_interceptor que viene con la fuente CXF:

 OutputStream os = message.getContent(OutputStream.class); CachedStream cs = new CachedStream(); message.setContent(OutputStream.class, cs); message.getInterceptorChain().doIntercept(message); try { cs.flush(); CachedOutputStream csnew = (CachedOutputStream) message.getContent(OutputStream.class); String soapMessage = IOUtils.toString(csnew.getInputStream()); ... 

La variable soapMessage contendrá el mensaje SOAP completo. Debería ser capaz de manipular el mensaje de soap, enjuagarlo en un flujo de salida y hacer una llamada a message.setContent(OutputStream.class... para poner sus modificaciones en el mensaje. Esto viene sin garantía, ya que soy bastante nuevo a CXF yo mismo!

Nota: CachedStream es una clase privada en la clase StreamInterceptor. No olvide configurar su interceptor para que se ejecute en la fase PRE_STREAM para que los interceptores SOAP puedan escribir el mensaje SOAP.

Basado en el primer comentario, creé una clase abstracta que puede usarse fácilmente para cambiar todo el sobre del soap.

Solo en caso de que alguien quiera una parte del código lista para usar.

 import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.io.IOUtils; import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor; import org.apache.cxf.io.CachedOutputStream; import org.apache.cxf.message.Message; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.apache.log4j.Logger; /** * http://www.mastertheboss.com/jboss-web-services/apache-cxf-interceptors * http://stackoverflow.com/questions/6915428/how-to-modify-the-raw-xml-message-of-an-outbound-cxf-request * */ public abstract class MessageChangeInterceptor extends AbstractPhaseInterceptor { public MessageChangeInterceptor() { super(Phase.PRE_STREAM); addBefore(SoapPreProtocolOutInterceptor.class.getName()); } protected abstract Logger getLogger(); protected abstract String changeOutboundMessage(String currentEnvelope); protected abstract String changeInboundMessage(String currentEnvelope); public void handleMessage(Message message) { boolean isOutbound = false; isOutbound = message == message.getExchange().getOutMessage() || message == message.getExchange().getOutFaultMessage(); if (isOutbound) { OutputStream os = message.getContent(OutputStream.class); CachedStream cs = new CachedStream(); message.setContent(OutputStream.class, cs); message.getInterceptorChain().doIntercept(message); try { cs.flush(); IOUtils.closeQuietly(cs); CachedOutputStream csnew = (CachedOutputStream) message.getContent(OutputStream.class); String currentEnvelopeMessage = IOUtils.toString(csnew.getInputStream(), "UTF-8"); csnew.flush(); IOUtils.closeQuietly(csnew); if (getLogger().isDebugEnabled()) { getLogger().debug("Outbound message: " + currentEnvelopeMessage); } String res = changeOutboundMessage(currentEnvelopeMessage); if (res != null) { if (getLogger().isDebugEnabled()) { getLogger().debug("Outbound message has been changed: " + res); } } res = res != null ? res : currentEnvelopeMessage; InputStream replaceInStream = IOUtils.toInputStream(res, "UTF-8"); IOUtils.copy(replaceInStream, os); replaceInStream.close(); IOUtils.closeQuietly(replaceInStream); os.flush(); message.setContent(OutputStream.class, os); IOUtils.closeQuietly(os); } catch (IOException ioe) { getLogger().warn("Unable to perform change.", ioe); throw new RuntimeException(ioe); } } else { try { InputStream is = message.getContent(InputStream.class); String currentEnvelopeMessage = IOUtils.toString(is, "UTF-8"); IOUtils.closeQuietly(is); if (getLogger().isDebugEnabled()) { getLogger().debug("Inbound message: " + currentEnvelopeMessage); } String res = changeInboundMessage(currentEnvelopeMessage); if (res != null) { if (getLogger().isDebugEnabled()) { getLogger().debug("Inbound message has been changed: " + res); } } res = res != null ? res : currentEnvelopeMessage; is = IOUtils.toInputStream(res, "UTF-8"); message.setContent(InputStream.class, is); IOUtils.closeQuietly(is); } catch (IOException ioe) { getLogger().warn("Unable to perform change.", ioe); throw new RuntimeException(ioe); } } } public void handleFault(Message message) { } private class CachedStream extends CachedOutputStream { public CachedStream() { super(); } protected void doFlush() throws IOException { currentStream.flush(); } protected void doClose() throws IOException { } protected void onWrite() throws IOException { } } } 

Lo siguiente es capaz de boost las excepciones del lado del servidor. El uso de os.close () en lugar de IOUtils.closeQuietly (os) en la solución anterior también puede generar excepciones.

 public class OutInterceptor extends AbstractPhaseInterceptor { public OutInterceptor() { super(Phase.PRE_STREAM); addBefore(StaxOutInterceptor.class.getName()); } public void handleMessage(Message message) { OutputStream os = message.getContent(OutputStream.class); CachedOutputStream cos = new CachedOutputStream(); message.setContent(OutputStream.class, cos); message.getInterceptorChain.aad(new PDWSOutMessageChangingInterceptor(os)); } } public class OutMessageChangingInterceptor extends AbstractPhaseInterceptor { private OutputStream os; public OutMessageChangingInterceptor(OutputStream os){ super(Phase.PRE_STREAM_ENDING); addAfter(StaxOutEndingInterceptor.class.getName()); this.os = os; } public void handleMessage(Message message) { try { CachedOutputStream csnew = (CachedOutputStream) message .getContent(OutputStream.class); String currentEnvelopeMessage = IOUtils.toString( csnew.getInputStream(), (String) message.get(Message.ENCODING)); csnew.flush(); IOUtils.closeQuietly(csnew); String res = changeOutboundMessage(currentEnvelopeMessage); res = res != null ? res : currentEnvelopeMessage; InputStream replaceInStream = IOUtils.tolnputStream(res, (String) message.get(Message.ENCODING)); IOUtils.copy(replaceInStream, os); replaceInStream.close(); IOUtils.closeQuietly(replaceInStream); message.setContent(OutputStream.class, os); } catch (IOException ioe) { throw new RuntimeException(ioe); } } }