gsoap does not generate C++ proxy classes - c++

I've generated an XSD from a set of example request files for an XML web service (using Xmplify - but I doubt that's important).
When I run this through gsoap, I get no errors or warnings, but even with -i or -j option on soapcpp2, I get no C++ proxy files generated (eg soapProxy.h).
Only the following files are generated:
ns1.nsmap
request.h
soapC.cpp
soapH.h
soapStub.h
Commands used:
wsdl2h request.xsd
soapcpp2 -i -C -I/usr/local/share/gsoap/import request.h
I figure there is something specific about the XSD required in order to generate these?
How do I get the proxy files generated? I know I can use without proxy objects, but it looks a lot more messy!
Schema doc is included below.
Thanks for any advice!
Phil.
<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' elementFormDefault='unqualified'>
<xs:element name='REQUEST'>
<xs:complexType>
<xs:sequence>
<xs:element ref='USERTOKEN'/>
<xs:element ref='ACTION'/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name='USERTOKEN'>
<xs:complexType>
<xs:sequence>
<xs:element ref='USERKEY'/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name='USERKEY' type='xs:NCName'/>
<xs:element name='ACTION'>
<xs:complexType>
<xs:sequence>
<xs:element minOccurs='0' ref='PARAMETER'/>
</xs:sequence>
<xs:attribute name='NAME' use='required' type='xs:NCName'/>
</xs:complexType>
</xs:element>
<xs:element name='PARAMETER'>
<xs:complexType mixed='true'>
<xs:attribute name='NAME' use='required' type='xs:NCName'/>
</xs:complexType>
</xs:element>
</xs:schema>

The wsdl2h tool does not generate proxy and service code for XSD files, since there are no operations defined in these (only in WSDL). You can use the gSOAP-generated (de)serializers for the XSD root elements to send/recv XML data that is (de)serialized from the C++ data types. For example
#include "ns1.nsmap" // ns1 namespaces etc
struct soap *ctx = soap_new();
ns1__REQUEST r;
r.soap_default(ctx); // reset content
r.USERTOKEN = … // set r's content as needed
ctx.os = … // set the output stream
soap_write_ns1__REQUEST(ctx, &r); // serialize REQUEST
You can send/recv data over streams, sockets, etc.

Related

XSD: Converting set of elements into array of complex types

Looking for someone to correct me.
I'm building transformation in custom system to finally get a JSON request Online Meeting
Start XML:
<participants>
<attendees>
<upn>testworkemail1#gmail.com</upn>
<role>Presenter</role>
</attendees>
<attendees>
<upn>testworkemail2#gmail.com</upn>
<role>Presenter</role>
</attendees>
</participants>
modifying XSD
<xs:element name="participants">
<xs:complexType>
<xs:all>
<xs:element name="attendees">
<xs:complexType>
<xs:sequence>
<xs:element ref="upn"/>
<xs:element ref="role"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="upn" type="xs:string"/>
<xs:element name="role" type="xs:string"/>
this is the output in JSON, after processing
"participants": {
"attendees": {
"upn": "testworkemail1#gmail.com",
"role": "Presenter"
},
"attendees": {
"upn": "testworkemail2#gmail.com",
"role": "Presenter"
}
}
Although it's not accepted by MS Graph API as it's service expects in this format:
"participants": {
"attendees": [
{
"upn": "testworkemail1#gmail.com",
"role": "presenter"
},
{
"upn": "testworkemail2#gmail.com",
"role": "presenter"
}
]
}
How can I alter Either XML or XSD to get it to MS specification of JSON request with omitted attendee element names?
Modifying the 4th line of the XSD by specifying the upper bound limit to be unbounded has converted the array of attributes with out label.
<xs:element name="attendees" maxOccurs="unbounded">

Send mail via EWS: Schema validation: invalid child element 'Body'

I'm trying to send an e-mail from within a C++ application via a Microsoft Exchange 2010 server. For this, I use the EWS protocol using the library ews-cpp.
The following trivial example, based on the one from https://github.com/otris/ews-cpp/blob/master/examples/send_message.cpp, is failing (mail addresses and credentials stripped from my actual code):
#include <iostream>
#include <ews/ews.hpp>
struct {
std::string domain = "mailserver";
std::string username = "...";
std::string password = "...";
std::string server_uri = "https://mailserver/EWS/Exchange.asmx";
} env;
int main()
{
ews::set_up();
try
{
auto service = ews::service(env.server_uri, env.domain, env.username,
env.password);
service.set_request_server_version(ews::server_version::exchange_2010_sp2);
auto message = ews::message();
message.set_subject("Test mail from outer space");
std::vector<ews::mailbox> recipients;
recipients.push_back(ews::mailbox("..."));
message.set_to_recipients(recipients);
auto text = ews::body("This is a test.");
message.set_body(text);
service.create_item(message,
ews::message_disposition::send_and_save_copy);
}
catch (ews::schema_validation_error& exc)
{
std::cout << exc.what() << std::endl;
std::cout << exc.violation() << std::endl;
}
ews::tear_down();
return 0;
}
The raw SOAP request is as follows (indentation added by me):
<m:CreateItem MessageDisposition="SendAndSaveCopy">
<m:Items>
<t:Message>
<t:Subject>Test mail from outer space</t:Subject>
<t:ToRecipients>
<t:Mailbox>
<t:EmailAddress>...</t:EmailAddress>
</t:Mailbox>
</t:ToRecipients>
<t:Body BodyType="Text">This is a test.</t:Body>
</t:Message>
</m:Items>
</m:CreateItem>
The function create_item throws an ews::schema_validation_error which is caught in the above code, printing:
The request failed schema validation
The element 'Message' in namespace ‘http://schemas.microsoft.com/exchange/services/2006/types’ has invalid child element 'Body' in namespace 'http://schemas.microsoft.com/exchange/services/2006/types'. List of possible elements expected: 'CcRecipients, BccRecipients, IsReadReceiptRequested, IsDeliveryReceiptRequested, ConversationIndex, ConversationTopic, From, InternetMessageId, IsRead, IsResponseRequested, References, ReplyTo, ReceivedBy, ReceivedRepresenting' in Namespace 'http://schemas.microsoft.com/exchange/services/2006/types'.
In other words, EWS doesn't expect <t:Body> within <t:Message>.
So, when leaving out that element in the SOAP request (comment out message.set_body(text)), the mail is sent smoothly. However, a mail without a body doesn't make much sense, does it?
I thought that the problem might be the fact that ews-cpp was written for Exchange 2013 (and that the schema changed between 2010 and 2013 in this regard). So I digged into the schema, which each Exchange server serves at /ews/types.xsd, to see if the schema allows such a child element.
In the schema definition file, I found the definition of the type MessageType (which is the type of the Message element we are talking about):
<xs:complexType name="MessageType">
<xs:complexContent>
<xs:extension base="t:ItemType">
<xs:sequence>
<xs:element name="Sender" minOccurs="0" type="t:SingleRecipientType"/>
<xs:element name="ToRecipients" type="t:ArrayOfRecipientsType" minOccurs="0"/>
<xs:element name="CcRecipients" type="t:ArrayOfRecipientsType" minOccurs="0"/>
<xs:element name="BccRecipients" type="t:ArrayOfRecipientsType" minOccurs="0"/>
<xs:element name="IsReadReceiptRequested" type="xs:boolean" minOccurs="0"/>
<xs:element name="IsDeliveryReceiptRequested" type="xs:boolean" minOccurs="0"/>
<xs:element name="ConversationIndex" type="xs:base64Binary" minOccurs="0"/>
<xs:element name="ConversationTopic" type="xs:string" minOccurs="0"/>
<xs:element name="From" type="t:SingleRecipientType" minOccurs="0"/>
<xs:element name="InternetMessageId" type="xs:string" minOccurs="0"/>
<xs:element name="IsRead" type="xs:boolean" minOccurs="0"/>
<xs:element name="IsResponseRequested" type="xs:boolean" minOccurs="0"/>
<xs:element name="References" type="xs:string" minOccurs="0"/>
<xs:element name="ReplyTo" type="t:ArrayOfRecipientsType" minOccurs="0"/>
<xs:element name="ReceivedBy" type="t:SingleRecipientType" minOccurs="0"/>
<xs:element name="ReceivedRepresenting" type="t:SingleRecipientType" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
As you can see, there is no Body child element, but MessageType is based on ItemType, which is defined as follows (excerpt):
<xs:complexType name="ItemType">
<xs:sequence>
<xs:element name="MimeContent" type="t:MimeContentType" minOccurs="0"/>
<xs:element name="ItemId" type="t:ItemIdType" minOccurs="0"/>
<xs:element name="ParentFolderId" type="t:FolderIdType" minOccurs="0"/>
<xs:element name="ItemClass" type="t:ItemClassType" minOccurs="0"/>
<xs:element name="Subject" type="xs:string" minOccurs="0"/>
<xs:element name="Sensitivity" type="t:SensitivityChoicesType" minOccurs="0"/>
<xs:element name="Body" type="t:BodyType" minOccurs="0"/>
<xs:element name="Attachments" type="t:NonEmptyArrayOfAttachmentsType" minOccurs="0"/>
[...]
</xs:sequence>
</xs:complexType>
As you can see, it accepts the Body element as a child.
Note that the Subject element is also defined in the ItemType and not in MessageType, and that is accepted by EWS in the above code snippet.
What might be the cause of this strange validation failure?
Found the solution myself:
For the element Message, which is based on Item according to the schema definition, EWS first expects all child elements for Item, followed by the Message-specific child elements.
This sounds very insane (to me), but swapping <t:ToRecipients> and <t:Body> in the <t:Message> element indeed solved the problem.
I did this by swapping the two corresponding setters in my code:
auto message = ews::message();
// First, set properties of the general "item":
message.set_subject("Test mail from outer space");
auto text = ews::body("This is a test.");
message.set_body(text);
// Then, set properties of the concrete "message":
std::vector<ews::mailbox> recipients;
recipients.push_back(ews::mailbox("..."));
message.set_to_recipients(recipients);
I'm not sure if this is a bug in ews-cpp, in EWS / Exchange server, or in the EWS schema definition.

Python Spyne change the name of _return values

I'm using python 2.7 and Spyne for creating some web services in Django.
I'm not able to change the name of the returned values, for example:
Given this code:
class Consumer(ServiceBase):
#rpc(Integer,Integer, _returns = [Integer,Integer])
def addConsumer(ctx, topic_id, consumer_id):
...
...
The response in my wsdl looks like:
<xs:sequence>
<xs:element name="addConsumerResult0" type="xs:integer" minOccurs="0" nillable="true"/>
<xs:element name="addConsumerResult1" type="xs:integer" minOccurs="0" nillable="true"/>
</xs:sequence>
I am looking for something that allow me to change name="addConsumerResult0" to name="whateverXYZ"
You can use _out_variable_names to change return type names.
e.g.
class Consumer(ServiceBase):
#rpc(Integer,Integer, _returns = [Integer,Integer],
_out_variable_names=["whateverXYZ", "foo"])
def addConsumer(ctx, topic_id, consumer_id):
...
...

xpath copy expression in BPEL

I have problem in copying the output of a service response to the response message in BPEL .
The amount element has an attribute currency, How do I acheiev this ? All other copying seems to work fine, except copying an element to an attribute of another element.
The copy expression is below.
<copy>
<from variable="InvokePersistence_insert_OutputVariable"
part="ProBookingInitiationCollection" query="/ns3:ProBookingInitiationCollection/ns3:ProBookingInitiation/ns3:bookingDetail/ns3:isoCurrencyCd"/>
<to variable="outputVariable" part="payload"
query="/ns4:BookingConfirmation/ns4:amount/#ns4:currency"/>
</copy>
The excerpts from xsd is below
<xs:element name="amount">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="currency" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
Make sure that "outputVariable" output variable is properly initialised according to the schema and contains an attribute called "currency"

Complex type with single array element throws marshalling exception

We have JAX-RPC style web service, with a complex type defined as follows:
<xs:complexType name = "SomeFault">
<xs:sequence>
<xs:element name = "errorMessages" type="some:ErrorMessageWSType" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:simpleType name = "ErrorMessageWSType">
<xs:restriction base = "xs:NMTOKEN">
<xs:enumeration value = "INVALID_1"/>
<xs:enumeration value = "INVALID_2"/>
<xs:enumeration value = "INVALID_3"/>
</xs:restriction>
</xs:simpleType>
We are running into Marshaling exception on the server side when the response/fault complex type has a single array type field.
weblogic.wsee.codec.CodecException: Failed to encode
com.bea.xml.XmlException: failed to find a suitable binding type for
use in marshalling object
"[Lnamespace.type.ErrorMessageWSType;#693767e9". using schema type:
t=SomeFault#http://namespace/SOME/v1 java
type:namespace.type.ErrorMessageWSType[]
If we change SomeFault, by adding another element to the complex type the error goes away.
<xs:complexType name = "SomeFault">
<xs:sequence>
<xs:element name = "errorMessages" type="some:ErrorMessageWSType" maxOccurs="unbounded" />
<xs:element name = "dummyString" type="xsd:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
Are we doing something wrong during the wsdlc code generation or is this a known issue?
A similar question is already posted at https://forums.oracle.com/forums/thread.jspa?messageID=4462906, but without any response, any pointers would be great.
Thanks.
Don't know if this solves the "why" part of the question, but you could try rewriting the sequence part like:
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="errorMessages" type="some:ErrorMessageWSType"/>
</xs:sequence>
OTOH, what might be the mechanism that lets the second case work, but not the first?
Might it be that the marshaller then has to figure out what xsd:string means before checking what some:ErrorMessageWSType means, and then has to wake up a resolver or something?
This line of thought leads to the second approach I would try, which would be to declare ErrorMessageWSType before SomeFault (and perhaps in another namespace, just to see if that fixes anything).
Just my (tired) two cents, and I guess that both of these approaches presume a bug of some sort in the marshaller, because I can't really see that anything in your example code isn't according to the XML schema definition.