/* * Copyright 2003-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * * @author Damitha Kumarage (damitha@opensource.lk, damitha@jkcsworld.com) * */ This README explains the test case of testing the Axis C++ fault mapping. It is recommended that you also read the README file of $AXISCPP_HOME/tests/server/exceptionTest/README Here I have generated the stuff using FaultMapping.wsdl. This wsdl simply have several complex types. One such type is DivByZeroStruct which consists of three simple types(xsd:int,* xsd:foat and xsd:string). For portType operation "div" we have a fault named DivByZero the message for which is DivByZeroFault which is of the complex type mentioned above(DivByZeroStruct). The server side for this client sample is in $AXISCPP_HOME/tests/server/exceptionTest. When you generated the client side it will generate header and implementation files for the following MathOps: Service request class which calls div service method in the server and getFaultDetails if there's any. DivByZeroStruct: The type corresponding to the complex type DivByZeroStruct in the MathOps.wsdl OutOfBoundStruct: The type corresponding to the complex type OutOfBoundStruct in the MathOps.wsdl SpecialDetailStruct:The type corresponding to the complex type SpecialDetailStruct in the MathOps.wsdl AxisClientException: We generate an client side exception class which is derived from AxisException base class which is the root class for exceptions in Axis C++. This root class in term is derived from std::exception. In the server side if division by zero fault is encountered in the service class, service method it will ... ... DivByZeroStruct* pObjFault = new DivByZeroStruct(); if(pObjFault) { pObjFault->varString = "Division by zero exception"; pObjFault->varInt = 1; pObjFault->varFloat = 10.52; throw objFault; } ... ... Now in the service wrapper class after catching the struct thrown above ... ... pIWSSZ->createSoapFault("DivByZeroStruct", "http://soapinterop.org/wsdl", "Axis C++ Fault Code", "Custom Div By Zero Exception"); ... ... where pIWSSZ is the soap serializer interface. Once this method is called m_pSoapEnvelope->m_pSoapBody->m_pSoapFault is assigned a new soap fault object. After that, ... ... pIWSSZ->addFaultDetail(pObjFault, (void*) Axis_Serialize_DivByZeroStruct, (void*) Axis_Delete_DivByZeroStruct,"DivByZero", Axis_URI_DivByZeroStruct); ... ... Here the it call SoapSerialzer's addFaultDetail method with the knowledge of serializing and deserializing. Once this method is called setFaultDetail method of SoapFault is called from SoapSerializer. ... ... int SoapFault::setFaultDetail(const Param* pFaultDetail) { m_pFaultDetail = (Param*) pFaultDetail; return AXIS_SUCCESS; } ... ... So once the serialize method of SoapSerializer is called then in addition to serializing Faultcode, Faultstring and Faultactor, SoapFault's FaultDetail object is also serialized into the soap body's fault detail tag. So in the wire comes the Soap message with a soap fault. Now when you run the client here, if it catch an exception ... ... catch(AxisException& e) { int iExceptionCode = e.getExceptionCode(); if(AXISC_NODE_VALUE_MISMATCH_EXCEPTION != iExceptionCode) { throw; } ... ... it checks the exception code and if exception code is not equal to AXISC_NODE_VALUE_MISMATCH_EXCEPTION value it means that the exception thrown not because of a soap fault. Exception is caused by some other mean in the client side. If a soap fault comes in the wire SoapDeseriazer's checkMessageBody method throws and exception ... ... throw AxisGenException(AXISC_NODE_VALUE_MISMATCH_EXCEPTION); ... ... When we catch that exception we knows that a soap fault has come. ... ... pcCmplxFaultName = pSoapFault->getCmplxFaultObjectName().c_str(); //printf("pcCmplxFaultName:%s\n", pcCmplxFaultName); if(0 == strcmp("DivByZeroStruct", pcCmplxFaultName)) { DivByZeroStruct* pFaultDetail = NULL; pFaultDetail = (DivByZeroStruct*)pSoapFault-> getCmplxFaultObject((void*) Axis_DeSerialize_DivByZeroStruct, (void*) Axis_Create_DivByZeroStruct, (void*) Axis_Delete_DivByZeroStruct,"DivByZeroStruct", 0); pSoapFault->setCmplxFaultObject(pFaultDetail); m_pCall->unInitialize(); throw AxisClientException(pSoapFault); } ... ... Note that we compares pcCmplxFaultName which contains complex soap fault's name with the DivByZeroStruct. ... ... When the AxisClientException is thrown from the MathOps.cpp, it will be caught from MathOpsClient.cpp, the file we wrote containing the main method. Inside the AxisClientException class's processException(ISoapFault* pFault) method we might write the code to translate the pSoapFault information into a descriptive string. ... ... /*User can do something like deserializing the struct into a string*/ const char* pcCmplxFaultName; const char* pcDetail; if(pFault) { m_sMessage = "Fault Code:"; m_sMessage += pFault->getFaultcode(); m_sMessage += "\n"; m_sMessage += "Fault String:"; m_sMessage += pFault->getFaultstring(); m_sMessage += "\n"; m_sMessage += "Fault Actor:"; m_sMessage += pFault->getFaultactor(); m_sMessage += "\n"; pcDetail = pFault->getSimpleFaultDetail().c_str(); if(NULL != pcDetail && 0 != strcmp("", pcDetail)) m_sMessage += pcDetail; else { pcCmplxFaultName = pFault->getCmplxFaultObjectName().c_str(); //printf("pcCmplxFaultName:%s\n", pcCmplxFaultName); } if(0 == strcmp("OutOfBoundStruct", pcCmplxFaultName)) { OutOfBoundStruct* pFaultDetail = NULL; pFaultDetail = (OutOfBoundStruct*)pFault-> getCmplxFaultObject(); SpecialDetailStruct* pSpecialFaultDetail = pFaultDetail->specialDetail; m_sMessage += pFaultDetail->varString; m_sMessage += ":"; m_sMessage += pSpecialFaultDetail->varString; } else if(0 == strcmp("SpecialDetailStruct", pcCmplxFaultName)) { SpecialDetailStruct* pFaultDetail = NULL; pFaultDetail = (SpecialDetailStruct*)pFault-> getCmplxFaultObject(); m_sMessage += pFaultDetail->varString; } else if(0 == strcmp("DivByZeroStruct", pcCmplxFaultName)) { DivByZeroStruct* pFaultDetail = NULL; pFaultDetail = (DivByZeroStruct*)pFault-> getCmplxFaultObject(); char* carrTempBuff =new char[4 * sizeof(char)]; sprintf(carrTempBuff, "%d", pFaultDetail->varInt); m_sMessage += string(carrTempBuff); m_sMessage += "\n"; ... ... In order to test the sample you need to do the following To test the DivByZero exception ./mathops localhost 80 div 10 0 //You pass the second parameter zero To test the OutOfBound exception ./mathops localhost 80 div 10 -5 //You pass one parameter negative To test the NormalDetail exception ./mathops localhost 80 div 1000 5 //You pass the first parameter 1000