SOAP web services

Michael Mantkowski michaelj at
Mon Jul 2 09:37:36 EDT 2018

Hi Rudolf,

No Omnis native HTTPS.  On Windows I use Microsoft's  XMLHTTP.6.0 automation
object (or older depending on the OS Version we are running on) and on Mac,
Kelly's TCPTalk.  Here is the POST code.  Have similar for GET and DELETE.
Seems very reliable and works in Omnis 8.0 and 9.0 (Alpha).

This method can probably be reduced to 1/3 of its current size if you take
out some of the fluff.  Checking for older OS's, making the response text
more human readable, etc.

If suUseTCPTalk|(sys(6)='X')
;  Use TCPTalk for Macs
Calculate pvURL as replaceall(pvURL,' ','%20')     ;; Encode Spaces
,pvResponse) Returns responseCode
;  Create the IE Object
Do ie6.$createobject()
If ie6.$isavailable
Set reference httpobj to ie6.$ref
Do ie5.$createobject()
If ie5.$isavailable
Set reference httpobj to ie5.$ref
Do ie4.$createobject()
If ie4.$isavailable
Set reference httpobj to ie4.$ref
Do ie3.$createobject()
If ie3.$isavailable
Set reference httpobj to ie3.$ref
Quit method con(jst(statusCode,'-3NP0'),' ',statusDesc)
End If
End If
End If
End If
Do httpobj.$open('POST',pvURL,kFalse)
;  Make Headers
Begin reversible block
Set current list pvHeaderList
End reversible block
For each line in list from 1 to #LN step 1
Do httpobj.$setrequestheader(pvHeaderList.c1,pvHeaderList.c2)
End For
Do httpobj.$setrequestheader('User-Agent','ClienTrax')
Do httpobj.$setrequestheader('Content-Length',len(pvXML))
Do httpobj.$setrequestheader('Host',pvURL)
If pvUserID<>''&pvPassword<>''
;  Set Server Authentication
Calculate lvAuth as con(pvUserID,':',pvPassword)
UUEncode (lvAuth,lvEncodedAuth) 
Do httpobj.$setrequestheader('Authorization',con('Basic ',lvEncodedAuth))
End If
;  Send Request
Do httpobj.$send(pvXML)
;  Get Response
;  Calculate #S1 as con('ResponseBody=',httpobj.$responsebody,'
','ResponseStatusText=',httpobj.$responsestatustext,'  ',)
Calculate pvResponse as httpobj.$responsetext
Calculate statusDesc as httpobj.$statustext
Calculate statusCode as httpobj.$status
If 1=2
Calculate #S1 as httpobj.$getallresponseheaders
End If
Do httpobj.$release()
;  Replace Control Codes for readability in Omnis.
If 1=1
Do replaceall(pvResponse,chr(10),' ') Returns pvResponse
Do replaceall(pvResponse,'<','<') Returns pvResponse
Do replaceall(pvResponse,'>','>') Returns pvResponse
Do replaceall(pvResponse,'&','&') Returns pvResponse
Do replaceall(pvResponse,'><',con('>',chr(13),'<')) Returns pvResponse
Do replaceall(pvResponse,'> <',con('>',chr(13),'<')) Returns pvResponse
End If
Calculate responseCode as con(jst(statusCode,'-3NP0'),' ',statusDesc)
End If
If 1=2
Do method ------SaveLast (pvXML)
End If
Quit method responseCode

Michael Mantkowski
ClienTrax Software

-----Original Message-----
From: omnisdev-en <omnisdev-en-bounces at> On Behalf Of
Rudolf Bargholz
Sent: Monday, July 2, 2018 9:20 AM
To: OmnisDev List - English <omnisdev-en at>
Subject: AW: SOAP web services

Hi Michael,

Do the native HTTP POST methods allow you to use HTTPS in newer versions of
Omnis Studio? The HTTP xcomp allows us to use https in the $url parameter
and not just http.
Is an "HTTP Post" a blocking method call in a Studio web service, for
example? Or will it yield to other threads? Do you know? We use an old
version of Studio, so I am not up to date on what is possible in newer
Studio versions.

Another idiot-proof method is using cURL to send a request to a server,
write the response to file, and parse the file. But this would probably fail
in the context of a Studio web service. The advantage here is you can test
the complete request/response cycle outside of Omnis Studio, and then
integrate the finished process in Studio. cURL allows a plethora of
authentication/security options that might not be available in Omnis Studio,
and works on all platforms, even Windows. What we have also implemented is
calling services from the Task Scheduler, and then writing the response in a
folder, and then polling the folder from Omnis for the response file. It all
depends on the requirements for the SOAP call.


Rudolf Bargholz

-----Ursprüngliche Nachricht-----
Von: omnisdev-en [mailto:omnisdev-en-bounces at] Im Auftrag
von Michael Mantkowski
Gesendet: Montag, 2. Juli 2018 14:20
An: 'OmnisDev List - English' <omnisdev-en at>
Betreff: RE: SOAP web services

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 ''
;; Beta
    Calculate lvURL as ''
;; 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
    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
Do method ----setHeaderList (cvHeaderList,kFalse,'SOAPAction',lvAction)
Do method ----setHeaderList (cvHeaderList,kFalse,'Content-Type','text/xml;

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
HNS'),'.xml'),lvResponseText) Returns #1
    End If
    Quit method 1
End If
;  Error
Calculate lvXML as con('URL:
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

-----Original Message-----
From: omnisdev-en <omnisdev-en-bounces at> On Behalf Of
Rudolf Bargholz
Sent: Monday, July 2, 2018 7:56 AM
To: OmnisDev List - English <omnisdev-en at>
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

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


Rudolf Bargholz

Begin text block
;  Header
Text: <soapenv:Envelope
Text: <soapenv:Header/>
Text: <soapenv:Body>
Text: <olt:[iWsMethod]>

;  Body

;  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

;  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
If len(iSoapSessionList.SoapAction)>0
;  SOAPAction: ""
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
;  Calculate lAuthorizationStringBase64 as
OXML.$base64encode(lAuthorizationString)     ;; @MOD:rb:2013-10-10: Bug in
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

;  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
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.
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
Do lXmlDomObj.$getelementsbytagname('return',lErrorText) Returns lx_nl If

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

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] Im Auftrag
von Andrea Zen
Gesendet: Montag, 2. Juli 2018 09:34
An: OmnisDev List - English <omnisdev-en at>
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 Start a new
message -> mailto:omnisdev-en at
Manage your list subscriptions at Start a new
message -> mailto:omnisdev-en at 

Manage your list subscriptions at Start a new
message -> mailto:omnisdev-en at
Manage your list subscriptions at Start a new
message -> mailto:omnisdev-en at 

More information about the omnisdev-en mailing list