2011-08-02 23 views
16

我想修改一個傳出的SOAP請求。 我想從信封的正文中刪除2個xml節點。 我設法設置了一個攔截器,並將消息集的生成的字符串值獲取到端點。如何修改出站CXF請求的原始XML消息?

但是,下面的代碼似乎不起作用,因爲傳出消息未按預期編輯。有沒有人有一些關於如何做到這一點的代碼或想法?

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("<idJustification>0</idJustification>", ""); 
     content = content.replace("<indicRdv>false</indicRdv>", ""); 
     ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
     outputStream.write(content.getBytes(Charset.forName("UTF-8"))); 
     message.setContent(OutputStream.class, outputStream); 
} 

回答

17

我今天有這個問題。多哀哭切齒後,我能夠改變自帶的CXF源configuration_interceptor演示的StreamInterceptor類:

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()); 
    ... 

soapMessage變量將包含完整的SOAP消息。您應該能夠操作soap消息,將其刷新到輸出流並執行message.setContent(OutputStream.class...調用以對消息進行修改。這是沒有保證,因爲我自己很新的CXF!

注意:CachedStream是StreamInterceptor類中的私有類。不要忘記將攔截器配置爲在PRE_STREAM階段運行,以便SOAP攔截器有機會編寫SOAP消息。

+0

感謝您的輸入約翰。與此問題相關的其他元素可以在這裏找到:http://stackoverflow.com/questions/6906499/how-to-modify-the-generated-soap-request – kiwifrog

32

根據第一條評論,我創建了一個抽象類,可以很容易地用它來改變整個肥皂信封。

以防萬一有人想要現成的代碼部分。

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<Message> { 

    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 { 
     } 
    } 
} 
+2

這個解決方案完美的工作非常感謝噸:-) –

+2

真的很不錯!謝謝! – Jpnh

+1

'CachedStream'從哪裏來?我沒有看到它的導入,也找不到它。 – javamonkey79

1

以下是能夠喚起服務器端異常。在以前的解決方案中使用os.close()而不是IOUtils.closeQuietly(os)也能夠引發異常。

public class OutInterceptor extends AbstractPhaseInterceptor<Message> {  
    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<Message> { 
    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); 
     } 
    } 
} 
+2

歡迎堆棧溢出!雖然這個答案很可能是正確的,有用的,如果你有一些解釋與它一起,解釋它如何幫助解決這個問題,最好。這在未來變得特別有用,如果存在導致其停止工作,用戶需要了解它是如何工作後的變化(可能無關的)。 –