Extension Base on nusoap - web-services

I would like to create xml schema on nusoap like the following:
<xsd:complexType name="WSMessage">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1" name="ErrorMessage" type="s:string"/>
<xsd:element minOccurs="0" maxOccurs="1" name="ErrorCode" type="s:string"/>
</xsd:sequence>
</xsd:complexType>
<s:complexType name="ResultSet">
<s:complexContent mixed="false">
<s:extension base="tns:WSMessage">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="TestData" type="tns:ArrayOfTestData"/>
</s:sequence>
</s:extension>
</s:complexContent>
</s:complexType>
I can't see any documentation on how I could do that. Does anyone know this already?
Thank you.

Add two complex type for input, what i understood in your question is its input and has output
$this->nusaop->wsdl->addComplexType(
'WSMessage',
'complexType',
'struct',
'all',
'',
array(
'ErrorMessage ' => array(
'MethodParameters' => 'ErrorMessage',
'type' => 'xsd:string'
),
'ErrorCode' => array(
'MethodParameters' => 'ErrorCode',
'type' => 'xsd:string'
)
)
);
/Input Data type/
$this->nusaop->wsdl->addComplexType(
'ResultSet',
'complexType',
'struct',
'all',
'',
array(
'TestData' => array(
'MethodParameters' => 'TestData',
'type' => 'xsd:string'
),
)
);
/Output Data type/
$this->FM_SoapServer->register(
'Methodcall',// parameter list:
array('Credentials'=>'tns:WSMessage'),// return value(s):
array('return'=>'tns:ResultSet'),// namespace:
false,// soapaction: (use default)
false,// style: rpc or document
'rpc',// use: encoded or literal
'encoded',// description: documentation for the method
''
);
function Methodcall(){
/// validations ....
code....
return array("ResultSet" => $return);
}
Untested but the logic is there

Related

Zeep python SOAP client sending empty value in the argument

There is an external SOAP server that I'm trying to connect and make requests using the python-django framework with the zeep library.
The WSDL dump is as follows:
Prefixes:
xsd: http://www.w3.org/2001/XMLSchema
ns0: http://tempuri.org/
Global elements:
ns0:GetJobCards(key: xsd:string, technicianID: xsd:string, jobCardNumber: xsd:string, jobcards: ns0:ArrayOfJobCardsEnt, message: xsd:string)
ns0:GetJobCardsResponse(GetJobCardsResult: xsd:boolean, jobcards:ns0:ArrayOfJobCardsEnt, message: xsd:string)
Global types:
xsd:anyType
ns0:ArrayOfJobCardsEnt(JobCardsEnt: {schema: , _value_1: ANY}[])
xsd:ID
xsd:IDREF
xsd:IDREFS
xsd:NCName
xsd:NMTOKEN
xsd:NMTOKENS
xsd:NOTATION
xsd:Name
xsd:QName
xsd:anySimpleType
xsd:anyURI
xsd:base64Binary
xsd:boolean
xsd:byte
xsd:date
xsd:dateTime
xsd:decimal
xsd:double
xsd:duration
xsd:float
xsd:gDay
xsd:gMonth
xsd:gMonthDay
xsd:gYear
xsd:gYearMonth
xsd:hexBinary
xsd:int
xsd:integer
xsd:language
....
Bindings:
Soap11Binding: {http://tempuri.org/}CallSoap
Soap12Binding: {http://tempuri.org/}CallSoap12
Service: Call
Port: CallSoap (Soap11Binding: {http://tempuri.org/}CallSoap)
Operations:
GetJobCards(key: xsd:string, technicianID: xsd:string,
jobCardNumber: xsd:string, jobcards: ns0:ArrayOfJobCardsEnt,
message: xsd:string) -> GetJobCardsResult: xsd:boolean,
jobcards: ns0:ArrayOfJobCardsEnt, message: xsd:string
....(some other operations)
One of the calls is to get a list of jobCards with the following schema
<s:element name="GetJobCards">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="key" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="technicianID" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="jobCardNumber" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="jobcards" type="tns:ArrayOfJobCardsEnt"/>
<s:element minOccurs="0" maxOccurs="1" name="message" type="s:string"/>
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="ArrayOfJobCardsEnt">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="JobCardsEnt" nillable="true">
<s:complexType>
<s:sequence>
<s:element ref="s:schema"/>
<s:any/>
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
When I make the call using Postman I send the following request and it works:
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetJobCards xmlns="http://tempuri.org/">
<key>some_valid_key</key>
<technicianID>some_technician_id</technicianID>
<jobCardNumber></jobCardNumber>
<jobcards></jobcards>
<message>""</message>
</GetJobCards>
</soap:Body>
Please note that the values for "jobCardNumber" and "jobcards" need to be empty to get all the jobCards. But I cannot seem to replicate this same call using the zeep library.
Here is what I have tried.
1 - tried adding xsd.SkipValue for the empty values
request_data = {
'key': some_valid_key,
'technicianID': some_technician_ID,
'jobCardNumber': xsd.SkipValue,
'jobcards': xsd.SkipValue,
'message': ''
}
response_body = client.service.GetJobCards(**request_data)
2 - setting the values to Nil
from zeep.xsd import Nil
jobCardEnt = client.get_type('ns0:ArrayOfJobCardsEnt')
jobCardEnt = jobCardEnt()
request_data = {
'key': some_valid_key,
'technicianID': some_technician_ID,
'jobCardNumber': Nil,
'jobcards': Nil,
'message': ''
}
response_body = client.service.GetJobCards(**request_data)
None of these seems to works and I'm not sure how to get it to work.
Can someone please guide me on this?
Thanks in advance!
Here is how I got it working
with self.client.settings(strict=False):
response_body = self.client.service.GetJobCards(
key=some_valid_key,
technicianID=some_technician_id,
message=''
)
And omitted the values for 'jobCardNumber' and 'jobcards'

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):
...
...

Errors with using Scalaxb for code generation

I had to fiddle with a WSDL document for one of the implementations and I came across Scalaxb! I'm now trying to generate some scala classes from the WSDL file that I have and as expected I'm hitting into some issues:
Here is a snippet of the WSDL file:
<?xml version="1.0" encoding="UTF-8" ?>
<wsdl:definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.myservice.com/MyServices/2012/06/18/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
name="MyServices"
targetNamespace="http://www.myservice.com/MyServices/2012/06/18/">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://www.myservice.com/MyServices/2012/06/18/">
<s:complexType name="UserCredentials">
<s:sequence>
<s:element name="UserName" type="s:string" />
<s:element name="Password" type="s:string" />
</s:sequence>
</s:complexType>
<s:element name="UserCredentials" type="tns:UserCredentials" />
<s:complexType name="AnotherComplexType" >
<s:sequence>
<s:element name="Index" type="s:int" />
<s:element name="Name" type="s:string" />
<s:element name="Status" type="s:boolean" />
</s:sequence>
</s:complexType>
....
Assume that the rest of the WSDL file is completely fine, when I tried to compile the project, I hit the following error:
[error] /Users/joe/Desktop/scalaxb-soap-example/target/scala-2.11/src_managed/main/sbt-scalaxb/myservice/xmlprotocol.scala:1542: not found: value userCredentials
[error] scalaxb.toXML(userCredentials, Some("http://www.myservice.com/MyServices/2012/06/18/"), "UserCredentials", defaultScope), defaultScope, baseAddress, "POST", Some(new java.net.URI("http://1.1.1.1/cgi-bin/cgi.cgi?WebService=SetGPTimerChannel"))).transform({ case (header, body) =>
[error] ^
[error] /Users/joe/Desktop/scalaxb-soap-example/target/scala-2.11/src_managed/main/sbt-scalaxb/myservice/xmlprotocol.scala:1544: value toSeq is not a member of Any
[error] scala.xml.Elem(null, "Body", scala.xml.Null, defaultScope, true, body.toSeq: _*)
[error] ^
[error] /Users/joe/Desktop/scalaxb-soap-example/target/scala-2.11/src_managed/main/sbt-scalaxb/myservice/xmlprotocol.scala:1551: not found: value userCredentials
[error] scalaxb.toXML(userCredentials, Some("http://www.myservice.com/MyServices/2012/06/18/"), "UserCredentials", defaultScope), defaultScope, baseAddress, "POST", Some(new java.net.URI("http://1.1.1.1/cgi-bin/cgi.cgi?WebService=SomeServiceCall"))).transform({ case (header, body) =>
[error] ^
[error] /Users/joe/Desktop/scalaxb-soap-example/target/scala-2.11/src_managed/main/sbt-scalaxb/myservice/xmlprotocol.scala:1553: value toSeq is not a member of Any
[error] scala.xml.Elem(null, "Body", scala.xml.Null, defaultScope, true, body.toSeq: _*)
[error] ^
Any ideas what and why I'm facing this issue? Here is my build.sbt:
import ScalaxbKeys._
val scalaXml = "org.scala-lang.modules" %% "scala-xml" % "1.0.2"
val scalaParser = "org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.1"
val dispatchV = "0.11.1" // change this to appropriate dispatch version
val dispatch = "net.databinder.dispatch" %% "dispatch-core" % dispatchV
organization := "com.eon"
name := "scalaxb-myservice-sample"
scalaVersion := "2.11.6"
scalaxbSettings
packageName in (Compile, scalaxb) := "rdmservice"
dispatchVersion in (Compile, scalaxb) := dispatchV
async in (Compile, scalaxb) := true
sourceGenerators in Compile <+= scalaxb in Compile
libraryDependencies ++= Seq(scalaXml, scalaParser, dispatch)
If you only need to generate WSDL client code, using scalaxb might be a bit too much. As an option, you could just use wsimport wrapped as a simple SBT task that would be executed before the main code compilation. Apart from one less dependency, it also keeps your repository pristine and frees it from committing the generated boilerplate Java code. Here's a sample template project if anyone is interested: https://github.com/sainnr/sbt-scala-wsdl-template.

webservices : Are xs:string and xsd:string are same ??

We have developed Webservices using Apache CXF , and they are working fine .
This is some part of our generated wsdl file (http://localhost:8080/MyWeb/tata/soap?wsdl).
<xs:sequence>
<xs:element minOccurs="0" name="strikePrice" type="xs:double"/>
<xs:element minOccurs="0" name="symbol" type="xs:string"/>
</xs:sequence>
<soap:body use="literal"/>
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
We have developed Webservices using Apache CXF , and they are working fine .
While reading webservice performance tuning tutorials , i read always use document literal for interoperabilty .
My question is , is my WSDL is document /literal ??
Because most of the tutorials in internet , represent xsd:String in place of (xs:String) for representing document/literal approach ??
Are xs:String and xsd:String are same ??
xs:string and xsd:string are the same, provided that the "xs" and "xsd" prefixes are both bound to the namespace URI "http://www.w3.org/2001/XMLSchema".