Handling SOAP fault-s in Axis2/C

The example in this document implements a simple division service: the client sends two integers, and the server sends back their quotient. If the divisor is zero, the server sends back a custom SOAP fault with the following body:

<message>
    Division by zero
</message>

The complication with Axis2/C is that C has no exception mechanism, and the generated code does not support retrieving of the fault object in case of error. If the server sends fault, the client side service stub method returns NULL, and we need to dig out the fault object directly from the SOAP envelope, by using the AXIOM XML parsing facilities. However, Axis2/C does generate serializer, deserializer, getters and setters for the fault objects, so we need to cross the gap between the SOAP envelope and the deserielizer only.

Building the example

In this document, I do not explain the details of the steps of building and deploying the code, see the details in the Axis2/C documentation.

  • First, create the Axis2/C development and runtime environment by Axis2SetUp. As for Axis2/Java, follow Method 1.
  • Download the example:

wget https://twiki.cern.ch/twiki/pub/EGEE/Axis2SoapFault/division.tgz
tar -zxf division.tgz

  • Generate the client stub and databinding code for the client:
pushd division/client
WSDL2C.sh -uri ../Division.wsdl -u -d adb

The sources were generated in the src directory. For the description of the command line flags, see

WSDL2C.sh --help

  • Build the client:

make div

  • Build and deploy the server:

popd
pushd division/server
make div
mkdir -p $AXIS2C_HOME/services/division
cp libdivision.so services.xml $AXIS2C_HOME/services/division

  • Try it. Open two terminal windows, make sure that the environment variables specified in Axis2SetUp are set in both terminals. Start the server:

cd $AXIS2C_HOME/bin
./axis2_http_server

This will pick up the service code compiled to

libdivision.so

  • Try the client with two set of parameters (in the other terminal):

cd division/client
./div 10 2
./div 10 0

The first should print

Result: div (10 2 ) = 5

The second should display the fault message that the server returns:

FAULT occurred: Division by zero

The client also prints the fault XML for the curious minds...

Some explanation

Client side

On the client side, the trick is in

division/client/div.c:get_fault_message

See the code comments for the details, as well as the Axis2/C API document. The API document was created when you compiled Axis2/C, but you can also download from here. In general what we need to do is:

  • Check if the last server response really contains a fault.
  • Retrieve the SOAP envelope encoding the response (fault).
  • Fetch the SOAP body from the envelope
  • Fetch the fault XML from the SOAP body. It looks about like (plus namespaces, and other subtleties):

    <detail>
        <divFault>
            <message>
                Division by zero
            </message>
        </divFault>
   </detail>

  • Using the AXIOM XML parser, get the "detail" node
  • Get the "divFault" node.
  • The content of "divFault" can be deserialized by the generated code in
    src/adb_divFault.c
    Use the deserializer to build the fault object.
  • Using the message getter function, get the fault string.

Mind, that the code is not complete, as it is not defensive: never checks the validity of the return values. I ignored them in purpose, to demonstrate the point.

Server side

On the server side, the situation is more complicated. The server side code was generated with the following command:

pushd division/server
WSDL2C.sh -uri ../Division.wsdl -u -d adb -ss

The implementation of the service method should go to the generated src/axis2_skel_Division.c file. We moved this file to server/division.c, and implemented the service logic. In case of normal behavior, the service function (axis2_skel_Division_div) should return an adb_divResponse_t object, containing the server response. In case of fault, the function must return NULL. In this case, the web service engine calls the (also generated) axis2_svc_skel_Division.c : axis2_svc_skel_Division_on_fault function. It is set as a static and constant callback, we cannot change it in runtime. The function just sends a specific, static fault string that has nothing to to with the divFault object. In order to make the example usable, we needed to hack the generated code: removed the generated implementation of axis2_svc_skel_Division_on_fault and reimplemented it in division.c: it serializes an adb_divFault object instead of the default one.

UPDATE: The good news is that on 9 February, the Axis2/C developers checked in a code generator version that explicitly supports the custom fault objects. See the details in one of their developer's blog.

-- ZsoltMolnar - 26 Jan 2009

Topic attachments
I Attachment History Action Size Date Who Comment
Compressed Zip archivetgz axis_api.tgz r1 manage 1592.5 K 2009-02-10 - 10:38 ZsoltMolnar Axis2/C API document
Compressed Zip archivetgz division.tgz r1 manage 15.4 K 2009-02-10 - 10:05 ZsoltMolnar Example division service and client
Edit | Attach | Watch | Print version | History: r3 < r2 < r1 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r3 - 2009-02-19 - ZsoltMolnar
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    EGEE All webs login

This site is powered by the TWiki collaboration platform Powered by Perl This site is powered by the TWiki collaboration platformCopyright & by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Ask a support question or Send feedback