Thank Dimuthu.
I am able to get the soap fault xml from the ret_node in the generated stub 
code.
Now I just created C++ class to include the generated stub code and parsing the 
soap fault xml to throw my own exception.
I hope WSDL2C may generate C++ code instead C for exception handling. 
Basically I added call to the following method at every stub method to throw my 
own exception for service side fault: ExceptionEntry.
Thanks,
 
Jay

{
    axis2_svc_client_t* svc_client = 
axis2_stub_get_svc_client(m_serviceClientp, _envp );
    {
        string fault_string = 
        axutil_qname_t *qname = NULL;
        adb_ExceptionEntry* exception_entry = NULL;
        axiom_element_t* response_element = (axiom_element_t 
*)axiom_node_get_data_element(response_node, _envp);
        {
            axiom_node_t *child_nodep = 
axiom_node_get_first_child(response_node, _envp);
            {
                axiom_types_t type_id = axiom_node_get_node_type(child_nodep, 
_envp);
                {
                    axiom_element_t* child_elementp = 
(axiom_element_t*)axiom_node_get_data_element(child_nodep, _envp);
                    qname = axiom_element_get_qname(child_elementp, _envp, 
child_nodep);
                    axutil_qname_get_uri(qname, _envp),
                    axutil_qname_get_prefix(qname, _envp),
                    axutil_qname_get_localpart(qname, _envp),
                    axutil_qname_to_string(qname, 
_envp));voidWcfClient::checkResponse(axiom_node_t *response_node)    if( 
axis2_svc_client_get_last_response_has_fault(svc_client, _envp) )"";        if( 
NULL != response_element )            while( ! child_nodep )                if( 
type_id == AXIOM_ELEMENT )                    string element_name = 
axutil_qname_get_localpart(qname, _envp);
                    {
                        fault_string = axiom_element_get_text(child_elementp, 
_envp, child_nodep);
                    }
                        exception_entry = adb_ExceptionEntry_create(_envp);
                        {
                            adb_ExceptionEntry_free(exception_entry, _envp);
                            exception_entry = NULL;
                        }
                    }
                }
                child_nodep = axiom_node_get_next_sibling(child_nodep, _envp);
            }
        }
        {                    if( element_name == "faultstring")                 
   elseif( element_name == "ExceptionEntry")                    {               
         if( adb_ExceptionEntry_deserialize(exception_entry, _envp, 
&child_nodep, NULL, AXIS2_FALSE ) == AXIS2_FAILURE)                        
break;        if( NULL != exception_entry )            // found ExceptionEntry 
from Service            EgWcfServiceException exceptionEntry;
            exceptionEntry._stackTrace = 
adb_ExceptionEntry_get__stackTrace(exception_entry, _envp);
            exceptionEntry._innerException = 
adb_ExceptionEntry_get__innerException(exception_entry, _envp);
            exceptionEntry._errorCode = 
adb_ExceptionEntry_get__errorCode(exception_entry, _envp);
            exceptionEntry._externalErrorCode = 
adb_ExceptionEntry_get__externalErrorCode(exception_entry, _envp);
            exceptionEntry._externalErrorSource = 
adb_ExceptionEntry_get__externalErrorSource(exception_entry, _envp);
        } 
        {
            EG_EXCEPTION_1(fault_string.c_str());
        }             throwexceptionEntry;elseif( fault_string.length() > 0 
)        else        {
            EG_EXCEPTION_1(
        }
    }
}"Caught unknown exception in WCF service reponse");


----- Original Message ----
From: Dimuthu Gamage <[EMAIL PROTECTED]>
To: Apache AXIS C User List <[email protected]>
Sent: Tuesday, August 5, 2008 9:59:36 AM
Subject: Re: Question about receiving custom Fault object at Axis2/C client


Hi Jay,
Unfortunately still WSDL2C doesn't support custom faults. Anyway you have done 
the workaround correctly. using the _deserialize function you should be able to 
get the adb object corresponding to the fault detail. Did you try printing the 
xml corrosponding to the batch_fault_nodep, is it have the correct xml we 
expecting (the node inside the fault details node?. If so what the error log 
say about the failure on deseriazing. It should have some details.

Thanks
Dimuthu


On Thu, Jul 31, 2008 at 6:44 PM, Jay Qiu <[EMAIL PROTECTED]> wrote:

Hello,

We are trying to build a C++ client to connect to WCF services using 
basicHttpBinding.

I am able to use WSDL2C to generate the C++ stub and use the stub calls to send 
request to the service and get result object back.
But I am unable to get the Fault object back. It seems to me the generated stub 
can not handle the Soap Fault object.
I am wondering if any one can give me some help for receiving Fault object.

My service WSDL contains the service call GetData(string) and fault class 
BatchService:
   <wsdl:binding name="WSHttpBinding_IBatchService" type="i0:IBatchService">
    <wsp:PolicyReference URI="#WSHttpBinding_IBatchService_policy" />
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http"; />
    <wsdl:operation name="GetData">
      <soap12:operation soapAction="" style="document" />
      <wsdl:input>
        <wsp:PolicyReference 
URI="#WSHttpBinding_IBatchService_GetData_Input_policy" />
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <wsp:PolicyReference 
URI="#WSHttpBinding_IBatchService_GetData_output_policy" />
        <soap12:body use="literal" />
      </wsdl:output>
      <wsdl:fault name="BatchFaultFault">
        <wsp:PolicyReference 
URI="#WSHttpBinding_IBatchService_GetData_BatchFaultFault_Fault" />
        <soap12:fault use="literal" name="BatchFaultFault" namespace="" />
      </wsdl:fault>
    </wsdl:operation>
</wsdl:binding>

WSDL2C does generate the following files:
    axis2_stub_BatchService.[hc]
    adb_GetData.[hc]
    adb_BatchFault.[hc]

However the stub request function axis2_stub_op_BatchService_GetData() inside 
the geratated file axis2_stub_BatchService.c does not check if there is any 
fault. The function has the following lines:
            ret_node =  axis2_svc_client_send_receive_with_op_qname( 
svc_client, env, op_qname, payload);
            ret_val = adb_GetDataResponse_create(env);
            if(adb_GetDataResponse_deserialize(ret_val, env, &ret_node, NULL, 
AXIS2_FALSE ) == AXIS2_FAILURE)

If the soap xml is BatchFault instead of regular return object, the  
adb_GetDataResponse_deserialize() call would fail and 
axis2_stub_op_BatchService_GetData() call return NULL. Thus We are unable to 
get the Fault information.

If I add "xml =  axiom_node_sub_tree_to_string(ret_node, env);" after the line 
of
    ret_node =  axis2_svc_client_send_receive_with_op_qname( svc_client, env, 
op_qname, payload);

I do see the return XML as:
    <s:Fault xmlns:s="http://schemas.xmlsoap.org/soap/envelope/";>
        <faultcode>s:Client</faultcode>
        <faultstring         xmlns:xml="http://www.w3.org/XML/1998/namespace"; 
xml:lang="en-US">
            The creator of this fault did not specify a Reason.</faultstring>
        <detail>
            <BatchFault 
xmlns="http://schemas.datacontract.org/2004/07/eGlue.WCF.Common"; 
xmlns:i="http://www.w3.org/2001/XMLSchema-instance";>
                <ErrorCode>1</ErrorCode>
                <ErrorMessage>Batch Fault: Input value is too big. Expected 
value is less than 1000</ErrorMessage>
            </BatchFault>
        </detail>
    </s:Fault>
So should the stub provide some mechnism to return the custom Fault object or 
throw exception of custom Fault object?

Also I tried to modify the generated stub code to get the BatchFault object 
from the return node. But I am still unable to deserialize into BatchFault 
object.
Both xmls for subtree of <detail> and <BatchFault> are empty and 
adb_BatchFault_deserialize() call fails also. Can you please check what is 
wrong in my code?

The code that I added into axis2_stub_op_BatchService_GetData() function is as 
following:
   if(adb_GetDataResponse_deserialize(ret_val, env, &ret_node, NULL, 
AXIS2_FALSE ) == AXIS2_FAILURE)
    {
      if ( axis2_svc_client_get_last_response_has_fault(svc_client, env) )
      {
       axiom_element_t* data_element = axiom_node_get_data_element(ret_node, 
env);
       if ( data_element != NULL )
       {
        adb_BatchFault_t* fault = NULL;
        axutil_qname_t* detail_qname = NULL;
        axutil_qname_t* batch_fault_qname = NULL;
        axiom_element_t * detail_elementp = NULL;
        axiom_node_t * detail_nodep = axiom_node_create(env);
        axiom_element_t * batch_fault_elementp = NULL;
        axiom_node_t * batch_fault_nodep = axiom_node_create(env);
        detail_qname = axutil_qname_create(env, "detail", NULL, "");
        batch_fault_qname = axutil_qname_create(env, "BatchFault", NULL, "");
        
        detail_elementp = 
axiom_element_get_first_child_with_qname(data_element, env, detail_qname,  
ret_node, &detail_nodep);
        if ( detail_elementp != NULL )
        {
         xml =  axiom_node_sub_tree_to_string(detail_elementp, env);
         batch_fault_elementp = 
axiom_element_get_first_child_with_qname(detail_elementp, env, 
batch_fault_qname,  ret_node, &batch_fault_nodep);
         if ( batch_fault_elementp != NULL )
         {
          xml =  axiom_node_sub_tree_to_string(batch_fault_elementp, env);
          fault = adb_BatchFault_create(env);
          if ( adb_BatchFault_deserialize(fault, env, &batch_fault_nodep, NULL, 
AXIS2_FALSE ) == AXIS2_FAILURE)
          {
           printf("Got unknown exception" );
          }
          else {
           printf("BatchFault: %s\n", adb_BatchFault_get_ErrorMessage(fault, 
env));
          }         
        }
      }

Thank you very much for your help.

Jay




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


      

Reply via email to