2011-08-02 32 views
16

Tôi muốn sửa đổi Yêu cầu SOAP gửi đi. Tôi muốn xóa 2 nút xml ra khỏi cơ thể của phong bì. Tôi đã quản lý thiết lập Trình chặn và nhận giá trị Chuỗi được tạo của thông điệp được đặt thành điểm cuối.Làm thế nào để sửa đổi thông điệp XML thô của một yêu cầu CXF đi?

Tuy nhiên, mã sau dường như không hoạt động vì thư gửi đi không được chỉnh sửa như mong đợi. Có ai có một số mã hoặc ý tưởng về làm thế nào để làm điều này?

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); 
} 

Trả lời

17

Tôi cũng gặp vấn đề này ngày hôm nay. Sau nhiều khóc lóc và nghiến răng, tôi đã có thể làm thay đổi lớp StreamInterceptor trong bản demo configuration_interceptor mà đi kèm với nguồn 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()); 
    ... 

Biến soapMessage sẽ chứa các thông điệp SOAP hoàn chỉnh. Bạn có thể thao tác với thông điệp xà phòng, chuyển nó sang luồng đầu ra và thực hiện cuộc gọi message.setContent(OutputStream.class... để thực hiện các sửa đổi của bạn trên tin nhắn. Điều này đi kèm với không có bảo hành, vì tôi khá mới với CXF bản thân mình!

Lưu ý: CachedStream là một lớp riêng trong lớp StreamInterceptor. Đừng quên cấu hình interceptor của bạn để chạy trong pha PRE_STREAM để các interceptor SOAP có cơ hội viết thông báo SOAP.

+0

Cảm ơn bạn đã nhập John. Các yếu tố khác liên quan đến câu hỏi đó có thể được tìm thấy ở đây: http://stackoverflow.com/questions/6906499/how-to-modify-the-generated-soap-request – kiwifrog

32

Dựa trên nhận xét đầu tiên, tôi đã tạo một lớp trừu tượng có thể dễ dàng được sử dụng để thay đổi toàn bộ phong bì xà phòng.

Chỉ trong trường hợp ai đó muốn một phần mã sẵn sàng sử dụng.

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

Giải pháp này hoạt động hoàn hảo nhờ một tấn :-) –

+2

Thực sự tốt đẹp ! Cảm ơn! – Jpnh

+1

'CachedStream' đến từ đâu? Tôi không nhìn thấy một nhập khẩu cho nó và không thể tìm thấy nó. – javamonkey79

1

Sau đây có thể làm bong bóng ngoại lệ phía máy chủ. Sử dụng os.close() thay cho IOUtils.closeQuietly (os) trong giải pháp trước đó cũng có thể làm bong bóng ngoại lệ.

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

Chào mừng bạn đến với Stack Overflow! Trong khi câu trả lời này có lẽ là chính xác và hữu ích, nó được ưu tiên nếu bạn đưa ra một số giải thích cùng với nó để giải thích cách nó giúp giải quyết vấn đề. Điều này trở nên đặc biệt hữu ích trong tương lai, nếu có thay đổi (có thể không liên quan) khiến nó ngừng hoạt động và người dùng cần phải hiểu nó đã hoạt động như thế nào. –

Các vấn đề liên quan