A Web service returns a fault message to the client to report an error. SOAP 1.1 allows a server to distinguish between faults that result from incorrect input, client faults, and faults that originate in the server, server faults.
fA client proxy throws rwsf::ClientFault in response to a SOAP fault message from the server. The server throws both rwsf::ClientFaults and rwsf::ServerFaults.
For instances of both rwsf::ClientFault and rwsf::ServerFault, the rwsf::Fault.getFaultString() method retrieves the SOAP fault, while rwsf::Fault.getFaultCode() method returns from the server an enum rwsf:: FaultCode. The FaultCode defines whether this is a client fault or a server fault. A SOAP 1.1 server returns a Client fault when a request is invalid. If a request results in a Client fault, sending the same request again will result in another Client fault. In contrast, a server returns a Server fault to indicate a problem unrelated to the content of the request. If the application sends the same request again, the request may succeed.
For example, the code sample below translates an exception resulting from invalid client input into a client fault.
rwsf::Decimal AccountServlet::getAccountBalance(const std::string& user, const std::string& password) { try { Account acct(user, password); return acct.getBalance(); } catch (const AccountInvalidLoginError& e) { throw rwsf::ClientFault(e.why()); } }
Note that the sample translates a specific exception type to a client fault. The function propagates any other type of exception, so any other exception will result in a server fault.
For WSDL-defined faults, see Section 8.3.1.
HydraExpress generates code to facilitate fault handling for any faults defined in the WSDL. HydraExpress generates a class for each defined fault message element, with the name of the class being the message name with the string _message appended: message-name_message.
Each class contains the following datatypes, with their corresponding accessor methods:
a fault code, corresponding to the code element required in SOAP fault messages
a fault string, corresponding to the human-readable string element required in SOAP fault messages
one or more message parts, corresponding to the parts specified for this fault message type in the WSDL. These message parts become entries in the detail element of the SOAP message.
If the WSDL defines fault messages, the generated client-side sample application includes catch blocks for each operation, with one block for each defined message element.
To better understand this connection, let's look at how a fault gets defined in the WSDL. First, the WSDL defines a message element to be used by the fault:
<message name='AFaultMessage'> <part name='MessageString' type='xsd:string'/> </message>
Then the message element is used in defining a fault in the portType definition:
<portType name='SomeService'> <operation name='someOperation'> <input message='xyz:SomeService_doSomething' /> <output message='xyz:SomeService_doSomethingResponse' /> <fault name='SOME_FAULT' message='xyz:AFaultMessage' /> </operation> </portType>
Finally, the portType fault definition is used in the binding to define a SOAP fault:
<binding name='SomeServiceBinding' type='xyz:SomeService'> <soap:binding style='document' transport='http://schemas.xmlsoap.org/soap/http' /> <operation name='someOperation'> <soap:operation soapAction='http://www.abc.com/xyz/anAction' /> <input/> <output/> <fault> <soap:fault name='SOME_FAULT' encodingStyle='http://schemas/xmlsoap.org/soap/encoding/' namespace = 'http://www.abc.com/xyz/wsdl' use='literal' /> </fault> </operation> </binding>
The generated client sample application would then include the following code to catch and display this type of fault message:
try { proxy.someOperation(inputParameter); } catch(AFaultMessage_message& e) { std::cout << "Fault Code: " << e.getFaultCodeAsString() << std::endl; std::cout << "Fault String: " << e.getFaultString() << std::endl; std::string MessageString = e.getMessageString(); // Handle the detail entry ... //1 } // Catch blocks for other WSDL-defined message types. // ... // These final blocks catch other general faults. catch (const rwsf::Exception& x) { std::cerr << "Error invoking web service: " << x.why() << std::endl; } catch(std::exception& e) { std::cerr << "Error invoking web service: " << e.what() << std::endl; } catch(RWxmsg& e) { //2 std::cerr << "Error invoking web service: " << e.what() << std::endl; } catch(...) { std::cerr << "Unknown exception thrown" << std::endl; }
//1 | Do whatever you are going to do with the MessageString data. |
//2 | Required only for code generated with the -sourcepro option. |
As you can see, the generated code does not attempt to guess how the detail entry of the SOAP message needs to be handled. This entry can be anything from a simple string to a complex data element, so the service developer is the person in the best position to know how it must be handled.
In the server implementation, you can detect any errors you want to watch for in your service and return them to the client as one of the defined fault messages. Simply construct the desired fault message type instance and throw it. The fault is caught in the message handler, which constructs a SOAP fault message and sends it to the client.
Here is some code that demonstrates how to throw a fault in the server implementation:
throw AFaultMessage_message("This is the explanation of the fault", rwsf::XmlName("Server",rwsf::XmlNamespace("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/")), "Error: some kind of fault");
The rwsf::XmlName parameter inserts a server fault code in the SOAP fault message. To construct a standard server fault, define the parameter exactly as shown here. The first string parameter becomes the detail entry of the SOAP fault message, and the last string parameter becomes the human-readable fault string entry.
©2004-2007 Copyright Quovadx, Inc. All Rights Reserved.
Quovadx and Rogue Wave are registered trademarks of Quovadx, Inc. in the United States and other countries. All other trademarks are the property of their respective owners.
Contact Rogue Wave about documentation or support issues.