SOAP the protocol from the stone age
No edit summary
No edit summary
Line 1: Line 1:
We can real easy set up consumption of [[Rest Services In MDriven|REST services]] provided by someone else and we can just as easily expose REST services to others from our running MDriven system.
We can easily set up the consumption of [[Rest Services In MDriven|REST services]] provided by someone else and 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”.
But then 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 [[Efficient ViewModel fetch|first mentioned here]]).
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 [[Efficient ViewModel fetch|first mentioned here]]).


The new verb is selfVM.SoapCall.
The new verb is selfVM.SoapCall.


== This is how it works ==
== 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 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 Want to Call It Using MDriven ==
We first add an action to the ViewModel and set the expression to this:<blockquote>vNewVar:=selfVM.SoapCall(‘<nowiki>http://www.webserviceX.NET/stockquote.asmx’,’GetQuote’,’http://www.webserviceX.NET/’,”,”,’NestingWParams’</nowiki>)</blockquote>When hovering over the function in the ocl editor we get a hint that gives explanatory names to the parameters:
We first add an action to the ViewModel and set the expression to this:<blockquote>vNewVar:=selfVM.SoapCall(‘<nowiki>http://www.webserviceX.NET/stockquote.asmx’,’GetQuote’,’http://www.webserviceX.NET/’,”,”,’NestingWParams’</nowiki>)</blockquote>When hovering over the function in the OCL editor, we get a hint that gives explanatory names to the parameters:


[[File:SOAP -1 .png|frameless|522x522px]]
[[File:SOAP -1 .png|frameless|522x522px]]


'''TargetUrl''': The url of the web service (the service – not the method in the service) – in our case ‘<nowiki>http://www.webserviceX.NET/stockquote.asmx’</nowiki>
'''TargetUrl''': The URL of the web service (the service – not the method in the service) – in our case ‘<nowiki>http://www.webserviceX.NET/stockquote.asmx’</nowiki>


'''action''': The name of the method in the service – in our case ‘GetQuote’
'''action''': The name of the method in the service – in our case ‘GetQuote’
Line 22: Line 22:
[[File:SOAP - 2.png|none|frame]]
[[File:SOAP - 2.png|none|frame]]


In our case the actionnamespace is ‘<nowiki>http://www.webserviceX.NET/’</nowiki> (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)
In our case, the actionnamespace is ‘<nowiki>http://www.webserviceX.NET/’</nowiki> (it was the same as the location for this service – but it can be anything really – 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
'''user''': in our case, we leave this blank since the service is open


'''password''': dito
'''password''': dito
Line 31: Line 31:
[[File:SOAP - 3.png|none|thumb|588x588px]]
[[File:SOAP - 3.png|none|thumb|588x588px]]


In our case we said ‘NestingWParams’ so we must create a ViewModel nesting with that name:
We said ‘NestingWParams’ so we must create a ViewModel nesting with that name:
[[File:SOAP - 4.png|none|thumb]]
[[File:SOAP - 4.png|none|thumb]]


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.
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
In our action, we catch the resulting string into a variable of the ViewModel that we call: vNewVar
[[File:SOAP - 5.png|none|frame|573x573px]]
[[File:SOAP - 5.png|none|frame|573x573px]]


Line 42: Line 42:
[[File:SOAP - 6.png|none|frame|670x670px]]
[[File:SOAP - 6.png|none|frame|670x670px]]


Copying the result into notepad++ and applying xml prettyprint we have this:
Copying the result into notepad++ and applying XML prettyprint we have this:
[[File:SOAP - 7.png|none|frame|577x577px]]
[[File:SOAP - 7.png|none|frame|577x577px]]


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.
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 &amp;lt; with < and &amp;gt; with > I have this:
After replacing &amp;lt; with < and &amp;gt; with > I have this:
Line 91: Line 91:
</StockQuotes>
</StockQuotes>


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 [[Import xml and JSon with MDriven|described here]]
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 [[Import xml and JSon with MDriven|described here.]]


== More complex types as input ==
== 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.
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
Like this example: http://www.webservicex.net/genericbarcode.asmx?op=GenerateBarCode
Line 101: Line 101:
[[File:SOAP - 8.png|none|frame|464x464px]]
[[File:SOAP - 8.png|none|frame|464x464px]]


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.
As you see, the arguments come 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:
To define this in the ViewModel, we simply do nestings like this:
[[File:SOAP - 9.png|none|frame|282x282px]]
[[File:SOAP - 9.png|none|frame|282x282px]]


The order is important – it must match the order in the service.
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.
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:
Our example will look like this:
Line 114: Line 114:
vNewVar2:=selfVM.SoapCall(‘<nowiki>http://www.webserviceX.NET/genericbarcode.asmx’,’GenerateBarCode’,’http://www.webservicex.net/’,”,”,’genericbarcodeParams’</nowiki>)
vNewVar2:=selfVM.SoapCall(‘<nowiki>http://www.webserviceX.NET/genericbarcode.asmx’,’GenerateBarCode’,’http://www.webservicex.net/’,”,”,’genericbarcodeParams’</nowiki>)


When we execute the action we find this in the vSoapDebug variable:
When we execute the action, we find this in the vSoapDebug variable:
[[File:SOAP - 10.png|none|frame|512x512px]]
[[File:SOAP - 10.png|none|frame|512x512px]]


You can then verify that we really send a valid request to the service.
You can then verify that we sent a valid request to the service.


== Authentication ==
== Authentication ==
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:
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<nowiki/>’)
vNewVar2:=selfVM.SoapCall(‘http://www.webserviceX.NET/genericbarcode.asmx’,’GenerateBarCode’,’http://www.webservicex.net/’,‘SomeUserName’,‘SomePassword’,’genericbarcodeParams<nowiki/>’)

Revision as of 08:46, 22 February 2023

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 then 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:

SOAP -1 .png

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:

SOAP - 2.png

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 – 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: dito

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’:

SOAP - 3.png

We said ‘NestingWParams’ so we must create a ViewModel nesting with that name:

SOAP - 4.png

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

SOAP - 5.png

I add a ViewModelColumn to show the value of this variable and we get this after hitting the button that executes our action:

SOAP - 6.png

Copying the result into notepad++ and applying XML prettyprint we have this:

SOAP - 7.png

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 &lt; with < and &gt; 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:

SOAP - 8.png

As you see, the arguments come 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:

SOAP - 9.png

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:

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:

SOAP - 10.png

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’)

SOAP - 11.png

The SOAP standard calls for a Nonce element – and a special way to implement its value and password-passing.

This page was edited 5 days ago on 06/17/2024. What links here