Hello!
I believe the generated code (option -j) does not work with empty request messages. I have a patched WS-Transfer wsdl file with only a Get-Operation that returns Metadata according WS-Mex. The function definition in (wsdl2h generated) gSOAP header file looks like the following:
//gsoap wst4 service method-style: Get document
//gsoap wst4 service method-encoding: Get literal
//gsoap wst4 service method-action: Get http://schemas.xmlsoap.org/ws/2004/09/transfer/Get
int __wst4__Get(
_wsx4__Metadata* wsx4__Metadata ///< Response parameter
);
Using code generation (with option -j) generates the following request xml file:
<SOAP-ENV:Header>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
</SOAP-ENV:Body>
It is correct without any element within the SOAP body. Anyhow, in the generated dispatch() function the operation is missing after the soap_peek_element() call (see below)!
Aditionally there is a soap_get___wst4__Get() call in the serve___wst4__Get() function that always returns 3 (SOAP_TAG_MISMATCH). This is not surprising, since there is no element within the SOAP body. The following snippet is from the <name>Service.cpp file:
static int serve___wst4__Get(TransferBindingService*);
int TransferBindingService::dispatch()
{ TransferBindingService_init(this->soap->imode, this->soap->omode);
soap_peek_element(this->soap);
return this->soap->error = SOAP_NO_METHOD;
}
static int serve___wst4__Get(TransferBindingService *service)
{ struct soap *soap = service->soap;
struct __wst4__Get soap_tmp___wst4__Get;
_wsx4__Metadata wsx4__Metadata;
wsx4__Metadata.soap_default(soap);
soap_default___wst4__Get(soap, &soap_tmp___wst4__Get);
soap->encodingStyle = NULL;
if (!soap_get___wst4__Get(soap, &soap_tmp___wst4__Get, "-wst4:Get", NULL))
return soap->error;
if (soap_body_end_in(soap)
|| soap_envelope_end_in(soap)
|| soap_end_recv(soap))
return soap->error;
soap->error = service->Get(&wsx4__Metadata);
...
Thanks,
Steph
Try gSOAP 2.8.4 because a similar problem was reported and fixed. Hope this fix in 2.8.4 will work for you.
The problem still remains in gsoap 2.8.4. My compiler warns that the function was declared but never referenced:
warning (etoa:4177): function 'serve___wst4__Get' was declared but never referenced
static int serve___wst4__Get(TransferBindingService *service)
Current work around for me is to
- manually remove the static in front of the function's declaration and definition
- comment out the soap_get___wst4__Get() (whole if statement) and
- avoid using the dispatch function by calling serve___wst4__Get directly in case of a matching soap action.
Patch:
In src/symbol2.c:4519 in function gen_object_code():
}
else
catch_method = method;
}
move the else clause one level down:
}
}
else
catch_method = method;
The fix will be implemented in the upcoming 2.8.5 release.
stripped wsdl file that produces the bug
Still does not work. I attached a stripped version of the wsdl file.
Tested against your previous WSDL and that worked. In fact, now no soapcpp2 option (-i or -j) will help for your new example.
To enable this, change the code so that catch_method is set in the else's for two if-then-else branches:
}
else
catch_method = method;
}
else
catch_method = method;
}
The two functions to change in src/symbol2.c are: soap_serve() and gen_object_code() and make sure that in the latter to code output is correct as follows:
if (catch_method)
fprintf(fd, "\n\treturn serve_%s(this);\n}", ident(catch_method->sym->name));
Thanks for the help so far, but is only fixed half.
In the generated (-j) dispatch function the serve function is now correctly inserted (and called at runtime).
The second problem still exists: soap_get___wst4__Get() is still called in the serve___wst4__Get() function. Since the request does not contain an element within the SOAP body this call failed with SOAP_TAG_MISMATCH.
You say "The second problem still exists: soap_get___wst4__Get() is still called in the serve___wst4__Get() function. Since the request does not contain an
element within the SOAP body this call failed with SOAP_TAG_MISMATCH."
But this is the purpose of the soap_get_xyz method! To accept a message without a body and produce a response in your service operation. If that does not work in your case, then the service definition requires an element that is not there. Please check your code. Note that "-wst4:Get" does not parse an element, due to the leading "-". However, if the "Get" operation requires operands, then this will surely fail.
I still believe there is a bug.
soap_get___wst4__Get() calls soap_in___wst4__Get(), but this function always returns NULL (see below). This NULL is passed back to the original soap_get___wst4__Get() call that is why this function call fails with SOAP_TAG_MISMATCH.
SOAP_FMAC3 struct __wst4__Get * SOAP_FMAC4 soap_in___wst4__Get(struct soap *soap, const char *tag, struct __wst4__Get *a, const char *type)
{
a = (struct __wst4__Get *)soap_id_enter(soap, "", a, SOAP_TYPE_DSC___wst4__Get, sizeof(struct __wst4__Get), 0, NULL, NULL, NULL);
if (!a)
return NULL;
soap_default___wst4__Get(soap, a);
soap->error = SOAP_TAG_MISMATCH;
a = NULL;
return a;
}
soap_id_enter() has the following debug output:
Enter id='' type=164 loc=0012FDDF size=1 level=0
Which seems to be correct for me, since 164 is the correct type:
#ifndef SOAP_TYPE_DSC___wst4__Get
#define SOAP_TYPE_DSC___wst4__Get (164)
/* Operation wrapper: */
struct __wst4__Get
{
#ifdef WITH_NOEMPTYSTRUCT
private:
char dummy; /* dummy member to enable compilation */
#endif
};
#endif
In gSOAP 2.8.2 the corresponding code in symbol2.c was changed: http://gsoap2.svn.sourceforge.net/viewvc/gsoap2/gsoap/src/symbol2.c?annotate=9#l10416
When removing these two lines that generate:
soap->error = SOAP_TAG_MISMATCH;
a = NULL;
it works for me. (They appear twice, once for structs and once for class types lines 10905f in gSOAP 2.8.2)
The reason for the change that you observed was to fix an infinite loop when the deserializer does not consume any input, which happens when parsing a vector of elements with no content and no element tag name (empty wrappers). The Get() operation is an empty wrapper. So some additional non-trivial logic will be needed to keep the fix in place while handling the empty wrapper service operation. I will take a closer look and update the code generator.
Fixed. Download the patched file from SVN gsoap/src/symbol2.c