Soap get error

(PHP 5, PHP 7, PHP 8)

(PHP 5, PHP 7, PHP 8)

Введение

Представляет ошибку SOAP.

Обзор классов

public
?string
$_name = null;

protected
string
$file = «»;

private
array
$trace = [];

public __construct(
    array|string|null $code,
    string $string,
    ?string $actor = null,
    mixed $details = null,
    ?string $name = null,
    mixed $headerFault = null
)

}

Свойства

_name
detail
faultactor
faultcode
faultcodens
faultstring

Содержание

  • SoapFault::__construct — Конструктор SoapFault
  • SoapFault::__toString — Получить текстовое представление SoapFault

dmitry dot koterov at gmail dot com

13 years ago


You may use undocumented and invisible property $e->faultcode to access string version of $code. Because standard $e->getCode() does not work:

<?php

$e
= new SoapFault("test", "msg");

var_dump($e->getCode()); // prints "0"

var_dump($e->faultcode); // prints "test"

?>



Also you may use namespaced fault codes:

<?php

$e
= new SoapFault(array("namespace", "test"), "msg");

?>



- see ext/soap/soap.php, PHP_METHOD(SoapFault, SoapFault). To access the namespace, use $e->faultcodens


chris AT cmbuckley DOT co DOT uk

12 years ago


A bit more digging in ext/soap/soap.c and the set_soap_fault function reveals the other undocumented properties from the constructor:

<?php
try {
    throw new
SoapFault('code', 'string', 'actor', 'detail', 'name', 'header');
} catch (
Exception $ex) {
   
var_dump($ex->faultcode, $ex->faultstring, $ex->faultactor, $ex->detail, $ex->_name, $ex->headerfault);
}
?>


fbernoldi at gmail dot com

10 years ago


Hi all,

I've decided to post this since it may be helpful, I've spend a couple of days trying to do this.

In order to use wsdl's specified faults with complex types, i.e:

WSDL definitions:

(xsd:schema namespace, ns1 = target namespace)

<xsd:element name="doubleFault">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="detail1" type="xsd:string"/>
      <xsd:element name="detail2" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>

WSDL messages:

<message name="fault_specified">
    <part name="relevant_name" element="ns1:doubleFault"/>
</message>

WSDL port type:

<portType name="test">
  <operation name="operationTest">
  <input message="ns1:not_relevant_request"/>
  <output message="ns1:not_relevant_response"/>
  <fault name="FaultSpecified" message="ns1:fault_specified"/>
  ....
</portType>

You have to specify the response in the detail parameter as an array corresponding the tag names.

PHP Code:

<?phpfunction operationTest($request_param ...) {// ...
   
$array_details = array("detail1" => "Explanation 1", "detail2" => "Explanation 2");

        return new

SoapFault("Server", "example fault string", null, $array_details, "FaultSpecified");

}

$server = new SOAPServer("handmade.wsdl");
$server->addFunction("operationTest");
$server->handle(); ?>

that should respond something like this:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://mynamespace">
   <SOAP-ENV:Body>
      <SOAP-ENV:Fault>
         <faultcode>SOAP-ENV:Server</faultcode>
         <faultstring>example fault string</faultstring>
         <detail>
            <ns1:doubleFault>
               <detail1>Explanation 1</detail1>
               <detail2>Explanation 2</detail2>
            </ns1:doubleFault>
         </detail>
      </SOAP-ENV:Fault>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

I Hope it helps,
Federico.


This XML file does not appear to have any style information associated with it. The document tree is shown below.

<wsdl:definitions xmlns:xsd=«http://www.w3.org/2001/XMLSchema» xmlns:wsdl=«http://schemas.xmlsoap.org/wsdl/» xmlns:tns=«http://soap.ws.javastudy.ru/» xmlns:soap=«http://schemas.xmlsoap.org/wsdl/soap/» xmlns:ns1=«http://schemas.xmlsoap.org/soap/http» name=«HelloSoap» targetNamespace=«http://soap.ws.javastudy.ru/»>

<wsdl:types>

<xs:schema xmlns:xs=«http://www.w3.org/2001/XMLSchema» xmlns:tns=«http://soap.ws.javastudy.ru/» attributeFormDefault=«unqualified» elementFormDefault=«unqualified» targetNamespace=«http://soap.ws.javastudy.ru/»>

<xs:element name=«exceptionTest» type=«tns:exceptionTest»/>

<xs:element name=«exceptionTestResponse» type=«tns:exceptionTestResponse»/>

<xs:element name=«getGoods» type=«tns:getGoods»/>

<xs:element name=«getGoodsResponse» type=«tns:getGoodsResponse»/>

<xs:element name=«goods» type=«tns:goods»/>

<xs:element name=«sayHelloTo» type=«tns:sayHelloTo»/>

<xs:element name=«sayHelloToResponse» type=«tns:sayHelloToResponse»/>

<xs:element name=«testService» type=«tns:testService»/>

<xs:element name=«testServiceResponse» type=«tns:testServiceResponse»/>

<xs:complexType name=«testService»>

<xs:sequence/>

</xs:complexType>

<xs:complexType name=«testServiceResponse»>

<xs:sequence>

<xs:element minOccurs=«0» name=«return» type=«xs:string»/>

</xs:sequence>

</xs:complexType>

<xs:complexType name=«getGoods»>

<xs:sequence/>

</xs:complexType>

<xs:complexType name=«getGoodsResponse»>

<xs:sequence>

<xs:element minOccurs=«0» name=«return» type=«tns:goods»/>

</xs:sequence>

</xs:complexType>

<xs:complexType name=«goods»>

<xs:sequence>

<xs:element name=«id» type=«xs:int»/>

<xs:element minOccurs=«0» name=«name» type=«xs:string»/>

</xs:sequence>

</xs:complexType>

<xs:complexType name=«sayHelloTo»>

<xs:sequence>

<xs:element minOccurs=«0» name=«text» type=«xs:string»/>

</xs:sequence>

</xs:complexType>

<xs:complexType name=«sayHelloToResponse»>

<xs:sequence>

<xs:element minOccurs=«0» name=«return» type=«xs:string»/>

</xs:sequence>

</xs:complexType>

<xs:complexType name=«exceptionTest»>

<xs:sequence>

<xs:element minOccurs=«0» name=«text» type=«xs:string»/>

</xs:sequence>

</xs:complexType>

<xs:complexType name=«exceptionTestResponse»>

<xs:sequence/>

</xs:complexType>

<xs:complexType name=«exceptionTrace»>

<xs:sequence>

<xs:element minOccurs=«0» name=«trace» type=«xs:string»/>

</xs:sequence>

</xs:complexType>

<xs:element name=«MyWebserviceException» type=«tns:MyWebserviceException»/>

<xs:complexType name=«MyWebserviceException»>

<xs:sequence>

<xs:element minOccurs=«0» name=«exceptionTrace» type=«tns:exceptionTrace»/>

<xs:element minOccurs=«0» name=«message» type=«xs:string»/>

</xs:sequence>

</xs:complexType>

</xs:schema>

</wsdl:types>

<wsdl:message name=«testService»>

<wsdl:part element=«tns:testService» name=«parameters»></wsdl:part>

</wsdl:message>

<wsdl:message name=«exceptionTestResponse»>

<wsdl:part element=«tns:exceptionTestResponse» name=«parameters»></wsdl:part>

</wsdl:message>

<wsdl:message name=«getGoods»>

<wsdl:part element=«tns:getGoods» name=«parameters»></wsdl:part>

</wsdl:message>

<wsdl:message name=«testServiceResponse»>

<wsdl:part element=«tns:testServiceResponse» name=«parameters»></wsdl:part>

</wsdl:message>

<wsdl:message name=«sayHelloTo»>

<wsdl:part element=«tns:sayHelloTo» name=«parameters»></wsdl:part>

</wsdl:message>

<wsdl:message name=«exceptionTest»>

<wsdl:part element=«tns:exceptionTest» name=«parameters»></wsdl:part>

</wsdl:message>

<wsdl:message name=«getGoodsResponse»>

<wsdl:part element=«tns:getGoodsResponse» name=«parameters»></wsdl:part>

</wsdl:message>

<wsdl:message name=«MyWebserviceException»>

<wsdl:part element=«tns:MyWebserviceException» name=«MyWebserviceException»></wsdl:part>

</wsdl:message>

<wsdl:message name=«sayHelloToResponse»>

<wsdl:part element=«tns:sayHelloToResponse» name=«parameters»></wsdl:part>

</wsdl:message>

<wsdl:portType name=«WebserviceSEI»>

<wsdl:operation name=«testService»>

<wsdl:input message=«tns:testService» name=«testService»></wsdl:input>

<wsdl:output message=«tns:testServiceResponse» name=«testServiceResponse»></wsdl:output>

</wsdl:operation>

<wsdl:operation name=«getGoods»>

<wsdl:input message=«tns:getGoods» name=«getGoods»></wsdl:input>

<wsdl:output message=«tns:getGoodsResponse» name=«getGoodsResponse»></wsdl:output>

</wsdl:operation>

<wsdl:operation name=«sayHelloTo»>

<wsdl:input message=«tns:sayHelloTo» name=«sayHelloTo»></wsdl:input>

<wsdl:output message=«tns:sayHelloToResponse» name=«sayHelloToResponse»></wsdl:output>

</wsdl:operation>

<wsdl:operation name=«exceptionTest»>

<wsdl:input message=«tns:exceptionTest» name=«exceptionTest»></wsdl:input>

<wsdl:output message=«tns:exceptionTestResponse» name=«exceptionTestResponse»></wsdl:output>

<wsdl:fault message=«tns:MyWebserviceException» name=«MyWebserviceException»></wsdl:fault>

</wsdl:operation>

</wsdl:portType>

<wsdl:binding name=«HelloSoapSoapBinding» type=«tns:WebserviceSEI»>

<soap:binding style=«document» transport=«http://schemas.xmlsoap.org/soap/http»/>

<wsdl:operation name=«testService»>

<soap:operation soapAction=«» style=«document»/>

<wsdl:input name=«testService»>

<soap:body use=«literal»/>

</wsdl:input>

<wsdl:output name=«testServiceResponse»>

<soap:body use=«literal»/>

</wsdl:output>

</wsdl:operation>

<wsdl:operation name=«getGoods»>

<soap:operation soapAction=«» style=«document»/>

<wsdl:input name=«getGoods»>

<soap:body use=«literal»/>

</wsdl:input>

<wsdl:output name=«getGoodsResponse»>

<soap:body use=«literal»/>

</wsdl:output>

</wsdl:operation>

<wsdl:operation name=«sayHelloTo»>

<soap:operation soapAction=«» style=«document»/>

<wsdl:input name=«sayHelloTo»>

<soap:body use=«literal»/>

</wsdl:input>

<wsdl:output name=«sayHelloToResponse»>

<soap:body use=«literal»/>

</wsdl:output>

</wsdl:operation>

<wsdl:operation name=«exceptionTest»>

<soap:operation soapAction=«» style=«document»/>

<wsdl:input name=«exceptionTest»>

<soap:body use=«literal»/>

</wsdl:input>

<wsdl:output name=«exceptionTestResponse»>

<soap:body use=«literal»/>

</wsdl:output>

<wsdl:fault name=«MyWebserviceException»>

<soap:fault name=«MyWebserviceException» use=«literal»/>

</wsdl:fault>

</wsdl:operation>

</wsdl:binding>

<wsdl:service name=«HelloSoap»>

<wsdl:port binding=«tns:HelloSoapSoapBinding» name=«HelloSoapPort»>

<soap:address location=«http://localhost:8080/soap/webserviceSEI»/>

</wsdl:port>

</wsdl:service>

</wsdl:definitions>


If an error occurs during processing, the response to a SOAP message is a SOAP fault element in the body of the message, and the fault is returned to the sender of the SOAP message.

The SOAP fault mechanism returns specific information about the error, including a predefined code, a description, and the address of the SOAP processor that generated the fault.

Points to Note

  • A SOAP message can carry only one fault block.

  • Fault is an optional part of a SOAP message.

  • For HTTP binding, a successful response is linked to the 200 to 299 range of status codes.

  • SOAP Fault is linked to the 500 to 599 range of status codes.

Sub-elements of Fault

The SOAP Fault has the following sub elements −

Sr.No Sub-element & Description
1

<faultCode>

It is a text code used to indicate a class of errors. See the next Table for a listing of predefined fault codes.

2

<faultString>

It is a text message explaining the error.

3

<faultActor>

It is a text string indicating who caused the fault. It is useful if the SOAP message travels through several nodes in the SOAP message path, and the client needs to know which node caused the error. A node that does not act as the ultimate destination must include a faultActor element.

4

<detail>

It is an element used to carry application-specific error messages. The detail element can contain child elements called detail entries.

SOAP Fault Codes

The faultCode values defined below must be used in the faultcode element while describing faults.

Sr.No Error & Description
1

SOAP-ENV:VersionMismatch

Found an invalid namespace for the SOAP Envelope element.

2

SOAP-ENV:MustUnderstand

An immediate child element of the Header element, with the mustUnderstand attribute set to «1», was not understood.

3

SOAP-ENV:Client

The message was incorrectly formed or contained incorrect information.

4

SOAP-ENV:Server

There was a problem with the server, so the message could not proceed.

SOAP Fault Example

The following code is a sample Fault. The client has requested a method named ValidateCreditCard, but the service does not support such a method. This represents a client request error, and the server returns the following SOAP response −

<?xml version = '1.0' encoding = 'UTF-8'?>
<SOAP-ENV:Envelope
   xmlns:SOAP-ENV = "http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:xsi = "http://www.w3.org/1999/XMLSchema-instance"
   xmlns:xsd = "http://www.w3.org/1999/XMLSchema">

   <SOAP-ENV:Body>
      <SOAP-ENV:Fault>
         <faultcode xsi:type = "xsd:string">SOAP-ENV:Client</faultcode>
         <faultstring xsi:type = "xsd:string">
            Failed to locate method (ValidateCreditCard) in class (examplesCreditCard) at
               /usr/local/ActivePerl-5.6/lib/site_perl/5.6.0/SOAP/Lite.pm line 1555.
         </faultstring>
      </SOAP-ENV:Fault>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Error Handling with SOAP Faults

SOAP errors are handled using a specialized envelope known as a

Fault Envelope. If an error occurs
while the server processes a SOAP message, it constructs a SOAP Fault
and sends it back to the client. Here’s a typical
SOAP 1.1 Fault:

<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:
xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/
XMLSchema">

<SOAP-ENV:Body>
    <SOAP-ENV:Fault>
        <faultcode>SOAP-ENV:Server</faultcode>
         <faultstring>Test Fault</faultstring>
         <faultactor>/soap/servlet/rpcrouter</faultactor>
         <detail>
            <stackTrace>[SOAPException: faultCode=SOAP-ENV:Server; msg=Test Fault]
            at StockQuantity.getQty(StockQuantity.java:21)
            at java.lang.reflect.Method.invoke(Native Method)
            at org.apache.soap.server.RPCRouter.invoke(RPCRouter.java:146)
            ...
            at org.apache.tomcat.util.ThreadPool$ControlRunnable.run(
                ThreadPool.java:501)
            at java.lang.Thread.run(Thread.java:498)
         </stackTrace>
         </detail>
     </SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

A SOAP Fault is a special element that must appear as an immediate
child of the SOAP body element. The
<faultcode> and
<faultstring> elements are required. The
<faultactor> and
<detail> elements are optional. Table 4-1 lists the possible values for the faultcodes
and their meanings.

Table 4-1. SOAP faultcodes

Faultcode

Meaning

VersionMismatch

The SOAP node processing the request encountered a version mismatch.
The namespace identifier of the SOAP envelope determines version
compatibility.

MustUnderstand

An immediate child element of the SOAP header (i.e.,
<MessageHeader>) contained a
MustUnderstand attribute with a setting of
true or 1. The SOAP processor
was not able to recognize the element or was not capable of
processing it.

DTDNotSupported

Introduced in SOAP 1.2 Working Draft 12/17/2001. It is an error for a
SOAP 1.2 envelope to contain a DTD.

DataEncodingUnknown

The soapEncodingStyle attribute specified is
unknown or not supported. It was also introduced in SOAP 1.2 WD
12/17/2001.

Client

The content generated by the client is incorrect or malformed.
Therefore, resending the same data will result in the same error. In
SOAP 1.2, this fault is being changed to Sender.

Server

The content sent by the client is perfectly acceptable, but the SOAP
processor is unable to process it for some reason, such as an
unavailable service. Resending the message at a later time could
result in success. In SOAP 1.2, this fault is being changed to
Receiver.

The body and Fault elements are namespace-qualified to the
envelope’s namespace—for example,
<SOAP-ENV:body> and
<SOAP-ENV:Fault>. The
<faultcode> element uses the local namespace
(it has no namespace prefix), and the
<faultcode> value that the element contains
is a qualified name using the envelope’s
namespace—for example,
<faultcode>SOAP-ENV:Client</faultcode>.

The SOAP Fault from the previous listing was achieved by making a
slight modification to the StockQuantity service.
In Apache SOAP, having the service throw
an exception is all that’s needed to generate a
fault; Apache takes care of the rest:

public class StockQuantity{

  public int getQty (String item) 
    throws org.apache.soap.SOAPException {

    int inStockQty = (int)(java.lang.Math.random(  ) * (double)1000);
    
    if (item.equalsIgnoreCase("Fail"))
        throw new org.apache.soap.SOAPException   
                      (org.apache.soap.Constants.FAULT_CODE_SERVER, 
                                "Test Fault");    

    return inStockQty;
   }
...
}

In Apache SOAP 2.2, this code is all that is necessary to send a
complete SOAP 1.1 Fault message back to the sender. To view the full
output of the Fault message, redirect the
CheckStock RPC call through the TunnelGui utility
by using the command:

java CheckStock -url http://localhost:5555/soap/servlet/rpcrouter -item Fail

In this command, 5555 is the port on which the
TunnelGui is listening. The RPC request and the corresponding SOAP
Fault can be viewed in the TunnelGui window, as shown in Figure 4-1.

A SOAP Fault viewed through the Apache TunnelGui utility

Figure 4-1. A SOAP Fault viewed through the Apache TunnelGui utility

The sending client can trap the Fault programatically and take
appropriate action. Apache
SOAP has a Fault object that can be used to access
the pieces of the Fault message, as indicated in this excerpt from
CheckStock:

    //Invoke the service
    Response resp = call.invoke (url,"urn:go-do-this");

    //Check the response
    if (resp != null) {
        if (resp.generatedFault (  )) {
                        Fault fault = resp.getFault (  );
            System.out.println ("Call failed due to a SOAP Fault: ");
            System.out.println ("  Fault Code   = " + fault.getFaultCode (  ));
            System.out.println ("  Fault String = " + fault.getFaultString (  ));

While the ability to generate a fault by throwing an exception is
handy, you may want more control over what goes into a fault message.
For example, Apache SOAP, by default, puts the current stacktrace
into the <detail> element of the SOAP fault.
That may not be what you want. We will explore how to build your own
Fault message in the context of the mustUnderstand
attribute.

Soap Faults and the mustUnderstand Attribute

To appreciate the meaning and role of the
mustUnderstand or misUnderstood
fault codes, one must first understand the intent of the
mustUnderstand attribute. This attribute can be
placed in any top-level header element. The presence of the
mustUnderstand attribute with a value of
true or 1 means that the header
element must be recognizable by the receiving SOAP processor. If the
SOAP processor does not recognize or know how to process the header
element, it must generate a Fault. We can generate a header element
with a mustUnderstand attribute by adding the
following line of code to our
GenericHTTPSoapClient:

            // Create a header element in a namespace
            org.w3c.dom.Element headerElement =
                doc.createElementNS(URI,"jaws:MessageHeader");
            headerElement.setAttributeNS(URI,"SOAP-ENV:mustUnderstand","1");

            // Create subnodes within the MessageHeader
            org.w3c.dom.Element ele = doc.createElement("From");
            org.w3c.dom.Text textNode = doc.createTextNode("Me");

This code creates a SOAP envelope that looks like this:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Header>
    <jaws:MessageHeader xmlns:jaws="urn:http://oreilly/jaws/samples"
        SOAP-ENV:MustUnderstand="1" >
        <From>Me</From>
        <To>You</To>
        <MessageId>9999</MessageId>
        ...
    </jaws:MessageHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
...
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

This envelope requires the server to understand the
<MessageHeader> element. Since the server
doesn’t understand these elements, it returns a SOAP
1.1 Fault message:

<?xml version='1.0' encoding='UTF-8'?>

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:
xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/
XMLSchema">
    <SOAP-ENV:Body>
         <SOAP-ENV:Fault>
         <faultcode>SOAP-ENV:MustUnderstand</faultcode>
         <faultstring>Unsupported header: jaws:MessageHeader</faultstring>
         <faultactor>/examples/servlet/FaultServlet</faultactor>
         </SOAP-ENV:Fault>
     </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The code used to generate this fault is in the following listing of
the FaultServlet class.
FaultServlet is a variation of our
HTTPReceive class. As part of the
header’s processing, we look for the existence of a
mustUnderstand attribute:

public class FaultServlet extends HttpServlet
{
...

    public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException
    {
    ...
           // Get the header and check it for mustunderstand
           Header header = env.getHeader(  );
           java.util.Vector headerEntries = header.getHeaderEntries(  );
                    
           screenWriter.write("nHeader==>n");
           for (java.util.Enumeration e = headerEntries.elements(  ); 
                            e.hasMoreElements(  );)
           {
               org.w3c.dom.Element el = (org.w3c.dom.Element)e.nextElement(  );
               org.apache.soap.util.xml.DOM2Writer.serializeAsXML(
                 (org.w3c.dom.Node)el, screenWriter);
                        
            // process mustUnderstand
               String mustUnderstand=
                        el.getAttributeNS(Constants.NS_URI_SOAP_ENV, 
                          "mustUnderstand");                  
               screenWriter.write("nMustUnderstand: " 
                + mustUnderstand + "n");

               String tagName = el.getTagName(  );    
               screenWriter.write("Tag Name: " + tagName + "n");

FaultServlet doesn’t support the
<MessageHeader> tag; it supports only the
<IOnlyUnderstandThis> tag. Therefore, we
must generate a fault when it sees the message header tag combined
with the mustUnderstand attribute. To construct
the fault, we create a SOAPException and use it to
create a new Fault object:

                  if(!tagName.equalsIgnoreCase("IOnlyUnderstandThis"))
                  {
                      //generate a fault.
                      screenWriter.write("Unsupported header: " + tagName + "n");
                      screenWriter.write("Generating Fault....n");
                      SOAPException se = 
                      new SOAPException(Constants.FAULT_CODE_MUST_UNDERSTAND, 
                               "Unsupported header: " + tagName);
                      Fault fault = new Fault(se);
                      fault.setFaultActorURI (request.getRequestURI (  ));
                            
                      String respEncStyle = Constants.NS_URI_SOAP_ENC;

Next, we create a Response object and supply it
with the Fault object that we created:

                      org.apache.soap.rpc.Response soapResponse = 
                      new org.apache.soap.rpc.Response (
                                 null,         // targetObjectURI
                                 null,         // methodName
                                 fault,
                                 null,         // params
                                 null,         // headers
                                 respEncStyle, // encodingStyleURI
                                 null);        // SOAPContext

Finally, we create an Envelope from the
Response object and marshall it into the
PrintWriter attached to the
servlet’s HTTPResponse:

                      Envelope faultEnvelope = soapResponse.buildEnvelope(  );  

                      org.apache.soap.encoding.SOAPMappingRegistry smr 
                           = new org.apache.soap.encoding.SOAPMappingRegistry(  );

                      PrintWriter resW = response.getWriter(  );

                      faultEnvelope.marshall(resW, smr,   
                          soapResponse.getSOAPContext(  ));
                      response.setContentType(request.getContentType(  )); 
                      response.setStatus(response.SC_INTERNAL_SERVER_ERROR);
                      ...
                      }
                  }

Note that in the SOAP 1.2 effort, there has been much debate over
whether mustUnderstand also means
“MustExecute” or
“MustProcess.”

SOAP 1.2 clarifies the use of the SOAP header in Fault processing.
The general idea is that the body of a Fault message should contain
only the errors that resulted from processing the body of the message
that caused the Fault. Likewise, detailed information about any
errors that occur as the result of processing a header block should
be placed in the header block of the resulting Fault message. The
<Fault> and
<Faultcode> elements still appear in the
body. However, the <Misunderstood> element
in the header carries detailed information about which header element
could not be recognized.

The SOAP 1.2 Fault message (generated from not being able to
understand the <MessageHeader> element in
our previous example) would look like this:

<env:Envelope xmlns:env='http://www.w3.org/2001/09/soap-envelope'
         xmlns:f='http://www.w3.org/2001/09/soap-faults' >
    <env:Header>
        <f:misunderstood qname="jaws:MessageHeader"
            xmlns:jaws="urn:http://oreilly/jaws/samples" />
       </env:Header>
    <env:Body>
        <env:Fault>
                   <faultcode>env:mustUnderstand</faultcode>
                   <faultstring>
                One or more mandatory headers not understood
            </faultstring>
           </env:Fault>
    </env:Body>
</env:Envelope>

SOAP 1.2 adds an additional set of fault codes. These RPC fault codes
use the new namespace identifier http://www.w3.org/2001/09/soap-rpc with the
namespace prefix of rpc:. The new
codes are listed in Table 4-2.

Table 4-2. SOAP 1.2 RPC fault codes

Fault code

Meaning

rpc:ProcedureNotPresent

The server can’t find the specified procedure.

rpc:BadArguments

The server can’t parse the arguments (or the
arguments don’t match what the server is expecting
for the procedure call).

env:DataEncodingUnknown

The encodingStyle attribute contained in either
the header or body is not supported.

Introduction

If you are working on integration development for Cloud Platform Integration (CPI), you have probably already used the SOAP receiver adapter with the request-reply pattern.

As long as everything works fine on the receiver side, it works fine on the CPI side, I get the SOAP response and can work with it. But in case of server errors, I noticed an undesirable behavior. SOAP Faults or error messages were not accessible for me, in the error subprocesses. The message body was simply empty, after the request-reply step.

Context

In my case, I have set up a web service call to a SOAP endpoint from SAP Process Orchestration (PO). The endpoint is configured to send an error message with details to the sender when an error occurs.

To accomplish this on SAP PO site, follow this SAP Note 2293430 – Processing error response at sender SOAP adapter – SAP ONE Support Launchpad

In the CPI I want to process these error details and display them to the responsible user. This did not work out of the box, the message text was always just empty after the error occurred.

First Attempts

The only thing I got was a generic message “Server Error” from the exchange object with the ${exception.message} operation.

Next I’ve tried a script for http error response extraction from ${property.CamelExceptionCaught} , mentioned on this help site:
Script Example for Exception Handling in HTTP Receiver – SAP Help Portal
But this script works only with HTTP exceptions, like

org.apache.camel.component.ahc.AhcOperationFailedException

It doesn’t work because we captured another object in this property during runtime. It is not AhcOperationFailedException, but an object of SoapFault class.

Adjusted Solution

I’ve stickend to the solution with a script and tried to adjust it to SOAP Fault objects.

——————————————————————–

org.apache.cxf.binding.soap

Class SoapFault extends Fault

Element getDetail()

Returns the detail node.

Element getOrCreateDetail()

Returns the detail node.

ref.: SoapFault (Apache CXF JavaDoc 3.2.0 API)

——————————————————————–

Those both functions provide an org.w3c.dom.Element, which is (unfortunately) not parsable by the CPI. You can set this Element as a new body and you will see the message body during trace. But operations (like XPath, Content Modifier) won’t work on your new message body. You will receive an error message like:

org.apache.camel.NoTypeConversionAvailableException: 
No type converter available to convert from type: com.sun.org.apache.xerces.internal.dom.ElementNSImpl 
to the required type: javax.xml.transform.sax.SAXSource

Serializing the org.w3c.dom.Element object to a simple String and set it as the message body, works great for the CPI.

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import org.w3c.dom.Node;
import groovy.xml.*

def Message processData(Message message) {
    def map = message.getProperties();
    def ex = map.get("CamelExceptionCaught");
    if (ex.getClass().getCanonicalName().equals("org.apache.cxf.binding.soap.SoapFault")) {
        def xml = XmlUtil.serialize(ex.getOrCreateDetail());
        message.setBody(xml);
    }
    
    return message;
}

– Improvements by Thomas Buerki 

Conclusion

This script gives me the ability to process the SOAP fault response with the usual XPath operations and even mappings. I can now distinguish between nodes and evaluate them individually.

I hope this script helps someone who is struggling with the same problem.

I am open for improvements, opinions and questions.

Cheers

Dennis Sentler

Понравилась статья? Поделить с друзьями:

Читайте также:

  • Soap error что это
  • Socket error 10065 no route to host штрих
  • Soap error parsing wsdl couldn t load from failed to load external entity
  • Socket error 10061 егаис
  • Socket error 10060 егаис

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии