We can easily set up the consumption of REST services provided by someone else and expose REST services to others from our running MDriven system.
But someone came along and asked, “How do I pull data from a SOAP service?” My initial answer was: convert it into a REST service first - but that sounded a bit “hollow” and unlike “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 important to 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:
vNewVar:=selfVM.SoapCall(‘http://www.webserviceX.NET/stockquote.asmx’,’GetQuote’,’http://www.webserviceX.NET/’,”,”,’NestingWParams’)
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 – which keeps track of the case and trailing slash, etc – all is important).
- user: in our case, we leave this blank since the service is open
- password: ditto
- 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’:
We said ‘NestingWParams’ so we must create a ViewModel nesting with that name:
I hard-coded it to ‘IBM’ – the only stock symbol I could guess. I could easily pick 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 though the service handed us back HTML-coded XML in there… We would need to do some cleaning up before using data from this service.
After replacing < with < and > with > I have this:
<?xml version=”1.0″?>
<StockQuotes>
<Stock>
<Symbol>IBM</Symbol>
<Last>177.30</Last>
<Date>1/27/2017</Date>
<Time>4:00pm</Time>
<Change>-1.36</Change>
<Open>178.47</Open>
<High>179.20</High>
<Low>177.30</Low>
<Volume>3482311</Volume>
<MktCap>168.19B</MktCap>
<PreviousClose>178.66</PreviousClose>
<PercentageChange>-0.76%</PercentageChange>
<AnnRange>116.90 – 179.25</AnnRange>
<Earns>12.38</Earns>
<P-E>14.32</P-E>
<Name>International Business Machines</Name>
</Stock>
</StockQuotes>
In this article, I will not cover how you get this into objects – but it is the same strategy as that of 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 on many levels.
Like this example: http://www.webservicex.net/genericbarcode.asmx?op=GenerateBarCode
This service wants input like this:
As you see, the arguments come in 2 levels under action – the root level with the Barcode text 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 before sending the message.
Our example will look like this:
vNewVar2:=selfVM.SoapCall(‘http://www.webserviceX.NET/genericbarcode.asmx’,’GenerateBarCode’,’http://www.webservicex.net/’,”,”,’genericbarcodeParams’)
When we execute the action, we find this in the vSoapDebug variable:
You can then verify that we sent a valid request to the service.
Authentication
In our samples, we did not enter a user and pwd since we consumed open services. When you make use of user and pwd, the envelope will get a header part. For the message above, it would look like this:
vNewVar2:=selfVM.SoapCall(‘http://www.webserviceX.NET/genericbarcode.asmx’,’GenerateBarCode’,’http://www.webservicex.net/’,‘SomeUserName’,‘SomePassword’,’genericbarcodeParams’)
The SOAP standard calls for a Nonce element – and a special way to implement its value and password-passing.