2015-12-14 11 views
15
Client

My Wiosna Web Service ma ten niestandardowy resolverowi złapać SoapFaults:zwyczaj SoapFault rezolwer wyzwalanie ale nie znalezienie SoapFault w 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 org.springframework.ws.soap.saaj.SaajSoa[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); 
    } 

który zostanie wykonany gdy usterka wraca ze służby:

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

i zapisuje to w pliku dziennika:

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 

jestem zaskoczony dlaczego c Oda nie znajduje SoapFault w SoapBody. Czy ktoś może rzucić trochę światła na to? - dołączono - Intrygujące. Posiadam również usługa, która rzuca ten błąd:

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

i oto co rejestruje:

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

Tak oto widzimy, że kod błędu jest ustawiona na 500 w przypadku błędu, zanim opuści usługę, ale nie pojawi się w przeglądarce. TIA,

Still-learning Stev

+0

się zalogować „FC” , ale w twoim dzienniku zgłasza się "om_fc:"; sam z "frs:". Czy na pewno ten kod i ten plik dziennika pasują do siebie? –

+0

Tak.om_fc i om_frs oraz fc i fsr są unikalne. fc i fsr nigdy nie są rejestrowane, ponieważ sb.hasFault() zwraca wartość false, co zostało udowodnione przez "body mydła nie ma błędu", jak widać w pliku dziennika. – user1201168

+0

Proponuję, abyś debbugował swój kod i sprawdzał, co robi "sb.hasFault()". Może to co najmniej wskazywać, co zrobić –

Odpowiedz

3

mam do czynienia z podobnym problemie wcześniej. Ostatecznie problemem był kod statusu HTTP.

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/

nie mając prawidłowy kod stanu HTTP spowodowane moja biblioteka klienta (Metro/GlassFish) ignorować sekcję usterki całkowicie.

Należy pamiętać, że dotyczy to Soap 1.1, jednak uważam, że dla Soap 1.2 jest to znowu inne, jeśli jest to dla ciebie istotne, możesz przeczytać specyfikację, ale wygląda na to, że używasz wersji 1.1.

+0

Intrygujące. Nie widzę kodu błędu w xml zwróconym przez usługę WWW. Ale ja również posiadam serwis WWW i przeglądam logi dla wychodzącego CXF FaultInterceptor Widzę, że f.getStatusCode zwraca 500. Więc myślę, że jesteśmy na dobrej drodze - problem może nie leżeć nie z resolver klienta, ale z czym przechwytuje serwisowy przechwytywacz. Sprawdzę to. Thx za pomoc. Film o 11. – user1201168

+0

@ user1201168 ma szczęście? Jestem ciekawy sprawy. –

+0

podczas majsterkowania z urządzeniem przechwytującym w usłudze, którą odkryłem 1) wyłączenie przechwytywaczy przynosi plamę mydłem, jak pokazano, 2) włączenie interceptorów i brak rzucania czegokolwiek explicite skutkuje uszkodzeniem mydła, jak pokazano, 3) włączanie przechwytujących i wyrzucanie wyraźnego błędu z czymś takim jak nowy Fault (nowy wyjątek MyCustomException) nie spowodował żadnego błędu soap, ale raczej nieprawidłową odpowiedź 200-Ok. Używanie SoapUI znacznie przyspiesza testowanie tego, co wraca z usługi. Zamierzam umieścić to na tylnym palniku, dopóki nie będę mógł uruchomić moich przechwytujących klientów. Dzięki za pomoc. – user1201168

3

Po zwrocie z mydła brakuje przestrzeni nazw definicji, co może być przyczyną niepowodzenia znalezienia błędu przez kod.

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

Możesz spróbować tym to jak

<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

wewnętrznie metodą sb.hasFault() pobiera wszystkie elementy podrzędne SoapBody szuka jeden nazwany Fault i zdefiniowane z URI http://schemas.xmlsoap.org/soap/envelope/. Jakoś to nie znajduje.

Można jednak wyodrębnić informacje z obiektu SoapBody z mniej więcej tak:

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

Albo próbując rzucić dzieckiem SoapBody bezpośrednio:

SoapFault sff = null; 
DOMSource source = (DOMSource)sb.getPayloadSource(); 
Node fault = source.getNode().getChildNodes().item(0); 
if(fault instanceof SoapFault) { 
    sff = (SoapFault)fault; 
} 
Powiązane problemy