SOAP the protocol from the stone age
No edit summary
(Replacing message template with parser tag)
 
(7 intermediate revisions by 2 users not shown)
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.
<message>Write the content here to display this box</message>
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 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 [[Training: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:
vNewVar:=selfVM.SoapCall(‘<nowiki>http://www.webserviceX.NET/stockquote.asmx’,’GetQuote’,’http://www.webserviceX.NET/’,”,”,’NestingWParams’</nowiki>)
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’
 
* '''actionnamespace''': This is a bit tricky – you will find it in the wsdl here:
'''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:
[[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 – 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
'''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’:
'''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’:
[[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 39:
[[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:
 
<?xml version=”1.0″?>
 
<StockQuotes>
 
<Stock>
 
<Symbol>IBM</Symbol>
 
<Last>177.30</Last>
 
<Date>1/27/2017</Date>
 
<nowiki><Time>4:00pm</Time></nowiki>
 
<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>


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]]
After replacing &amp;lt; with < and &amp;gt; with > I have this:<blockquote><?xml version=”1.0″?></blockquote><blockquote><StockQuotes></blockquote><blockquote><Stock></blockquote><blockquote><Symbol>IBM</Symbol></blockquote><blockquote><Last>177.30</Last></blockquote><blockquote><Date>1/27/2017</Date></blockquote><blockquote><nowiki><Time>4:00pm</Time></nowiki></blockquote><blockquote><Change>-1.36</Change></blockquote><blockquote><Open>178.47</Open></blockquote><blockquote><High>179.20</High></blockquote><blockquote><Low>177.30</Low></blockquote><blockquote><Volume>3482311</Volume></blockquote><blockquote><MktCap>168.19B</MktCap></blockquote><blockquote><PreviousClose>178.66</PreviousClose></blockquote><blockquote><PercentageChange>-0.76%</PercentageChange></blockquote><blockquote><AnnRange>116.90 – 179.25</AnnRange></blockquote><blockquote><Earns>12.38</Earns></blockquote><blockquote><P-E>14.32</P-E></blockquote><blockquote><Name>International Business Machines</Name></blockquote><blockquote></Stock></blockquote><blockquote></StockQuotes></blockquote>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 54:
[[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 Barcode text 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 before sending the message.
 
Our example will look like this:
 
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:
Our example will look like this:<blockquote>vNewVar2:=selfVM.SoapCall(‘<nowiki>http://www.webserviceX.NET/genericbarcode.asmx’,’GenerateBarCode’,’http://www.webservicex.net/’,”,”,’genericbarcodeParams’</nowiki>)</blockquote>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:<blockquote>vNewVar2:=selfVM.SoapCall(‘http://www.webserviceX.NET/genericbarcode.asmx’,’GenerateBarCode’,’http://www.webservicex.net/’,‘SomeUserName’,‘SomePassword’,’genericbarcodeParams<nowiki/>’)</blockquote>[[File:SOAP - 11.png|none|frame|535x535px]]
 
vNewVar2:=selfVM.SoapCall(‘http://www.webserviceX.NET/genericbarcode.asmx’,’GenerateBarCode’,’http://www.webservicex.net/’,‘SomeUserName’,‘SomePassword’,’genericbarcodeParams<nowiki/>’)
[[File:SOAP - 11.png|none|frame|535x535px]]


The SOAP standard calls for a Nonce element – and a special way to implement its value and password-passing.
The SOAP standard calls for a Nonce element – and a special way to implement its value and password-passing.
[[Category:View Model]]
[[Category:View Model]]
{{Edited|July|12|2024}}
[[Category:TOC]]

Latest revision as of 07:55, 17 June 2024

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:

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 – 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’:
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 Barcode text 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 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:

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 95 days ago on 06/17/2024. What links here