2015-12-14 2 views
15
Client

My Spring Web Service имеет этот обычай распознаватель поймать SoapFaults:пользовательских SoapFault распознаватель запуска, но не находя SoapFault в 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); 
    } 

, который запускается на выполнение, когда эта ошибка возвращается из службы:

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

и записывает это в лог-файл:

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 

Я сбит с толку, почему с ode не находит SoapFault в SoapBody. Может кто-нибудь пролить некоторый свет на это? --appended-- Интригующий. Я также собственные веб-сервиса, который бросает эту ошибку:

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

и вот что он записывает:

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

Итак, мы видим, что код неисправности устанавливается в 500 по вине, прежде чем он покинет службу, но не появится в браузере. ТИА,

Еще обучения STEV

+0

Вы бревно «FC:» , но в вашем файле журнала сообщается «om_fc:»; Сам с «frs:». Вы уверены, что этот код и этот файл журнала совпадают? –

+0

Да.om_fc и om_frs и fc и fsr являются единственными. fc и fsr никогда не регистрируются, потому что sb.hasFault() возвращает false, как доказано «тело мыла не имеет ошибки», как показано в файле журнала. – user1201168

+0

Я предлагаю вам дебютировать ваш код и проверить, что делает «sb.hasFault()». У него может быть хотя бы указание на то, что делать –

ответ

3

Я имел дело с подобным вопросом раньше. В итоге проблема была в коде состояния 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/

Не имея правильный код статуса HTTP вызвал мой клиент библиотеки (Metro/Glassfish) игнорировать раздел неисправности полностью.

Обратите внимание, что это для Soap 1.1, однако я считаю, что для Soap 1.2 это опять-таки другое, если это имеет отношение к вам, тогда вы можете прочитать спецификации, но похоже, что вы используете 1.1.

+0

Интригующий. Я не вижу код ошибки в xml, возвращаемом веб-службой. Но я также владею веб-сервисом и просматриваю журналы для моего исходящего CXF FaultInterceptor. Я вижу, где f.getStatusCode возвращает 500. Поэтому я думаю, что мы на правильном пути - проблема может заключаться не в клиентском распознавателе, а в том, что сервисный перехватчик отключается. Я буду исследовать. Thx за вашу помощь. Фильм в 11. – user1201168

+0

@ user1201168 любая удача с этим? Мне интересно об этом. –

+0

во время перехвата с помощью перехватчика на службе, которую я обнаружил: 1) выключение перехватчиков приводит к появлению мыльного пузыря, как показано на рисунке, 2) включение перехватчиков и не выбрасывание какой-либо эксклюзии приводит к появлению мыльного пузыря, как показано, 3) включение перехватчиков и выявление явной ошибки с чем-то вроде throw new Fault (новое MyCustomException) вообще не вызывало никакого мыльного сбоя, а скорее неправильный ответ 200-Ok. Использование SoapUI значительно ускоряет тестирование того, что возвращается из службы. Я собираюсь поставить это на задний план, пока не смогу заставить мои клиентские перехватчики запускаться. Спасибо за вашу помощь. – user1201168

3

Ошибка возврата мыла не содержит пространства имен определения, которое может быть причиной того, что ваш код не находит ошибку.

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

Вы можете попробовать в том числе это как

<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

Внутренне, метод sb.hasFault() получает все дочерние элементы SoapBody ищет один с именем Fault и определяется с URI http://schemas.xmlsoap.org/soap/envelope/. Почему-то это не находит.

Однако, вы можете извлечь информацию из SoapBody объекта с чем-то вроде этого:

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

Или пытаюсь бросить ребенок из SoapBody непосредственно:

SoapFault sff = null; 
DOMSource source = (DOMSource)sb.getPayloadSource(); 
Node fault = source.getNode().getChildNodes().item(0); 
if(fault instanceof SoapFault) { 
    sff = (SoapFault)fault; 
} 
Смежные вопросы