I usually consume SOAP webservices with CFHTTP and post the XML as a HTTP parameter. However, this time I am trying to consume a webservice with createObject, but when I pass the XML as an argument to the webservice ws.someMethod(args);, it fails. I tried using a struct to hold the parameter values, but that also did not work. As such, how do one pass the parameters? The partial WSDL is below
<xs:element name="ORDER">
<xs:complexType>
<xs:sequence>
<xs:element name="Header" type="schemaOne:HeaderType"/>
<xs:element maxOccurs="unbounded" name="Detail" type="schemaOne:DetailType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="DetailType">
<xs:sequence>
<xs:element ref="schemaOne:DTORDN"/>
<xs:element ref="schemaOne:DTRCID"/>
<xs:element ref="schemaOne:DTPRT"/>
<xs:element ref="schemaOne:DTQTY"/>
<xs:element ref="schemaOne:DTNTU"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="HeaderType">
<xs:sequence>
<xs:element ref="schemaOne:DSORDN"/>
<xs:element ref="schemaOne:DSRCID"/>
<xs:element ref="schemaOne:DSBFNM"/>
<xs:element ref="schemaOne:DSBLNM"/>
<xs:element minOccurs="0" ref="schemaOne:DSBENT"/>
<xs:element ref="schemaOne:DSBAD1"/>
<xs:element minOccurs="0" ref="schemaOne:DSBAD2"/>
<xs:element minOccurs="0" ref="schemaOne:DSBAD3"/>
<xs:element ref="schemaOne:DSBAD4"/>
<xs:element ref="schemaOne:DSBSTT"/>
<xs:element ref="schemaOne:DSBZIP"/>
<xs:element ref="schemaOne:DSBCNT"/>
</xs:sequence>
</xs:complexType>
Here's the struct I've constructed.
<cfscript>
ORDER = {};
ORDER.Header = {};
ORDER.Detail = {};
ORDER.Header.DSORDN = '251716';
ORDER.Header.DSRCID = 'H';
ORDER.Header.DSBFNM = 'Joe';
ORDER.Header.DSBLNM = 'Smith';
ORDER.Header.DSBAD1 = '4997 County Road';
ORDER.Header.DSBAD4 = 'Springfield';
ORDER.Header.DSBSTT = 'MO';
ORDER.Header.DSBZIP = '49657';
ORDER.Header.DSBCNT = 'USA';
ORDER.Detail.DTORDN = '251716';
ORDER.Detail.DTRCID = 'D';
ORDER.Detail.DTPRT = '0300604';
ORDER.Detail.DTQTY = '0000000000001';
ORDER.Detail.DTNTU = '00000009.9900';
</cfscript>
i am working with unit tests at the moment and where trying to pass an xml file to my Webservice. I just saved the xml Files i needed inside external files and read them with "FileRead" inside cfscript. This is how i did it
<cfscript>
input = FileRead("http.....");
mycomponent = createObject("component", "component.beginning.from.root");
mycomponent.methodName(input);
</cfscript>
but i had to change my code because before i parsed the content of the HttpRequest to xml and where looking for the expected elements. Now i use the incoming file and look immediately for the elements i want instead of parsing because its already xml
<cfset var body = xmlsearch(arguments.input, "//soapenv:body")[1] />
if you're interested in the code of my webservice just look here
You have to consume SOAP web services that expect complex data type with CFC that mirrors the expected structure instead of passing the XML. See this
Related
I am trying to read xml tags from a document using QtXQuery. Works out fine besides a '\n'-char that is attached to each query-result. Moreover using the last()-statement on a collection returns the expected number of items in the collection with a trailing repetition + '\n'.
Why QXmlQuery seem to add a ` \n` to results? (and how to solve it?) suggest to use a QStringList and only take the first item into account, yet this does not seem to work with my setup as using a QStringList on query.evaluateTo(&qsl) fails to return any results. So: my question is if this is a bug in libqt5xmlPatterns5 or if my implementation is the reason for this behavior? Am I missing some details on how to use QtXmlQuery?
So here is the piece of code:
get_tag_value:
static lib_int_err_t get_tag_value(QString *result, QUrl schema_file, QString xml_file_name, QString var_name, QString query_str)
{
lib_int_err_t ret_code = LIE_OK;
QFile *xml_f= new QFile(xml_file_name);
xml_f->open(QIODevice::ReadOnly);
if(result!=nullptr){
result->clear();
QXmlSchema xmlschema;
// QStringList *results = new QStringList();
xmlschema.load(schema_file);
QXmlQuery query(QXmlQuery::XQuery10, xmlschema.namePool());
query.bindVariable(var_name, xml_f);
query.setQuery(query_str);
query.evaluateTo(result);
// result->append(results->first());
ret_code = LIE_OK;
}
else{
ret_code = LIE_XML_MALFORMED;
}
xml_f->close();
return ret_code;
}
The input query string:
'declare copy-namespaces no-preserve, inherit; declare variable $" + var_name + " external; doc($" + var_name + ")" + "//procLib/last()" '
The schema used for data description:
<xs:element name="toolConfig">
<xs:complexType>
<xs:sequence>
<xs:element name="processingLibsSettings">
<xs:complexType>
<xs:sequence>
<xs:element name="interfaceSchemaDef" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="interfaceSchemaPath" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="processingLibsInstances">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="procLib" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="procLibConfigName" type="xs:string"/>
<xs:element name="procLibConfigPath" type="xs:string"/>
<xs:element name="procLibName" type="xs:string"/>
<xs:element name="procLibPath" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="installDir" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Solved this with a workaround:
results=results.remove('\n');
results=results.split(' ')[0];
not really nice, but it works...
Requirement is read data from file and invoke webservice. Target webservice can handle one payload at a time but there will be multiple payload in source.
So am using while loop to process payload one by one.
Issue: In target service EarningTypeInclusion is optional element, so in source some payload this element will be present and in some payload this option element will not be present.
<thresholdRequestInterface xmlns:xs="http://www.sample.com/ns/LMSReferrals">
<thresholdRequest>
<Referral>11</Referral>
<thresholdValue>100</thresholdValue>
<EarningTypeInclusion>
<earningType>positive</earningType>
<ProvisionId>1000</ProvisionId>
</EarningTypeInclusion>
</thresholdRequest>
<thresholdRequest>
<Referral>11</Referral>
<thresholdValue>100</thresholdValue>
</thresholdRequest>
</thresholdRequestInterface>
If am using assign activity, then selection failure fault will come when optional elements are not present in source payload. We are using BPEL 10g, no option in assign activity to supress selection failure fault.
So decided to use transformation inside while loop .
logic used
Read from file
assign Loop counter=1
Count of payload(read from file)
While loop counter<= Count of payload
pass loop counter param value to transform
transform source i.e thresholdRequest[loopcounter] to target
Invoke target web service
increment loop counter
end loop;
Problem is same data is getting trsnformed.
In the below example, referral 11 data is loading 3 times. I have checked conter value, its getting incremented but inside transformation same values are getting transformed.
<thresholdRequestInterface xmlns:xs="http://www.sample.com/ns/LMSReferrals">
<thresholdRequest>
<Referral>11</Referral>
<thresholdValue>100</thresholdValue>
<EarningTypeInclusion>
<earningType>positive</earningType>
<ProvisionId>1000</ProvisionId>
</EarningTypeInclusion>
</thresholdRequest>
<thresholdRequest>
<Referral>12</Referral>
<thresholdValue>100</thresholdValue>
</thresholdRequest>
<thresholdRequest>
<Referral>13</Referral>
<thresholdValue>100</thresholdValue>
<EarningTypeInclusion>
<earningType>positive</earningType>
<ProvisionId>1000</ProvisionId>
</EarningTypeInclusion>
</thresholdRequest>
</thresholdRequestInterface>
Source
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns="http://www.sample.com/ns/LMSReferrals" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://www.sample.com/ns/LMSReferrals" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="thresholdRequestInterface">
<xs:complexType>
<xs:sequence>
<xs:element name="thresholdRequest" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Referral" type="xs:string"/>
<xs:element name="thresholdValue" type="xs:int"/>
<xs:element name="EarningTypeInclusion" minOccurs="0" maxOccurs="1" >
<xs:complexType>
<xs:sequence>
<xs:element name="earningType" type="xs:stirng" />
<xs:element name="ProvisionId">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="20" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Please find the schema structure for source and target
Target
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns="http://www.sample.com/ns/LMSReferrals" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://www.sample.com/ns/LMSReferrals" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="thresholdRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="Referral" type="xs:string"/>
<xs:element name="thresholdValue" type="xs:int"/>
<xs:element name="EarningTypeInclusion" minOccurs="0" maxOccurs="1" >
<xs:complexType>
<xs:sequence>
<xs:element name="earningType" type="xs:stirng" />
<xs:element name="ProvisionId">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="20" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Please note schema validation is enabled at target webservice.
Is there a specific reason that you are using Transform.Try using ora:getElement('/thresholdRequestInterface /thresholdRequest',bpws:getVariable(loopCounter))
In an application, I have web services that are based on WSDL files provided by a third-party company. All I did until now, was generating the associated Java code by using an ant script with axis wsdl2java.
I say until now because the company which provide the web services has modified its architecture and the soap messages must know respect the order of the input elements which is apparently not the case.
Example : in my WSDL I have something like this
<xs:element name="personinfo">
<xs:complexType>
<xs:sequence>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
But when I look at the soap message that is sent to the web service, the order of the elements are not the same as in the WSDL file.
Do you guys have any idea on what do I have to do in order to make the elements order respected in the message that I send ?
EDIT : I use Axis 1.4
Thanks a lot for your help !
I am trying to create a soap web service for a server using jax-ws following this xml schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="OfeliaDataEx">
<xs:complexType>
<xs:sequence>
<xs:element ref="Header"/>
<xs:element ref="User"/>
<xs:element ref="Data"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Header">
<xs:complexType>
<xs:sequence>
<xs:element ref="State"/>
<xs:element ref="TypeReq"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="State" type="xs:string"/>
<xs:element name="TypeReq" type="xs:string"/>
<xs:element name="User">
<xs:complexType>
<xs:sequence>
<xs:element ref="JabberID"/>
<xs:element ref="OpenID"/>
<xs:element ref="OauthToken"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="JabberID" type="xs:string"/>
<xs:element name="OpenID" type="xs:anyURI"/>
<xs:element name="OauthToken">
<xs:complexType>
<xs:sequence>
<xs:element ref="AuthToken"/>
<xs:element ref="TokenSecret"/>
<xs:element ref="ExpireDate"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="AuthToken" type="xs:string"/>
<xs:element name="TokenSecret" type="xs:string"/>
<xs:element name="ExpireDate" type="xs:string"/>
<xs:element name="Data">
<xs:complexType mixed="true">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="POSI"/>
<xs:element ref="TESTE"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="POSI">
<xs:complexType>
<xs:all>
<xs:element ref="TimeStamp"/>
<xs:element ref="RefreshInterval"/>
<xs:element ref="Lon"/>
<xs:element ref="Lat"/>
<xs:element ref="Data"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="RefreshInterval" nillable="true" type="xs:integer"/>
<xs:element name="Lon" nillable="true" type="xs:float"/>
<xs:element name="Lat" nillable="true" type="xs:float"/>
<xs:element name="TESTE">
<xs:complexType>
<xs:all>
<xs:element ref="TimeStamp"/>
<xs:element ref="cenas"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="cenas" nillable="true" type="xs:float"/>
<xs:element name="TimeStamp" type="xs:string"/>
</xs:schema>
My first try was follow a POJO model how ever i did not have any success. I couldnt reproduce the <xs:choice minOccurs="0" maxOccurs="unbounded">. So i am here to ask for an idea to create a soap web service that follows this schema.
best regards,
Why don't you use the xjc tool which comes with your JDK and creates the required jax-b artifacts from a xsd...
something like this will create the classes in the 'generated' subfolder of the current directory:
xjc /the/path/to/my/xsdfile.xsd
Also look here: http://docs.oracle.com/javase/6/docs/technotes/tools/share/xjc.html
I'm using the following lines of code to call the web-service below:
def wsdl = 'http://somewhere.com/services/msgService?wsdl'
proxy = new WSClient(wsdl, this.class.classLoader)
proxy.initialize()
def msg = proxy.create("com.somwhere.test.api.MsgService")
msg.applicationName = "APP1"
msg.clientId = 5
msg.additionalProperties = [test:3]
for web-service
<xs:schema targetNamespace="http://somewhere.com/test/api/MsgService" version="1.0" xmlns:tns="http://somewhere.com/test/api/MsgService" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="sendMessage" type="tns:sendMessage"/>
<xs:complexType name="sendMessage">
<xs:sequence>
<xs:element minOccurs="0" name="mRequest" type="tns:mServiceRequest"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="mServiceRequest">
<xs:sequence>
<xs:element name="additionalProperties">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="entry">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="key" type="xs:string"/>
<xs:element minOccurs="0" name="value" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="applicationName" type="xs:string"/>
<xs:element minOccurs="0" name="clientId" type="xs:long"/>
.......
</xs:sequence>
</xs:complexType>
</xs:schema>
But get the following error:
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '{test=3}' with class 'java.util.LinkedHashMap' to class 'com.somwhere.test.api.MsgService$AdditionalProperties'
However, when the additionalProperties are an empty map, i.e. [:] it works fine.
What am I doing wrong? How must I format the map, or what other object do I need to use in order for it to work?
This is almost a year old... I hope you already found the answer somewhere else.
Just for the record I'll add what I think
The client should have generated a class with properties named key and value, just instantiate it with the normal create() and set said properties.
The field additionalProperties might be a simple list of said 'entries' or another class wrapping the list, in which case you have to create() it also.
The best thing to do is check the list of generated classes when generating the client, creating each one and dump()ing them to see the structure.
Be prepared to write something like this.
new groovyx.net.ws.WSClient(
"http://localhost/service?wsdl",
this.class.classLoader).with {
initialize()
def wrapper = create('defaultnamespace.MapWrapper')
wrapper.map = create('defaultnamespace.ArrayOfMapWrapperEntry')
wrapper.map.mapWrapperEntry = [key1:'value1',key2:'value2'].collect{k,v->
def entry = create('defaultnamespace.MapWrapperEntry')
entry.key = k
entry.value = v
entry
}
send wrapper
}
We decided to connect to another gateway that uses REST instead of wsdl since I didn't get it to work. I haven't tried jpertinos solution, but it looks promising.
However, I'm closing this ticket.