2012-06-14 6 views
11

मैं सीएक्सएफ पर सर्वर साइड इंटरसेप्टर के साथ झुका रहा हूं। लेकिन ऐसा लगता है कि सरल इनकमिंग और आउटगोइंग इंटरसेप्टर्स को लागू करने के लिए यह एक छोटा सा काम नहीं है जो मुझे एसओएपी एक्सएमएल युक्त एक सादा स्ट्रिंग देता है।अपाचे सीएक्सएफ का उपयोग करके एक साधारण तरीके से इनकमिंग और आउटगोइंग साबुन एक्सएमएल कैसे प्राप्त करें?

मुझे इंटरसेप्टर में सादा एक्सएमएल होना चाहिए ताकि मैं उन्हें विशिष्ट लॉगिंग कार्यों के लिए उपयोग कर सकूं। मानक लॉग इन & लॉगऑट इंटरसेप्टर कार्य तक नहीं हैं। क्या कोई इस बात पर कुछ उदाहरण साझा करने को तैयार है कि मैं एक साधारण आने वाले इंटरसेप्टर को कैसे कार्यान्वित कर सकता हूं जो आने वाले एसओएपी एक्सएमएल और आउटगोइंग इंटरसेप्टर को फिर से एसओएपी एक्सएमएल प्राप्त करने में सक्षम है?

उत्तर

13

एक इनकमिंग इंटरसेप्टर यहाँ मिले कोड: Logging request/response with Apache CXF as XML

मेरे बाहर जाने वाले इंटरसेप्टर:

import java.io.OutputStream; 

import org.apache.cxf.interceptor.Fault; 
import org.apache.cxf.interceptor.LoggingOutInterceptor; 
import org.apache.cxf.io.CacheAndWriteOutputStream; 
import org.apache.cxf.io.CachedOutputStream; 
import org.apache.cxf.io.CachedOutputStreamCallback; 
import org.apache.cxf.message.Message; 
import org.apache.cxf.phase.Phase; 

public class MyLogInterceptor extends LoggingOutInterceptor { 

    public MyLogInterceptor() { 
     super(Phase.PRE_STREAM); 
    } 

    @Override 
    public void handleMessage(Message message) throws Fault { 
     OutputStream out = message.getContent(OutputStream.class); 
     final CacheAndWriteOutputStream newOut = new CacheAndWriteOutputStream(out); 
     message.setContent(OutputStream.class, newOut); 
     newOut.registerCallback(new LoggingCallback()); 
    } 

    public class LoggingCallback implements CachedOutputStreamCallback { 
     public void onFlush(CachedOutputStream cos) { 
     } 

     public void onClose(CachedOutputStream cos) { 
      try { 
       StringBuilder builder = new StringBuilder(); 
       cos.writeCacheTo(builder, limit); 
       // here comes my xml: 
       String soapXml = builder.toString(); 
      } catch (Exception e) { 
      } 
     } 
    } 
} 
+1

कॉलबैक का क्या फायदा है? – Basil

+1

आउटपुट स्ट्रीम फ़्लश होने के बाद कॉलबैक में ऑनक्लोज़() विधि लागू की जाती है और आपके डेटा को पुनर्प्राप्त करने के लिए आपके लिए उपलब्ध है। – annkatrin

+1

इस उदाहरण में 'सीमा' क्या है? इसे कहीं भी घोषित नहीं किया गया है ... – Cleankod

6

मैं मेरे लिए काम करने के लिए उपरोक्त समस्या का समाधान नहीं हो सकता है। यह मैं क्या विकसित किया है और आशा है कि यह दूसरों की मदद कर सकते हैं:

मेरे "भेजे" इंटरसेप्टर:

import org.apache.cxf.interceptor.LoggingInInterceptor; 
import org.apache.cxf.interceptor.LoggingMessage; 

public class MyCxfSoapInInterceptor extends LoggingInInterceptor { 


    public MyCxfSoapInInterceptor() { 
     super(); 
    } 

    @Override 
    protected String formatLoggingMessage(LoggingMessage loggingMessage) { 
     String soapXmlPayload = loggingMessage.getPayload() != null ? loggingMessage.getPayload().toString() : null; 

     // do what you want with the payload... in my case, I stuck it in a JMS Queue 

     return super.formatLoggingMessage(loggingMessage); 
    } 
} 

मेरे "बाहर जाने वाले" इंटरसेप्टर:

import org.apache.cxf.interceptor.LoggingMessage; 
import org.apache.cxf.interceptor.LoggingOutInterceptor; 

public class MyCxfSoapOutInterceptor extends LoggingOutInterceptor { 

    public MyCxfSoapOutInterceptor() { 
     super(); 
    } 

    @Override 
    protected String formatLoggingMessage(LoggingMessage loggingMessage) { 
     String soapXmlPayload = loggingMessage.getPayload() != null ? loggingMessage.getPayload().toString() : null; 

     // do what you want with the payload... in my case, I stuck it in a JMS Queue 

     return super.formatLoggingMessage(loggingMessage); 
    } 
} 

कुछ मैं अपने वसंत ढांचे आवेदन करने के लिए जोड़ा संदर्भ एक्सएमएल (एक्सएमएल फाइल में दो इंटरसेप्टर्स को भी परिभाषित करना याद रखें) ...

... 

    <cxf:bus> 
     <cxf:inInterceptors> 
      <ref bean="myCxfSoapInInterceptor"/> 
     </cxf:inInterceptors> 
     <cxf:inFaultInterceptors> 
      <ref bean="myCxfSoapInInterceptor"/> 
     </cxf:inFaultInterceptors> 
     <cxf:outInterceptors> 
      <ref bean="myCxfSoapOutInterceptor"/> 
     </cxf:outInterceptors> 
     <cxf:outFaultInterceptors> 
      <ref bean="myCxfSoapOutInterceptor"/> 
     </cxf:outFaultInterceptors> 
    </cxf:bus> 

    ... 

नोट, एनोटेशन के माध्यम से इंटरसेप्टर जोड़ने के अन्य तरीके हैं जो आपको विशिष्ट साबुन सेवाओं को केवल अवरुद्ध करने की अनुमति देंगे। इंटरसेप्टर जोड़ने का उपरोक्त तरीका "बस" आपकी सभी साबुन सेवाओं को रोक देगा।

+0

मैंने वही किया जो आपने सुझाव दिया था लेकिन मेरा 'लॉगिंगऑटइंटरसेप्टर' को पार नहीं किया गया है। 'लॉगिंगइनइंटरसेप्टर' के लिए यह अपेक्षा के अनुसार ठीक से काम करता है। तुम जानते हो क्यों? धन्यवाद। – bryannguyen

4

मैं सिर्फ एक और विकल्प साझा करना चाहता हूं, कुछ लॉगिंग उद्देश्यों के लिए एक ही समय में इनकमिंग और आउटगोइंग संदेशों को कैसे प्राप्त करना है, उदाहरण के लिए लॉग अनुरोध और डेटाबेस से संबंधित प्रतिक्रियाएं।

import javax.xml.namespace.QName; 
import javax.xml.soap.SOAPMessage; 
import javax.xml.soap.SOAPPart; 
import javax.xml.transform.TransformerException; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult; 
import javax.xml.ws.handler.MessageContext; 
import javax.xml.ws.handler.soap.SOAPHandler; 
import javax.xml.ws.handler.soap.SOAPMessageContext; 
import java.io.StringWriter; 
import java.util.Collections; 
import java.util.Set; 

public class CxfLoggingHandler implements SOAPHandler<SOAPMessageContext> { 

private static final String SOAP_REQUEST_MSG_KEY = "REQ_MSG"; 

public Set<QName> getHeaders() { 
    return Collections.EMPTY_SET; 
} 

public boolean handleMessage(SOAPMessageContext context) { 
    Boolean outgoingMessage = (Boolean) context.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY); 
    if (outgoingMessage) { 
     // it is outgoing message. let's work 
     SOAPPart request = (SOAPPart)context.get(SOAP_REQUEST_MSG_KEY); 
     String requestString = convertDomToString(request); 
     String responseString = convertDomToString(context.getMessage().getSOAPPart()); 
     String soapActionURI = ((QName)context.get(MessageContext.WSDL_OPERATION)).getLocalPart(); 
     // now you can output your request, response, and ws-operation  
    } else { 
     // it is incoming message, saving it for future 
     context.put(SOAP_REQUEST_MSG_KEY, context.getMessage().getSOAPPart()); 
    } 
    return true; 
} 

public boolean handleFault(SOAPMessageContext context) {   
    return handleMessage(context); 
} 

private String convertDomToString(SOAPPart soap){ 
    final StringWriter sw = new StringWriter(); 
    try { 
     TransformerFactory.newInstance().newTransformer().transform(
       new DOMSource(soap), 
       new StreamResult(sw)); 
    } catch (TransformerException e) { 
     // do something 
    } 
    return sw.toString(); 
} 
} 

और फिर उस हैंडलर वेब सेवा के साथ कुछ कस्टम गुण और अनुरोध एक्सएमएल को छानने पर कब्जा करने के लिए एक StringBuffer के लिए पाठ लिखने के लिए

<jaxws:endpoint id="wsEndpoint" implementor="#myWS" address="/myWS" > 
    <jaxws:handlers> 
     <bean class="com.package.handlers.CxfLoggingHandler"/> 
    </jaxws:handlers> 
</jaxws:endpoint> 
+0

'if (outgoingMessage) {' के साथ 'if (! के साथ बदलकर यह पूरी तरह से काम करता है!आउटगोइंग मैसेज) {' – Ivano85

+0

एचएम, यह" अगर (आउटगोइंग मैसेज) "होना चाहिए। चूंकि आने वाले संदेश को भविष्य के लिए सहेजा जाना चाहिए, और जब हमारे पास आउटसोइंग मैसेज है, तो हम डेटा लॉग इन करने में सक्षम हैं, क्योंकि हमारे पास इनकमिंग और आउटगोइंग संदेशों दोनों की पहुंच है। – error1009

+0

क्षमा करें, आप सही हैं क्योंकि यह एक एंडपॉइंट है: पी ... मैंने इसे क्लाइंट साइड का इस्तेमाल किया, इसलिए आउटगोइंग मैसेज मेरे मामले में और आने वाले संदेश में प्रतिक्रिया थी। मैंने इसे बहुत, महान समाधान की सराहना की ;-) – Ivano85

3

उदाहरण कनेक्ट, हुक के साथ:

public class XMLLoggingInInterceptor extends AbstractPhaseInterceptor<Message> { 

    private static final String LOCAL_NAME = "MessageID"; 

    private static final int PROPERTIES_SIZE = 128; 

    private String name = "<interceptor name not set>"; 

    protected PrettyPrinter prettyPrinter = null; 
    protected Logger logger; 
    protected Level reformatSuccessLevel; 
    protected Level reformatFailureLevel; 

    public XMLLoggingInInterceptor() { 
     this(LogUtils.getLogger(XMLLoggingInInterceptor.class), Level.INFO, Level.WARNING); 
    } 

    public XMLLoggingInInterceptor(PrettyPrinter prettyPrinter) { 
     this(LogUtils.getLogger(XMLLoggingInInterceptor.class), Level.INFO, Level.WARNING); 

     this.prettyPrinter = prettyPrinter; 
    } 

    public XMLLoggingInInterceptor(Logger logger, Level reformatSuccessLevel, Level reformatFailureLevel) { 
     super(Phase.RECEIVE); 
     this.logger = logger; 
     this.reformatSuccessLevel = reformatSuccessLevel; 
     this.reformatFailureLevel = reformatFailureLevel; 
    } 

    public XMLLoggingInInterceptor(PrettyPrinter prettyPrinter, Logger logger, Level reformatSuccessLevel, Level reformatFailureLevel) { 
     this(logger, reformatSuccessLevel, reformatFailureLevel); 
     this.prettyPrinter = prettyPrinter; 
     this.logger = logger; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public void handleMessage(Message message) throws Fault { 

     if (!logger.isLoggable(reformatSuccessLevel)) { 
      return; 
     } 

     InputStream in = message.getContent(InputStream.class); 
     if (in == null) { 
      return; 
     } 

     StringBuilder buffer; 

     CachedOutputStream cache = new CachedOutputStream(); 
     try { 
      InputStream origIn = in; 
      IOUtils.copy(in, cache); 

      if (cache.size() > 0) { 
       in = cache.getInputStream(); 
      } else { 
       in = new ByteArrayInputStream(new byte[0]); 
      } 

      // set the inputstream back as message payload 
      message.setContent(InputStream.class, in); 

      cache.close(); 
      origIn.close(); 

      int contentSize = (int) cache.size(); 

      buffer = new StringBuilder(contentSize + PROPERTIES_SIZE); 

      cache.writeCacheTo(buffer, "UTF-8"); 
     } catch (IOException e) { 
      throw new Fault(e); 
     } 

     // decode chars from bytes 
     char[] chars = new char[buffer.length()]; 
     buffer.getChars(0, chars.length, chars, 0); 

     // reuse buffer 
     buffer.setLength(0); 

     // perform local logging - to the buffer 
     buffer.append(name); 

     logProperties(buffer, message); 

     // pretty print XML 
     if(prettyPrinter.process(chars, 0, chars.length, buffer)) { 
      // log as normal 
      logger.log(reformatSuccessLevel, buffer.toString()); 
     } else { 
      // something unexpected - log as exception 
      buffer.append(" was unable to format XML:\n"); 
      buffer.append(chars); // unmodified XML 

      logger.log(reformatFailureLevel, buffer.toString()); 
     } 
    } 


    /** 
    * Gets theMessageID header in the list of headers. 
    * 
    */ 
    protected String getIdHeader(Message message) { 
     return getHeader(message, LOCAL_NAME); 
    } 

    protected String getHeader(Message message, String name) { 
     List<Header> headers = (List<Header>) message.get(Header.HEADER_LIST); 

     if(headers != null) { 
      for(Header header:headers) { 
       if(header.getName().getLocalPart().equalsIgnoreCase(name)) { 
        return header.getObject().toString(); 
       } 
      } 
     } 
     return null; 
    }   

    /** 
    * Method intended for use within subclasses. Log custom field here. 
    * 
    * @param message message 
    */ 

    protected void logProperties(StringBuilder buffer, Message message) { 
     final String messageId = getIdHeader(message); 
     if(messageId != null) { 
      buffer.append(" MessageId="); 
      buffer.append(messageId); 
     } 
    } 

    public void setPrettyPrinter(PrettyPrinter prettyPrinter) { 
     this.prettyPrinter = prettyPrinter; 
    } 

    public PrettyPrinter getPrettyPrinter() { 
     return prettyPrinter; 
    } 

    public Logger getLogger() { 
     return logger; 
    } 

    public String getName() { 
     return name; 
    } 

    public Level getReformatFailureLevel() { 
     return reformatFailureLevel; 
    } 

    public Level getReformatSuccessLevel() { 
     return reformatSuccessLevel; 
    } 

    public void setReformatFailureLevel(Level reformatFailureLevel) { 
     this.reformatFailureLevel = reformatFailureLevel; 
    } 

    public void setReformatSuccessLevel(Level reformatSuccessLevel) { 
     this.reformatSuccessLevel = reformatSuccessLevel; 
    } 

    public void setLogger(Logger logger) { 
     this.logger = logger; 
    } 
} 

आउटपुट इंटरसेप्टर के साथ पूरी तरह से काम करने वाले उदाहरण के लिए, मेरा CXF module गीथब पर देखें।

संबंधित मुद्दे