2015-12-14 4 views
15

My Spring Web-Service-Client zu finden, hat sich diese benutzerdefinierten Resolver SoapFaults zu fangen:benutzerdefinierte SoapFault Resolver Auslösung aber nicht SoapFault in SoapBody

public class MySoapFaultResolver extends SoapFaultMessageResolver implements FaultMessageResolver 
{ 
    private static Logger logger = Logger.getLogger(MySoapFaultResolver.class); 

    @Override 
    public void resolveFault(WebServiceMessage wsm) throws IOException 
    { 
     logger.debug("entering"); 

//  SOAPMessage soapMessage = (SOAPMessage) wsm; cant cast to this 
     SoapMessage soapMessage = (SoapMessage) wsm; 

     if(soapMessage == null) { 
      logger.debug("soapMessage is null"); 
     } else { 
      logger.debug("soapMessage is not null"); 
      QName om_fc = soapMessage.getFaultCode(); 
      String om_frs = soapMessage.getFaultReason(); 
      logger.debug("om_fc:" + om_fc); 
      logger.debug("om_frs:" + om_frs); 
      if(soapMessage.getSoapBody() == null) { 
       logger.debug("soap body is null");    
      } else { 
       logger.debug("soap body is not null"); 
       SoapBody sb = soapMessage.getSoapBody(); 
       logger.debug(sb.toString()); // prints [email protected] 
       QName sb_name = sb.getName(); 
       logger.debug("sb_name:" + sb_name); 
       Iterator<QName> iter_attr_sb = sb.getAllAttributes(); 
       while(iter_attr_sb.hasNext()) { 
        QName qname = iter_attr_sb.next(); 
        String qname_valu = sb.getAttributeValue(qname); 
        logger.debug("attribute: " + qname + ":" + qname_valu); 
       } 
       if(sb.hasFault()) { 
        logger.debug("soap body has fault"); 
        SoapFault sff = sb.getFault(); 
        QName fc = sff.getFaultCode(); 
        String fsr = sff.getFaultStringOrReason(); 
        logger.debug("fc:" + fc); 
        logger.debug("fsr:" + fsr); 
        Iterator<QName> iter_attr = sff.getAllAttributes(); 
        while(iter_attr.hasNext()) { 
         QName qname = iter_attr.next(); 
         String qname_valu = sff.getAttributeValue(qname); 
         logger.debug("attribute: " + qname + ":" + qname_valu); 
        } 
        if(sff.getFaultDetail() == null) { 
         logger.debug("fault has no details"); 
        } else { 
         logger.debug("fault has details"); 
         SoapFaultDetail faultDetail = sff.getFaultDetail(); 
         Iterator<SoapFaultDetailElement> detailEntries = faultDetail.getDetailEntries(); 
         while(detailEntries.hasNext()) { 
          SoapFaultDetailElement detailElement = detailEntries.next(); 
          logger.debug("Found SoapFaultDetailElement name:" + detailElement.getName()); 
         } 
        } 
       } else { 
        logger.debug("soap body does not have fault");  
       } 
      } 
     } 
     logger.debug("exiting"); 

     SoapFaultClientException sfce = new SoapFaultClientException(soapMessage); 
     throw new IOException("cursesfoiledagain", sfce); 
    } 

, die ausgeführt wird, wenn dieser Fehler vom Service kommt zurück:

<soap:Envelope> 
    <soap:Body> 
    <soap:Fault> 
     <faultcode>soap:Server</faultcode> 
     <faultstring>Could not open connection; nested exception is org.hibernate.exception.GenericJDBCException: Could not open connection</faultstring> 
    </soap:Fault> 
    </soap:Body> 
</soap:Envelope> 

und schreibt diese in das Logfile:

MySoapFaultResolver-resolveFault] - entering 
MySoapFaultResolver-resolveFault] - soapMessage is not null 
MySoapFaultResolver-resolveFault] - om_fc:null 
MySoapFaultResolver-resolveFault] - om_frs:null 
MySoapFaultResolver-resolveFault] - soap body is not null 
MySoapFaultResolver-resolveFault] - [email protected] 
MySoapFaultResolver-resolveFault] - sb_name:{http://schemas.xmlsoap.org/soap/envelope/}Body 
MySoapFaultResolver-resolveFault] - soap body does not have fault 
MySoapFaultResolver-resolveFault] - exiting 

ich bin ratlos, warum die von c Ode findet den SoapFault nicht innerhalb des SoapBody. Kann jemand etwas Licht dazu bringen? --angebracht - Faszinierend. Ich besitze auch die webservice, dass dieser Fehler ist zu werfen:

public class MyOutSoapFaultInterceptor extends AbstractSoapInterceptor 
{ 
    private static Logger logger = Logger.getLogger(MyOutSoapFaultInterceptor.class); 

    public MyOutSoapFaultInterceptor() 
    { 
     super(Phase.MARSHAL); 
    } 

    @Override 
    public void handleMessage(SoapMessage message) throws Fault 
    { 
     logger.debug("entering"); 

     Exception e = message.getContent(Exception.class); 
     if(e == null) { 
      logger.debug("e is null"); 
     } else { 
      logger.debug("e is not null"); 
      logger.debug("e.getCause:" + e.getCause()); 
      logger.debug("e.getMessage:" + e.getMessage()); 
      if(e instanceof Fault) { 
       logger.debug("e is instanceOf Fault"); 
       Fault f = (Fault) message.getContent(Fault.class); 
       SoapFault sf = SoapFault.createFault((Fault) e, message.getVersion()); 
       logger.debug("sf is not null"); 
       logger.debug("sf.getCause:" + sf.getCause()); 
       logger.debug("sf.getMessage:" + sf.getMessage()); 
       logger.debug("sf.getStatusCode:" + sf.getStatusCode()); 
       logger.debug("sf.getCode:" + sf.getCode()); 
       FormsEndpointFault newFault = new FormsEndpointFault(); 
       newFault.setCode(sf.getStatusCode()); 
       newFault.setMessage(sf.getMessage()); 
       if(sf.hasDetails()) { 
        logger.debug("sf has details");  
        Element eee = sf.getDetail(); 
        if(eee.hasAttributes()) { 
         NamedNodeMap nnm = eee.getAttributes(); 
         logger.debug("sf.details has " + nnm.getLength() + " attributes"); 
         for(int ii = 0 ; ii < nnm.getLength() ; ii++) { 
          Node nnode = nnm.item(ii); //WARNING Nodes are recursive structures 
          logger.debug(" attribute node value:" + nnode.getNodeValue()); 
         } 
        } 
        if(eee.hasChildNodes()) { 
         NodeList nl = eee.getChildNodes(); 
         logger.debug("sf.details has " + nl.getLength() + " child nodes"); 
         for(int ii = 0 ; ii < nl.getLength() ; ii++) { 
          Node nnode = nl.item(ii); 
          logger.debug(" child node value:" + nnode.getNodeValue()); 
         } 
        } 
       } else { 
        logger.debug("sf has no details");     
       } 
      } 
     } 
     logger.debug("exiting"); 
    } 

und hier ist, was es protokolliert:

handleMessage] - entering 
handleMessage] - e is not null 
handleMessage] - e.getCause:org.springframework.orm.jpa.JpaSystemException: Could not open connection; nested exception is org.hibernate.exception.GenericJDBCException: Could not open connection 
handleMessage] - e.getMessage:Could not open connection; nested exception is org.hibernate.exception.GenericJDBCException: Could not open connection 
handleMessage] - e is instanceOf Fault 
handleMessage] - sf is not null 
handleMessage] - sf.getCause:org.springframework.orm.jpa.JpaSystemException: Could not open connection; nested exception is org.hibernate.exception.GenericJDBCException: Could not open connection 
handleMessage] - sf.getMessage:Could not open connection; nested exception is org.hibernate.exception.GenericJDBCException: Could not open connection 
handleMessage] - sf.getStatusCode:500 
handleMessage] - sf.getCode:Could not open connection; nested exception is org.hibernate.exception.GenericJDBCException: Could not open connection 
handleMessage] - sf has no details 
handleMessage] - exiting 

-/appended--

So, hier sehen wir, dass der Fehlercode gesetzt ist 500 im Fehler bevor es den Dienst verlässt, aber nicht im Browser erscheint. TIA,

Still-Lernen Stev

+0

Sie log "fc" , aber in Ihrer Logdatei wird "om_fc:" gemeldet; das sam mit "frs:". Sind Sie sicher, dass dieser Code und dieses Logfile zusammenpassen? –

+0

Ja.om_fc und om_frs und fc und fsr sind alle eindeutig. fc und fsr werden nie eingeloggt, da sb.hasFault() false zurückgibt, wie von "soap body hat keinen Fehler" in der Logdatei gezeigt. – user1201168

+0

Ich schlage vor, Sie debuggen Ihren Code und überprüfen, was genau "sb.hasFault()" tun. Es kann zumindest einen Hinweis darauf geben, was zu tun ist. –

Antwort

3

Ich habe, bevor sie mit einem ähnlichen Problem befasst. Am Ende war das Problem der HTTP-Statuscode.

In case of a SOAP error while processing the request, the SOAP HTTP server MUST issue an HTTP 500 "Internal Server Error" response and include a SOAP message in the response containing a SOAP Fault element (see section 4.4) indicating the SOAP processing error.

http://www.w3.org/TR/2000/NOTE-SOAP-20000508/

nicht verursacht die korrekte HTTP-Statuscode hat meine Client-Bibliothek (Metro/Glassfish) vollständig den Fehlerabschnitt zu ignorieren.

Beachten Sie, dass dies für Soap 1.1 ist, aber ich glaube, dass für Soap 1.2 ist dies wieder anders, wenn dies für Sie relevant ist dann können Sie die Spezifikationen lesen, aber es sieht aus wie Sie 1,1 verwenden.

+0

Faszinierend. Ich sehe keinen Fehlercode in der XML-Datei, die vom Webdienst zurückgegeben wird. Aber ich besitze auch den Webservice und schaue in den Logs nach meinem abgehenden CXF FaultInterceptor. Ich sehe, wo f.getStatusCode 500 zurückgibt. Ich denke also, wir sind auf dem richtigen Weg - das Problem liegt vielleicht nicht beim Client Resolver, sondern bei welchem Der Service Interceptor schleudert aus. Ich werde ermitteln. Danke für Ihre Hilfe. Film bei 11. – user1201168

+0

@ user1201168 Glück dabei? Ich bin neugierig auf den Fall. –

+0

mit dem Abfangjäger auf dem Dienst, den ich entdeckt habe, basteln 1) das Ausschalten von Abfängern ergibt einen Seifenbruch wie gezeigt, 2) das Abfeuern von Abfangjägern und das Nicht-Werfen von etwas Explizit liefert einen Seifenbruch wie gezeigt, 3) das Abfeuern von Abfängern und das Auslösen eines expliziten Fehlers mit etwas wie neu werfen Fault (new MyCustomException) ergab überhaupt keine soapfault, sondern eine falsche 200-Ok-Antwort. Durch die Verwendung von SoapUI wird das Testen der aus dem Service zurückkommenden Inhalte erheblich beschleunigt. Ich werde dies in den Hintergrund stellen, bis ich meine Client-Interzeptoren auslösen kann. Danke für Ihre Hilfe. – user1201168

3

Der Soap-Fehler, den Sie zurückgeben, fehlt der Definitionsnamensbereich, was der Grund sein könnte, dass Ihr Code den Fehler nicht finden kann.

if(sb.hasFault()) { 
    logger.debug("soap body has fault"); 
    ... 

Möglicherweise möchten Sie mit dieser als

<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
0

Intern Methode versuchen sb.hasFault() die Kind alle Elemente von SoapBody für ein Blick bekommt namens Fault und mit dem URI http://schemas.xmlsoap.org/soap/envelope/ definiert. Irgendwie findet es es nicht.

Sie können jedoch die Informationen aus dem SoapBody Objekt mit so etwas wie dies extrahieren:

DOMSource source = (DOMSource)sb.getPayloadSource(); 
Node fault = source.getNode().getChildNodes().item(0); 

String faultcode = fault.getChildNodes().item(0) // "faultcode" 
         .getChildNodes().item(0) // text node inside "faultcode" 
          .getNodeValue(); 
String faultstring = fault.getChildNodes().item(1) // "faultstring" 
         .getChildNodes().item(0) // text node inside "faultstring" 
          .getNodeValue(); 

Oder indem man versucht, das Kind von SoapBody direkt zu werfen:

SoapFault sff = null; 
DOMSource source = (DOMSource)sb.getPayloadSource(); 
Node fault = source.getNode().getChildNodes().item(0); 
if(fault instanceof SoapFault) { 
    sff = (SoapFault)fault; 
} 
Verwandte Themen