As I showed earlier we can real easy set up consumption of REST services provided by someone else – and we can just as easily expose REST services to others from our running MDriven system.
But then someone came along and asked “How do I pull data from a SOAP service?”. My initial answer was – you convert it to a REST service first. But that sort of sounded a bit “hollow” and not very “us”.
What we have done in releases from today and onwards is to add a new verb to ocl selfVM (the variable available in ViewModels and first mentioned here).
The new verb is selfVM.SoapCall.
This is how it works
We have a SOAP service, with a method like the one found here: http://www.webservicex.net/stockquote.asmx?op=GetQuote (I hope this is available for perpetuity – but if it is not you should know that it is not really that important for this article – it is just a practical example )
We want to call it using MDriven
We first add an action to the ViewModel and set the expression to this:
When hovering over the function in the ocl editor we get a hint that gives explanatory names to the parameters:
TargetUrl: The url of the web service (the service – not the method in the service) – in our case ‘http://www.webserviceX.NET/stockquote.asmx’
action: The name of the method in the service – in our case ‘GetQuote’
actionnamespace: this is a bit tricky – you will find it in the wsdl here:
In our case the actionnamespace is ‘http://www.webserviceX.NET/’ (it was the same as the location for this service – but it can be anything really – keep track on case and trailing slash etc – all is important)
user: in our case we leave this blank since the service is open
nestingWithParams: This is the name of the ViewModel nesting (a blue box) that holds the arguments to the action call – the wsdl says the call expects 1 string parameter with name ‘symbol’:
In our case we said ‘NestingWParams’ so we must create a ViewModel nesting with that name:
In this case I hard coded it to ‘IBM’ – the only stock symbol I could guess – I could just as easily picked an attribute from the model or a variable from the ViewModel by entering any ocl expression.
In our action we catch the resulting string into a variable of the ViewModel that we call: vNewVar
I add a ViewModelColumn to show the value of this variable and we get this after hitting the button that executes our action:
Copying the result into notepad++ and applying xml prettyprint we have this:
The real answer is inside the GetQuoteResult element – but it seems as the we service handed us back html coded xml in there… So we would need to do some cleaning up before using data from this service.
After replacing < with < and > with > I have this:
<AnnRange>116.90 – 179.25</AnnRange>
<Name>International Business Machines</Name>
I will not cover in this article how you get this into objects – but it is the same strategy as for REST service consumption; use XmlToObjects as described here
More complex types as input
It is not unusual that the input types to SOAP services methods are complex – having many arguments in many levels.
Like this example: http://www.webservicex.net/genericbarcode.asmx?op=GenerateBarCode
This service wants input like this:
As you see the arguments comes in 2 levels under action – the root level with the Barcodetext at the bottom – and a sublevel called BarCodeParam.
To define this in the ViewModel we simply do nestings like this:
The order is important – it must match the order in the service.
As you can imagine it can be error prone to get the message exactly correct when calling Soap services like this. For this reason we added a way to inspect the messages we send in order to debug them. If you add a ViewModel variable named vSoapDebug – when we find this in the ViewModel – we assign the complete SoapEnvelope to it prior to sending the message.
Our example will look like this:
When we execute the action we find this in the vSoapDebug variable:
You can then verify that we really send a valid request to the service.
In our samples we did not enter a user and pwd since we consumed open services. But when you make use of user and pwd the envelope will get a header part. For the message above it would look like this:
The SOAP standard calls for a Nonce element – and a special way to implement its value and password-passing.