I'm trying to use the Microsoft Dynamics SOAP request:
XRMServices/2011/Organization.svc/web
with the following request:
<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">
<request i:type=\"a:retrieveOptionSetRequest\" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts\">
<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">
<a:KeyValuePairOfstringanyType>
<b:key>Name</b:key>
<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">new_industry</b:value>
</a:KeyValuePairOfstringanyType>
</a:Parameters>
<a:RequestId i:nil=\"true\" />
</request>
</Execute>
but, being a novice all I get bad is "Bad request"!
Any help will be greatfully received!
Thanks
There is a few issues with the your request. Firstly the request is 'RetrieveOptionSetRequest' not 'retrieveOptionSetRequest' (it will tell you this doesn't exist!)
Secondly there is a missing '\' on your request line
<request i:type=\"a:retrieveOptionSetRequest\" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts\">
Should be
<request i:type=\"a:RetrieveOptionSetRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">
If you fix those two issues then you will find you still won't get the required result.
As can be seen at the website mentioned by Pedro Azevedo you need to include the MetadataId and RetrieveAsIfPublished parameters or you won't get a result (the response will make you aware of this). You need to include RequestName in your request.
Your final request should look like this
<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">
<request i:type=\"a:RetrieveOptionSetRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">
<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">
<a:KeyValuePairOfstringanyType>
<b:key>MetadataId</b:key>
<b:value i:type=\"c:guid\" xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/\">00000000-0000-0000-0000-000000000000</b:value>
</a:KeyValuePairOfstringanyType>
<a:KeyValuePairOfstringanyType>
<b:key>Name</b:key>
<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">new_industry</b:value>
</a:KeyValuePairOfstringanyType>
<a:KeyValuePairOfstringanyType>
<b:key>RetrieveAsIfPublished</b:key>
<b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">false</b:value>
</a:KeyValuePairOfstringanyType>
</a:Parameters>
<a:RequestId i:nil=\"true\" />
<a:RequestName>RetrieveOptionSet</a:RequestName>
</request>
</Execute>
Related
I've implemented a simple API service in WSO2 EI. The Input endpoint is configured to accept 'application/edi-hl7' essentially to read HL7 message. I perform certain transformations on the message and then need to respond with JSON. So, as part of the response JSON payload I also want to have original HL7 message sent as request payload and that too in original shape (not XML / JSON formatted).
Say my input is,
MSH|^~\&|ULTRA_V3.1|LAV|Web Portal|Web Portal|201810030949||ORU^R01|279857418|P|2.3.1|||AL|AL|AU
PID||3914950|21710425491^^^AUSHIC^MC~111111^^^^UR~5548391^^^^ULTRAREL||KAY^BRUCE^^^||19630604|M|||11 NJUONA AVE^^BAIURE BAY^WSN^2000||^^^^^^0243333323||||||21710425491
PV1||O|CSLI^KINUYMBER|||||214082JL^KOPRA^MARUTI^^KAYBB^DR
ORC|RE||18-15768981-000-0||R
OBR|1||18-15768981-000-0|000^PENDING^ULTRA^LAVLEI||20180914|201810030805|||CSKI||||201810030949||214082JL^KOPRA^MARUTI^^KAYBB^DR||TFT-0^GLU-0^CRP-0^RDA-0^MBA-0^LIP-0^FBE-0||683131368452|LAV^false|201810030949||LAB|I||^^^20180914|
And sample output is,
{"message": "MSH|^~\&|.....", "Otherkeys": "someVal"}
As part of message, I want original message as is and not SOAP body.
P.S. I need to remove \n\r available at the end of each line.
The main question is how can get the original message in original shape in the mediation flow.
Here is a sample API. Hope It helps.
Screenshot of the result
Just put payloadFactory Mediator in appropriate place in your Sequence.
<api xmlns="http://ws.apache.org/ns/synapse" name="Test" context="/Test">
<resource methods="POST" uri-template="/testHL">
<inSequence>
<log level="full"/>
<payloadFactory media-type="json">
<format>{"message": "$1", "Otherkeys": "someVal"}</format>
<args>
<arg evaluator="xml" expression="$body/*[1]"/>
</args>
</payloadFactory>
<respond/>
</inSequence>
</resource>
</api>
**Issue solved, thanks to neildo. Here's what it took to get a response from a POST
RAML file must have a response body definition
HTTP Endpoint must be set to request-response
All Flows using the synchronous Processing Strategy
Accept and Content-Type HTTP headers set to application/json on the request
**
The implementation of my REST Flow calls a Java API that returns a Java object. I then convert the object to a JSON document and return it to the client. My Logger step is logging the correct data, however the client just gets a 200 OK with an empty body.
I have set all my Flows to synchronous and my HTTP Endpoint to request-response. What am I missing?
Thank you!
Nathan
Here is my XML file
<apikit:config name="IAMPerson-config" raml="IAMPerson.raml" consoleEnabled="true" consolePath="console" doc:name="Router"/>
<apikit:mapping-exception-strategy name="IAMPerson-apiKitGlobalExceptionMapping">
<apikit:mapping statusCode="404">
<apikit:exception value="org.mule.module.apikit.exception.NotFoundException" />
<set-property propertyName="Content-Type" value="application/json" />
<set-payload value="{ "message": "Resource not found" }" />
</apikit:mapping>
...
</apikit:mapping-exception-strategy>
<flow name="IAMPerson-main" doc:name="IAMPerson-main" processingStrategy="synchronous">
<http:inbound-endpoint address="http://localhost:8081/api" doc:name="HTTP" exchange-pattern="request-response" password="admin" user="admin" contentType="application/json"/>
<apikit:router config-ref="IAMPerson-config" doc:name="APIkit Router"/>
<exception-strategy ref="IAMPerson-apiKitGlobalExceptionMapping" doc:name="Reference Exception Strategy"/>
</flow>
<flow name="post:/person:IAMPerson-config" doc:name="post:/person:IAMPerson-config" processingStrategy="synchronous">
<json:json-to-object-transformer doc:name="JSON to Object" returnClass="PersonDTO"/>
<invoke name="invokeCreate" object-ref="personService" method="create" methodArguments="#[payload]"></invoke>
<json:object-to-json-transformer sourceClass="Person" doc:name="Person Object to JSON"/>
<logger level="INFO" doc:name="Logger" message="#[payload]"/>
</flow>
<flow name="put:/person:IAMPerson-config" doc:name="put:/person:IAMPerson-config" processingStrategy="synchronous">
<logger level="INFO" doc:name="Logger" message="#[payload]"/>
<json:json-to-object-transformer doc:name="JSON to Object" returnClass="PersonDTO"/>
<invoke name="invokeUpdate" object-ref="personService" method="update" methodArguments="#[payload]"/>
<json:object-to-json-transformer sourceClass="Person" doc:name="Person Object to JSON"/>
<logger level="INFO" doc:name="Logger" message="#[payload]"/>
</flow>
Here is part of my RAML file where I define a request and response body. When I posted a message to Mule, I got this error with nothing logged to the Mule console.
null (java.lang.NullPointerException). Message payload is of type: ContentLengthInputStream
post:
body:
application/json:
responses:
200:
body:
application/json:
In your raml file, make sure your resource method is mapping the response 200 body with application/json. For example...
/person:
post:
responses:
200:
body:
application/json:
I had the same problem (using version 3.5.0), but with a GET request. None of the proposed solutions (neither items 1 through 4 at the top of the edited question, nor the checked answer) solved the problem for me. (Most of them were already true in my case.)
What did work for me was adding the following at the bottom of the problematic GET flow's XML:
<response>
<set-property propertyName="Content-Type" value="application/json"/>
</response>
Unfortunately, there seems to be no way to do this using the visual editor (in the "Message Flow" tab). I had to do this manually in the "Configuration XML" tab instead.
Also, inserting the above element in the main flow (the one that invokes the APIKit Router) -- which has to be done BEFORE the <exception-strategy> element for some reason -- does not solve the problem. However, in this case, the response element DOES show up in the visual editor.
I looked at this page on SO 15 times before I realized how I'd caused this. I'd added a Transformer to do some authentication. I'd customized my onCall method, but left transformMessage as the default which sets a 200 and returns null.
Lo and behold, changing return null to return message made everything work again.
Use this format of response for 200 status code in your RAML file.
responses:
200:
body:
application/json:
I am using SoapUI Pro to test web services used for creating postal despatch shipments.
I am using a groovy script to validate my web service requests. If I am expecting the request to succeed I look for a value of ‘Allocated’ in the ‘status’ field. If I am expecting the request to fail I look for the correct error code and errorDescription in the integration footer.
Sometimes a valid request will have a warning message (e.g. to inform user that field data is too long and has been truncated). I also want to validate these warning messages as well.
I specify the element path that I want to validate in my data source file and then pass it to my groovy script that does the validation.
The groovy script retrieves the value in the element path and assigns it to a variable actualReturn1 using ..
actualReturn1 = holder.getNodeValue(testElementOne);
where testElementOne could be either
//NS1:completedShipmentInfo/NS1:status/status/statusCode/code
OR
//NS1:createShipmentResponse/NS1:integrationFooter/errors/error/errorCode
The first path is valid and correctly assigns the value of this status field to actualReturn1.
But the second path does not appear to be valid and assigns null to actualReturn1.
Below are part of my 2 response files the elements I’m trying to extract data from.
Response with status element that is extracted successfully..
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<NS1:createShipmentResponse xmlns:NS1="http://www.royalmailgroup.com/api/ship/V1">
<NS1:integrationHeader>
<dateTime xmlns="http://www.royalmailgroup.com/integration/core/V1">2013-12-02T17:06:11</dateTime>
<version xmlns="http://www.royalmailgroup.com/integration/core/V1">1</version>
<identification xmlns="http://www.royalmailgroup.com/integration/core/V1">
<applicationId>111111113</applicationId>
<transactionId>420642961</transactionId>
</identification>
</NS1:integrationHeader>
<NS1:completedShipmentInfo>
<NS1:status>
<status>
<statusCode>
<code>Allocated</code>
</statusCode>
</status>
Response with errorCode that can not be extracted…
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<NS1:createShipmentResponse xmlns:NS1="http://www.royalmailgroup.com/api/ship/V1">
<NS1:integrationHeader>
<dateTime xmlns="http://www.royalmailgroup.com/integration/core/V1">2013-12-02T17:06:13</dateTime>
<version xmlns="http://www.royalmailgroup.com/integration/core/V1">1</version>
<identification xmlns="http://www.royalmailgroup.com/integration/core/V1">
<applicationId>111111113</applicationId>
<transactionId>420642961</transactionId>
</identification>
</NS1:integrationHeader>
<NS1:integrationFooter>
<errors xmlns="http://www.royalmailgroup.com/integration/core/V1">
<error>
<errorCode>E1101</errorCode>
<errorDescription>Name is a required field</errorDescription>
</error>
</errors>
Could someone tell me why this isn't working for the second response? If I have warning messages in a valid response then I'm also not able to extract the value. Is it because this is in the integrationFooter?
Happened to see this now, so adding the answer.
In the 2nd case, it was not working for you because of the namespace issue.
The element, errors is using default namespace and is different from its parent element integrationFooter. And in your xpath, no namespace was referred to element errors and its child elements.
Here is the script that works for 2nd case:
def xml = '''
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<NS1:createShipmentResponse xmlns:NS1="http://www.royalmailgroup.com/api/ship/V1">
<NS1:integrationHeader>
<dateTime xmlns="http://www.royalmailgroup.com/integration/core/V1">2013-12-02T17:06:13</dateTime>
<version xmlns="http://www.royalmailgroup.com/integration/core/V1">1</version>
<identification xmlns="http://www.royalmailgroup.com/integration/core/V1">
<applicationId>111111113</applicationId>
<transactionId>420642961</transactionId>
</identification>
</NS1:integrationHeader>
<NS1:integrationFooter>
<errors xmlns="http://www.royalmailgroup.com/integration/core/V1">
<error>
<errorCode>E1101</errorCode>
<errorDescription>Name is a required field</errorDescription>
</error>
</errors>
</NS1:integrationFooter>
</NS1:createShipmentResponse>
</soapenv:Body>
</soapenv:Envelope>'''
def holder = new com.eviware.soapui.support.XmlHolder( xml )
holder.declareNamespace('a','http://www.royalmailgroup.com/api/ship/V1')
holder.declareNamespace('b','http://www.royalmailgroup.com/integration/core/V1' )
def errorCode = holder.getNodeValue( "//a:integrationFooter/b:errors/b:error/b:errorCode" )
assert errorCode == 'E1101'
I have successfully connected to a remote webservice using SOAPUI (www.soapui.org). But, I am having trouble calling it successfully from CF9.2.
Here is my entire CFC function. There are dynamic vars but I've tested the output in the soapUI interface and it works:
<cffunction name="getOrganisation" access="remote" returnType="any" output="true">
<cfargument name="iPageNumber" type="any" required="false" default="0">
<cfargument name="iPageSize" type="any" required="false" default="0">
<cfargument name="bCurrentNamesOnly" type="boolean" required="false" default="1">
<cfargument name="bExcludeNotRtos" type="boolean" required="false" default="0">
<cfargument name="bExcludeRtoWithoutActiveRegistration" type="boolean" required="false" default="0">
<cfargument name="sFilter" type="any" required="false" default="">
<cfargument name="bIncludeCode" type="boolean" required="false" default="1">
<cfargument name="sRegistrationManagers" type="any" required="false" default="">
<cfargument name="sClassificationFilters" type="any" required="false" default="">
<cfargument name="sScheme" type="any" required="false" default="">
<cfset var endpoint = "https://ws.staging.training.gov.au/Deewr.Tga.WebServices/OrganisationService.svc/Organisation">
<cfsavecontent variable="soapBody">
<cfoutput>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ser="http://training.gov.au/services/"
xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<soapenv:Header/>
<soapenv:Body>
<ser:Search>
<ser:request>
<ser:PageNumber>#arguments.iPageNumber#</ser:PageNumber>
<ser:PageSize>#arguments.iPageSize#</ser:PageSize>
<ser:ClassificationFilters>
<ser:ClassificationFilter>
<ser:Scheme>#arguments.sScheme#</ser:Scheme>
<ser:Values>
<cfif len(arguments.sClassificationFilters)>
<cfloop list="#arguments.sClassificationFilters#" index="item">
<arr:string>#item#</arr:string>
</cfloop>
</cfif>
</ser:Values>
</ser:ClassificationFilter>
</ser:ClassificationFilters>
<ser:CurrentNamesOnly>#arguments.bCurrentNamesOnly#</ser:CurrentNamesOnly>
<ser:ExcludeNotRtos>#arguments.bExcludeNotRtos#</ser:ExcludeNotRtos>
<ser:ExcludeRtoWithoutActiveRegistration>#arguments.bExcludeRtoWithoutActiveRegistration#</ser:ExcludeRtoWithoutActiveRegistration>
<ser:Filter>#arguments.sFilter#</ser:Filter>
<ser:IncludeCode>#arguments.bIncludeCode#</ser:IncludeCode>
<ser:RegistrationManagers>
<cfif len(arguments.sRegistrationManagers)>
<cfloop list="#arguments.sRegistrationManagers#" index="item">
<arr:string>#item#</arr:string>
</cfloop>
</cfif>
</ser:RegistrationManagers>
</ser:request>
</ser:Search>
</soapenv:Body>
</soapenv:Envelope>
</cfoutput>
</cfsavecontent>
<cfhttp
url="#endpoint#"
method="post"
username="#variables.username#"
password="#variables.password#">
<cfhttpparam type="header" name="accept-encoding" value="no-compression" />
<cfhttpparam type="xml" value="#trim(soapBody)#"/>
</cfhttp>
<cfdump var="#cfhttp.FileContent#"><cfabort>
<cfreturn cfhttp.FileContent>
</cffunction>
Running this, I get the error:
An error occurred when verifying security for the message.
Following is the complete return xml
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</faultcode>
<faultstring xml:lang="en-AU">An error occurred when verifying security for the message.</faultstring>
</s:Fault>
</s:Body>
</s:Envelope>
So, it appears to be an authorisation issue.
Here is the SoapUI request screen:
So, how do I construct the cfhttp, or maybe cfinvoke, to emulate the soapUI call?
EDIT
SOAP Request XML
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://training.gov.au/services/" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<soapenv:Header/>
<soapenv:Body>
<ser:Search>
<ser:request>
<ser:PageNumber>0</ser:PageNumber>
<ser:PageSize>0</ser:PageSize>
<ser:ClassificationFilters>
<ser:ClassificationFilter>
<ser:Scheme></ser:Scheme>
<ser:Values>
<arr:string></arr:string>
</ser:Values>
</ser:ClassificationFilter>
</ser:ClassificationFilters>
<ser:CurrentNamesOnly>true</ser:CurrentNamesOnly>
<ser:ExcludeNotRtos>0</ser:ExcludeNotRtos>
<ser:ExcludeRtoWithoutActiveRegistration>0</ser:ExcludeRtoWithoutActiveRegistration>
<ser:Filter></ser:Filter>
<ser:IncludeCode>1</ser:IncludeCode>
<ser:RegistrationManagers>
<arr:string></arr:string>
</ser:RegistrationManagers>
</ser:request>
</ser:Search>
</soapenv:Body>
</soapenv:Envelope>
EDIT 2
Further information:
Here is the url directly to the service: https://ws.staging.training.gov.au/Deewr.Tga.WebServices/OrganisationService.svc
Below is a screenshot of some authentication related information from the docs
I'm thinking that you need to post the username and password in cfhttpparam tags, not as attributes in the cfhttp tag.
SOAPUI is a fantastic tool, and one I've bee using a lot recently when debugging SOAP requests or transferring them from static .wsdl files into a ColdFusion component.
The first thing to look at is the error message itself:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</faultcode>
<faultstring xml:lang="en-AU">An error occurred when verifying security for the message. </faultstring>
</s:Fault>
</s:Body>
</s:Envelope>
The faultcode node contains a link to the OASIS security namespace document:
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd
Viewing that in the browser, you can see what security values are required and you can clarify the naming conventions. So, we can confirm from this that you do need to send through the following with the following format:
Username
Password
Without having access to the request you are testing in SOAPUI, we can also see that the Username and Password values are visible in the property window (your screen grab from the interface, above).
Are these values set within the XML of the request in SOAPUI? Perhaps in the SOAP request header, like so:
<soapenv:Header>
<authInfo xsi:type="soap:authentication">
<Username xsi:type="xsd:string">?</Username>
<Password xsi:type="xsd:string">?</Password>
</authInfo>
</soapenv:Header>
If that is the case, you will also need to include this header in your ColdFusion component when building the soapBody variable.
Also, can you view the URL of the SOAP request directly in the browser to see what variables it expects?
https://ws.staging.training.gov.au/Deewr.Tga.WebServices/OrganisationService.svc/Organisation
The overall structure of your CFC and soapBody looks good, so without having access to the file you are running in SOAPUI to see it running, debugging it and providing answers would be a little tricky.
If you can rule out all of the possibilities mentioned above and still have issues, let me know.
Yes, you were not originally passing a Oasis security header. The answers here so far probably aren't going to work however. Oasis standard can allow for many an varied combinations of user/password/nonce/digest/created and encoding attributes.
As you may or may not have found, the Axis 1 library (CF9 and lower user Axis 1 (versions 1.1-1.4); CF10 also has Axis 2 (Axis version 1.6)). And thus you must POST (cfhttp/http) to pass and receive an Oasis header. The Axis 1 library will cry about trying to understand the Oasis node in the header area.**
Since you are manually posting, you can simply construct your Oasis header in your header much like the example fro Matt Gifford.
Depending on what exactly the receiving party is expecting, you may will have something like this:
<wsse:Security soap:mustUnderstand="true" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<wsse:UsernameToken wsu:Id="UsernameToken-15">
<wsse:Username>
<!-- Removed-->
</wsse:Username>
<wsse:Password>
<!-- Removed-->
</wsse:Password>
<wsse:Nonce>
<!-- Removed-->
</wsse:Nonce>
<wsu:Created>2012-07-11T02:02:48.410Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
or this (from early cladding method pre-output):
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" >
<wsse:Username>#Arguments.szUserName#</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0##PasswordText">#Arguments.szPassword#</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
or this (final output):
<wsse:Security soapenv:mustUnderstand="1"xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-974900"xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>SuperJellyMan</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">jellybeanboom</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">SmVsbHlCZWFuQm9vbTk3NDkwMA==</wsse:Nonce>
<wsu:Created>2012-07-26T17:00:34Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
And so on and so forth. I have seen people invoke java libraries to do this more dynamically. I simply built a few simple methods to build my nonce and format my xml time stamp. But basically, it is pretty simple to build some kind of function or other helper methods to clad the values required in xml with the proper Oasis attributes and xsd references and then insert that in your header of your request of the manual post.
The tricky part is knowing exactly what they want in the Oasis security header if they do not tell you. The xsd simply shows what is acceptable according to Oasis standards, but not necessarily what they are using (and in what combination). If you can get that from them, you can pretty easily put that together from the Oasis docs.
Usually, the combination is User/Pwd (first example). If a Nonce is used, very often a Password Digest is also used (the password gets a ##PasswordDigest instead of ##PasswordText) and is an encoded hash of the created time and password (see Oasis docs for more explanation).
But, the last project I worked on had a plain text pwd plus a nonce with no digest. Not exactly logical since the nonce is supposed to make a fake request more difficult and use a non-clear text password which needs to be decoded by receiver and compared to validate... So it is totally up to the service on what they want/use/need.
You should be able to paste your concocted Oasis header into SoapUI and pretty quickly figure out what they might need/want from their responses to same.
If they have specified user/password (as text), you might find one of these examples (probably the second one) workable and not passing the nonce and created elements.
** Here is the Axis 1 fault for fun reference when Oasis is used with CF9 or less using actual SOAP methods (web service stub, rather than manual post):**
The fault returned when invoking the web service operation is: AxisFault faultCode: {http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}InvalidSecurity faultSubcode: faultString: An error occurred when verifying security for the message. faultActor: faultNode:
faultDetail: {http://xml.apache.org/axis/}stackTrace:An error occurred when verifying security for the message. at org.apache.axis.message.SOAPFaultBuilder.createFault(SOAPFaultBuilder.java:221) at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder.java:128) at org.apache.axis.encoding.DeserializationContext.endElement(DeserializationContext.java:1087)
at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source) at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source) at org.apache.xerces.parsers.XML11Conf...
[EDIT]
Here is a bit more info as I am working on another webservice that is similar.
Your [SOAP] xml with the cannot possibly be working. I use soapUI as well and unless I add in a security header values in their proper spot the service will return exactly the response you are receiving ("InvalidSecurity") so not very sure this xml is what you should be trying to replicate. I have also successfully built a simple cf based script version to build the header which properly generates the header and adds it to a createObject() invoked javastubbed webservice:
doc = xmlNew();
doc['Security'] = XmlElemNew(doc,'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd', 'Security');
doc.Security['UsernameToken'] = XmlElemNew(doc, 'UsernameToken');
doc.Security.UsernameToken['Username'] = XmlElemNew(doc, 'Username');
doc.Security.UsernameToken.username.XmlText = "TESTERDUDE" ;
doc.Security.UsernameToken.username.XmlAttributes["xsi:type"] = "xsd:string";
doc.Security.UsernameToken['Password'] = XmlElemNew(doc, 'Password');
doc.Security.UsernameToken.password.XmlText = "YetAnotherPassword";
doc.Security.UsernameToken.password.XmlAttributes["xsi:type"] = "xsd:string";
doc.Security.UsernameToken.password.XmlAttributes["Type"] = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0##PasswordDigest";
doc.Security.UsernameToken['Nonce'] = XmlElemNew(doc, 'Nonce');
doc.Security.UsernameToken.nonce.XmlText = "tKUH8ab3Rokm4t6IAlgcdg9yaEw="; // This would be generated if needed
doc.Security.UsernameToken.nonce.XmlAttributes["xsi:type"] = "xsd:string";
doc.Security.UsernameToken['Created'] = XmlElemNew(doc, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", 'Created');
doc.Security.UsernameToken.created.XmlText = "2010-08-10T10:52:42Z";
doc.Security.UsernameToken.created.XmlAttributes["xsi:type"] = "xsd:string";
addSOAPRequestHeader(ws, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security", doc);
This properly generates [taken from the server side xml using getSoapRequest() which grabs the entire xml request] :
<soapenv:Header>
<Security soapenv:actor="" soapenv:mustUnderstand="0" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken>
<Username xsi:type="xsd:string">TESTERDUDE</Username>
<Password xsi:type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">My Password is my Voice</Password>
<Nonce xsi:type="xsd:string">tKUH8ab3Rokm4t6IAlgcdg9yaEw=</Nonce>
<Created xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ns2="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xsi:type="xsd:string">2010-08-10T10:52:42Z</Created>
</UsernameToken>
</Security>
</soapenv:Header>
I am using Coldfusion 8. I have exceedingly limited experience with SOAP.
I am trying to send out a SOAP request. My SOAP body looks like this:
<cfsavecontent variable="SoapBody">
<cfoutput>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v2="http://www.a2zshow.com/DataServices/v2/" >
<soapenv:Header>
<a2zAuthenticationHeader xmlns="http://www.a2zshow.com/DataServices/v2/">
<Key>#Key#</Key>
<UserName>#UserName#</UserName>
<Password>#Password#</Password>
<InstallName>#InstallName#</InstallName>
</a2zAuthenticationHeader>
</soapenv:Header>
<soapenv:Body>
<DataService xmlns="http://www.a2zshow.com/DataServices/ExhibitorListRequest/v1">
<Request>
<a2zXMLRootNode>
<RequestHeader>
<RequestAttribute Search="NONE"/>
</RequestHeader>
<RequestCriteria>
<EventID>#EventID#</EventID>
</RequestCriteria>
</a2zXMLRootNode>
</Request>
</DataService>
</soapenv:Body>
</soapenv:Envelope>
</cfoutput>
</cfsavecontent>
My SOAP request looks like this:
<cfhttp
url="#PostURL#"
method="post"
result="httpResponse">
<cfhttpparam
type="header"
name="SOAPAction"
value="#SOAPAction#" />
<cfhttpparam
type="xml"
value="#trim(soapBody)#"/>
</cfhttp>
The SOAPAction variable is set like this:
SOAPAction = "http://www.a2zshow.com/getExhibitorList";
I think I am successfully posting to the right place, but I am getting an error message saying that client didn't recognize the SOAPAction. Here's my error:
soap:ClientServer did not recognize the value of HTTP Header SOAPAction: http://www.a2zshow.com/getExhibitorList.
This error seems to be telling me that I don't have the SOAPAction correct. The guy at the other end tells me that I have everything set up right and that it should be working. Is there something missing?
The error was in the vendor's SOAPAction. They gave me the wrong URL. Their documentation was created 8 years ago and they updated it in 2008.
I guess they would rather spend time making their product hard to use by confusing people with the wrong information than to help get something done.
Thanks for the help!