SOAP web services

Michael Mantkowski michaelj at clientrax.com
Mon Jul 2 08:19:49 EDT 2018


Here is an even simpler example similar to what Rudolf suggests.  It asks
for a set of lab results from previous orders.  In this method I have
created a XML Template that is stored in a folder on the Hard Drive making
it easy to modify should the Lab Company make any changes.  I open the
template, replace the necessary fields for credentials or other information
as needed and then POST the request using generic HTTP POST, GET or DELETE
as needed.  (I do the same for REST as well.)  It's rather simple.  I
usually just ask the Server-Side people to send me a sample of the requests
I need and set them up as templates.  Can have a new service setup in an
hour this way.

I normally parse the results myself as I have found that I can code up a
parsing method that is on average 10 to 20 times faster than a generic
method which becomes important when you are download 50 to 100 sets of lab
results in one go.

;  gets last 30 results
If cvBeta
    Calculate lvURL as 'https://betaservices.idexx.com/laboratory/results'
;; Beta
Else
    Calculate lvURL as 'https://services.idexx.com/laboratory/results'
;; Production
End If

Calculate lvXMLpath as con(PdIdexxWeb,sys(9),'getResults.xml')
Do FileOps.$doesfileexist(lvXMLpath) Returns #F
If flag true
    Do FileOps.$splitpathname(lvXMLpath,lvDrv,lvDir,lvFile,lvExt)
    Calculate lvAction as lvFile     ;; Action is the name of the File
    ReadBinFile (lvXMLpath,lvXML) Returns lvError
    If lvError<0
        OK message Error (Icon,Sound bell) {Error - Read File: [lvXMLpath] -
Error = [lvError]}
    End If
Else
    OK message  {'Not Setup - Cannot Find Templates'}
End If

;  Get User ID
Begin reversible block
    Set main file {IdexxUsers}
End reversible block
Set search as calculation {IdexxLoc=inLoc}
Do code method S.SQL/Find (IdexxINI,kTrue,kTrue,'RXX')
If flag false
    OK message Error... (Icon,Sound bell) {The Curent User - RXX - Is not
Setup to Use Idexx Labs. . .}
    Quit method 0
End If
Calculate IdexxUserID as '123456'
Do replace(lvXML,'>username<',con('>',IdexxUserID,'<')) Returns lvXML
Do replace(lvXML,'>password<',con('>',IdexxPassword,'<')) Returns lvXML

Do method ----setHeaderList (cvHeaderList,kTrue,'userId',IdexxUserID)
Do method ----setHeaderList (cvHeaderList,kFalse,'password',IdexxPassword)
Do method ----setHeaderList
(cvHeaderList,kFalse,'sourceIdentifier','CLIENTRAX')
Do method ----setHeaderList (cvHeaderList,kFalse,'SOAPAction',lvAction)
Do method ----setHeaderList (cvHeaderList,kFalse,'Content-Type','text/xml;
charset=utf-8')

Do method ----postRequest
(lvURL,cvHeaderList,lvXML,IdexxUserID,IdexxPassword,lvResponseText) Returns
lvResponseCode
If lvResponseCode='200 OK'
    If pos('<labResults requisitionID=',lvResponseText)>0
        Do replaceall(lvResponseText,'<','<') Returns lvResponseText
        Do replaceall(lvResponseText,'>','>') Returns lvResponseText
        Do replaceall(lvResponseText,'&','&') Returns lvResponseText
        WriteBinFile
(con(PdIdexxWeb,sys(9),'downloads',sys(9),jst(#D,'DT:MDY
HNS'),'.xml'),lvResponseText) Returns #1
    End If
    Quit method 1
End If
;  Error
Calculate lvXML as con('URL:
',lvURL,chr(13,13),lvXML,chr(13,13),lvResponseText)
Do method ----getBlockTag (lvResponseText,'faultcode') Returns lvFaultID
Do method ----getBlockTag (lvResponseText,'faultstring') Returns
lvFaultString
Copy to clipboard lvXML
OK message Error - Idexx Get Results (Icon,Sound bell) {[lvFaultString]
[lvFaultID] - Req XML is on the ClipBoard}
Breakpoint
Quit method 0

*********************************************************************
Michael Mantkowski
ClienTrax Software
1-614-875-2245
*********************************************************************


-----Original Message-----
From: omnisdev-en <omnisdev-en-bounces at lists.omnis-dev.com> On Behalf Of
Rudolf Bargholz
Sent: Monday, July 2, 2018 7:56 AM
To: OmnisDev List - English <omnisdev-en at lists.omnis-dev.com>
Subject: AW: SOAP web services

Hi Andrea,

As a consumer, SOAP is just a wrapper on top of an HTTP POST. You test the
interface in soapUI, copy the raw structure of the request from soapUI, and
build the request in Omnis using the oXml/Text blocks and HTTP xComp object
in Omnis. The response is XML, and you can parse the XML using the oXml in
Omnis Studio. There really is no need for anything special in Omnis Studio
to support SOAP. As long as the HTTP and oXml objects work in Studio you
will also be able to use Studio as a SOAP consumer.

As SOAP is just XML, I do not think Omnis really needs to document this
explicitly, other than perhaps with a tech note. REST is it's own data
structure, that requires its own xComp to generate JSON or parse JSON, so it
does make sense to spend more time documenting this. There is no need to use
the complex Java interface to send SOAP requests. This just complicates
matters.

Below some code of ours that might help. We still use Studio 4.3.2.1, but I
cannot imagine Omnis removing the HTTP xComp.

Regards

Rudolf Bargholz



Begin text block
;  Header
Text: <soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:olt="[iSoapSessionList.Url]/[iWsLibrary]/[iWsService].wsdl">
Text: <soapenv:Header/>
Text: <soapenv:Body>
Text: <olt:[iWsMethod]>

;  Body
Text:
<olt:pBookingSource>[$cinst.$_urlEncodeString(ir_olt_web_oltlogon.pBookingSo
urce)]</olt:pBookingSource>

;  Footer
Text: </olt:[iWsMethod]>
Text: </soapenv:Body>
Text: </soapenv:Envelope> 

End text block
Get text block iRequest



Calculate iSoapSessionList.SendCharset as 'UTF-8'
Calculate iSoapSessionList.SendTimeout as 15 Calculate
iSoapSessionList.ReceiveTimeout as 60 Calculate
iSoapSessionList.ConnectTimeout as 15 Calculate
iSoapSessionList.SendContentType as 'text/xml'
Calculate iSoapSessionList.ResponseContentType as 'text/xml'


Calculate lHttpObj as #NULL
Do $root.$extobjects.WebWin32 Library.$objects.HTTP.$newref() Returns
lHttpObj

;  Clear status fields
Do method $clearResponse

;  Set flags in HTTP object
Calculate lHttpObj.$escapedisable as 0
Calculate lHttpObj.$escapedisablequery as 0 Calculate
lHttpObj.$escapepercent as 0 Calculate lHttpObj.$nullcodepage as 0 Calculate
lHttpObj.$refresh as 0 Calculate lHttpObj.$disablecookies as 0 Calculate
lHttpObj.$disablekeepalive as 0 Calculate lHttpObj.$disableredirects as 0 ;
Security flags Calculate lHttpObj.$securityallowcertcninvalid as 0 Calculate
lHttpObj.$securityallowcertdateinvalid as 0 Calculate
lHttpObj.$securityallowunknownca as 0 Calculate
lHttpObj.$securityignorewrongcertusage as 0 ;  Timeouts and retries
Calculate lHttpObj.$sendtimeout as iSoapSessionList.SendTimeout Calculate
lHttpObj.$receivetimeout as iSoapSessionList.ReceiveTimeout Calculate
lHttpObj.$connecttimeout as iSoapSessionList.ConnectTimeout Calculate
lHttpObj.$connectretries as 1 ;  Proxy Calculate lHttpObj.$proxy as 0
Calculate lHttpObj.$proxyname as ''
Calculate lHttpObj.$proxybypasslist as ''

;  Set other properties
Calculate lUrl as trim(iSoapSessionList.Url,0,1,'/')
Calculate lUrl as con(lUrl,'/',iWsLibrary,'/',iWsService)
Calculate lHttpObj.$url as lUrl

Do lAcceptList.$define(lAcceptType)
Calculate lHttpObj.$accept as lAcceptList Do
lExtraHeadersList.$define(lExtraHeaderName,lExtraHeaderValue)
If len(iSoapSessionList.SoapAction)>0
;  SOAPAction: "http://127.0.0.1:6001?POOL=WS"
Do lExtraHeadersList.$add('SOAPAction',iSoapSessionList.SoapAction)
End If
If len(iSoapSessionList.Username)>0&len(iSoapSessionList.Password)>0
Calculate lUsername as iSoapSessionList.Username Calculate lPassword as
iSoapSessionList.Password Calculate lAuthorizationString as
con(lUsername,':',lPassword)
;  Calculate lAuthorizationStringBase64 as
OXML.$base64encode(lAuthorizationString)     ;; @MOD:rb:2013-10-10: Bug in
OXML.$base64encode
Calculate lAuthorizationStringBase64 as base64Encode(lAuthorizationString)
Do lExtraHeadersList.$add('Authorization',con('Basic
',lAuthorizationStringBase64)) End If Calculate lHttpObj.$extraheaders as
lExtraHeadersList Calculate lHttpObj.$httpversion as kWebHttpVersion11
Calculate lHttpObj.$sendcontenttype as iSoapSessionList.SendContentType
Calculate lHttpObj.$responsecontenttype as
iSoapSessionList.ResponseContentType

;  Execute the HTTP method
Calculate lHttpObj.$sendcharset as 'UTF-8'     ;; 'ISO-8859-1'   'UTF-8'
Do lHttpObj.$dohttpmethod('POST',iRequest) Returns FlagOK

;  Get any error code values
Calculate iErrorCode as lHttpObj.$httperrorcode Calculate iErrorName as
lHttpObj.$geterrorcodename(iErrorCode)
Calculate iErrorText as trim(con(iErrorName,' ',lHttpObj.$httperrortext))

If FlagOK
Do lHttpObj.$getbinaryresponse() Returns lBinary If isnull(lBinary)
Calculate FlagOK as kFalse Calculate iErrorCode as -999999 Calculate
iErrorName as 'WebWin32_HttpPost__NULL_getcharacterresponse'
Calculate iErrorText as con('WebWin32_HttpPost__NULL_getcharacterresponse:
','A NULL response was returned for the HTTP call. This is a fatal error and
must be traced.')

Do lHttpObj.$deleteref()     ;; Important: must delete the object reference
otherwise a memory leak might occur
Calculate lHttpObj as #NULL
Break to end of loop     ;; This error needs to be logged. A loop would
destroy the error message.
Else
If binlength(lBinary)>0
Do lXmlDomObj.$setempty() Returns #F
Calculate lXmlDomObj.$parservalidates as 0 Calculate
lXmlDomObj.$outputencoding as kXMLEncodingISO8859 Calculate
lXmlDomObj.$replaceentityreferences as kTrue

If not(OXML.$maybexml(lBinary))
Calculate iErrorCode as -999999
Calculate iErrorName as 'Soap response not XML'
Calculate iErrorText as con(iErrorName,': ',iResponse) Calculate FlagOK as
kFalse Else If not(lXmlDomObj.$loadbinary(lBinary,lErrorText))
Calculate iErrorCode as -999999
Calculate iErrorName as 'Soap response not XML'
Calculate iErrorText as con(iErrorName,': ',iResponse,chr(13,13),lErrorText)
Calculate FlagOK as kFalse
Else
Do lXmlDomObj.$getelementsbytagname('return',lErrorText) Returns lx_nl If
lx_nl.$length=0

Else
Calculate lx_n as lx_nl.$item(0)
Do lx_n.$getcdatasection(iReturn)
End If
End If
End If
End If
End If
Else

End If

If lHttpObj.$validref
Do lHttpObj.$deleteref()     ;; Important: must delete the object reference
otherwise a memory leak might occur
End If
Calculate lHttpObj as #NULL



-----Ursprüngliche Nachricht-----
Von: omnisdev-en [mailto:omnisdev-en-bounces at lists.omnis-dev.com] Im Auftrag
von Andrea Zen
Gesendet: Montag, 2. Juli 2018 09:34
An: OmnisDev List - English <omnisdev-en at lists.omnis-dev.com>
Betreff: SOAP web services

Hello, about Omnis as a SOAP web services consumer...
I see it's still possible in Omnis 8.1 to create, through "class wizard", an
object to use a SOAP web service given a WSDL file spec.
But I've noticed the relative section from the "Extending Omnis" manual has
disappeared. The manual now only talks about REST.
Anyone knows if the support to SOAP web services is going to be removed in
next versions? Or maybe it will be kept only for backward compatibility?

Andrea Zen
_____________________________________________________________
Manage your list subscriptions at http://lists.omnis-dev.com Start a new
message -> mailto:omnisdev-en at lists.omnis-dev.com
_____________________________________________________________
Manage your list subscriptions at http://lists.omnis-dev.com Start a new
message -> mailto:omnisdev-en at lists.omnis-dev.com 




More information about the omnisdev-en mailing list