With the help from WRC we converted the OBX stream to a GlobalCharacter Stream. See below as an example.

- Log in to post comments
With the help from WRC we converted the OBX stream to a GlobalCharacter Stream. See below as an example.

Without Proxy...
0 +«npiregistry.cms.hhs.gov:443
With Proxy
0 3Â %<WRITE>zSend+179^%Net.HttpRequest.1
I think I am definately being blocked along the process somewhere. I tried the above commands as Sean mentioned with a proxy and without one, but I keep running into issues.
USER>set req=##class(%Net.HttpRequest).%New()
USER>set req.SSLConfiguration="npiregistry"
USER>set req.Server="npiregistry.cms.hhs.gov"
USER>set req.Https=1
USER>set req.Port=443
USER>set sc=req.Get("/api?city=baltimore&postal_code=212")
USER>write req.HttpResponse.Data.Read(300000)
WRITE req.HttpResponse.Data.Read(300000)
^
<INVALID OREF>
USER>set req=##class(%Net.HttpRequest).%New()
USER>set req.ProxyServer="10.127.20.41"
USER>set req.ProxyPort="8080"
USER>set req.SSLConfiguration="npiregistry"
USER>set req.Server="npiregistry.cms.hhs.gov"
USER>set req.Https=1
USER>set req.Port=443
USER>set sc=req.Get("/api?city=baltimore&postall_code=212")
USER>write req.HttpResponse.Data.Read(300000)
WRITE req.HttpResponse.Data.Read(300000)
^
<INVALID OREF>
Does this only work on certain Ensemble versions? I tried it on 2015.2.2 and was getting SYNTAX errors.
Yes I created a blank SSL/TLS confirguration called npireigstry just like you mentioned above.

I wrote out sc after executing the GET and got the following...
write sc0 [Š%<WRITE>zSend+199^%Net.HttpRequest.1 'USER #$^zSend+199^%Net.HttpRequest.1 +1 $^zGet+1^%Net.HttpRequest.1 +1X^@ +1$D^zExecute+15^%Studio.General.1 +1X^@ +1 D^runMtdLow+22^%SYS.BINDSRV +1 D^popFrame+199^%SYS.BINDSRV +1!D^ServerLoop+23^%SYS.BINDSRV +2!D^SuperConnect+34^%SYS.DBSRV +1"D^SuperServer+112^%SYS.SERVER +1
Any Idea on what this error could be?
Sean,
I tried running through your example above. When I got to set results={} ,I got the following error. Does this mean I could not get a connection outside my firewall at the Hospital?
USER>set req=##class(%Net.HttpRequest).%New()
USER>set req.SSLConfiguration="npiregistry"
USER>set sc=req.Get("https://npiregistry.cms.hhs.gov/api?city=balimore&postal_code=212")
USER>set results={}.%FromJSON(req.HttpResponse.Data)
<THROW>%FromJSON+37^%Library.DynamicAbstractObject.1 *%Exception.General Premature end of data 12 Line 1 Offset 0
USER 2e1>write results.%Get("result_count")
WRITE results.%Get("result_count")
^
<UNDEFINED>^%Library.DynamicAbstractObject.1 *results
USER 2e1>set results={}.%FromJSON(req.HttpResponse.Data)
<THROW>%FromJSON+37^%Library.DynamicAbstractObject.1 *%Exception.General Premature end of data 12 Line 1 Offset 0
Thanks
Scott
Thanks.
Yes I would think the easiest way would be to create a record mapper structure, then use the DTL to map your HL7 fields to where they need to be, then send it to a EnsLib.RecordMap.Operation.FileOperation.
Record Mapper

DTL

Eduard, where can I see the code for ZSTART AND ZSTOP?
Thanks
Scott
Yes the JDBC Gateways within the Production do stop and start when Cache' is going down and coming back up, but I am talking at the %SYS level,

Without the JDBC Gateway Server running a lot of the JDBC Gateway's (Services) start failing in the production which causes us issues.
ZSTART and ZSTOP are kind of vague, how does that fit into ccontrol start and ccontrol stop. Is there any setting where this can be set to automatic?
Scott
Just following up, can anyone answer my question above?
The majority of my Ancillary billing files in HL7 are batch. In the structure I have just made FHS, BHS,FTS,FHS all optional. In my DTL, I am only processing those messages that truly begin with a MSH segment.
In a lot of places I use...
ConvertDateTime (
..ConvertDateTime(source.{Z01(1):DateOfBirth},"%Y%m%d","%q(1)")
%q(1) is the format.
We had a consultant write this for us as well...
ClassMethod FormatStringToSQLDate(InDate As %String) As %String [ Final ]
{
If InDate=""
{
set OutDate="1900-01-01 00:00:00"
}
else
{
set DateLength=..Length(InDate)
if (DateLength > 7) && (DateLength < 15)
{
set YYYY=..SubString(InDate,1,4)
set mm=..SubString(InDate,5,6)
set dd=..SubString(InDate,7,8)
set OutDate=YYYY_"-"_mm_"-"_dd
if DateLength=8
{
set OutDate=OutDate_" 00:00:00"
}
if DateLength=10
{
set HH=..SubString(InDate,9,10)
set OutDate=OutDate_" "_HH_":00:00"
}
if DateLength=12
{
set HH=..SubString(InDate,9,10)
set MM=..SubString(InDate,11,12)
set OutDate=OutDate_" "_HH_":"_MM_":00"
}
if DateLength=14
{
set HH=..SubString(InDate,9,10)
set MM=..SubString(InDate,11,12)
set SS=..SubString(InDate,13,14)
set OutDate=OutDate_" "_HH_":"_MM_":"_SS
}
}
else
{
set OutDate="1900-01-01 00:00:00"
}
}
Quit OutDate
}
}
We've have done something similar but wrote a function to do the looping... This example loops through a given segment and field and looks that value up against a lookup table. This could be modified for your use. This is the only way I know to do the looping within the BusinessRule.
{
#dim tSeg as EnsLib.HL7.Segment
set tSegCount = pHL7Msg.SegCountGet()
set i = 1
Set tFound = 0
//get new values
set tval=""
while ((i <= tSegCount) && (tval="")) {
set tSeg = pHL7Msg.GetSegmentAt(i)
if (tSeg.Name = pSegment) {
set tID = tSeg.GetValueAt(pField)
set tval= ..Lookup(pLookupTable, tID)
}
set i = i + 1
}
if (tval '= "")
{
Q 1
}
quit 0
}
I am not familiar with that function.
This is how I am looking up a repeatable segment against a lookup table.
ClassMethod GroupIDExists(pHL7Msg As EnsLib.HL7.Message, pSegment As %String, pField As %String, pLookupTable As %String) As %Boolean
{
#dim tSeg as EnsLib.HL7.Segment
set tSegCount = pHL7Msg.SegCountGet()
set i = 1
Set tFound = 0
//get new values
set tval=""
while ((i <= tSegCount) && (tval="")) {
set tSeg = pHL7Msg.GetSegmentAt(i)
if (tSeg.Name = pSegment) {
set tID = tSeg.GetValueAt(pField)
set tval= ..Lookup(pLookupTable, tID)
}
set i = i + 1
}
if (tval '= "")
{
Q 1
}
quit 0
}
Not sure how you would do that with XECUTE
This is not in a translation. We want to write a function to loop through a repeating segment and compare it to a string value within a Routing Rule. I've done this before as a lookup against a table but not compare strings before.
Are you connecting from a Windows Client to a Windows LDAP server? Or is it an Unix Client to a Windows LDAP server? Its a matter of using Binds vs SimpleBinds. I am wondering if that is causing your error. I use Delegated Authentication through LDAP using a TLS certificate so my setup maybe more complicated than yours.
Was this ever pushed forward as true development? I know you have been working on it sometime, and wanted to see if I could take a look at it for my organization.
Thanks
Scott
I got jTDS working through using Squirrel SQL Client, I am just now trying to transpose that over to Ensemble to see if I can get it to work.
Maybe I didn't describe this right. I am trying to go from No Authentication to a Windows Authentication account. Has anyone done this? if so can you share your part of your URL to see what I am possibly missing.
Thanks
Scott
Yes I was. That would explain the syntax issue. I have verified that the SimpleBinds without StartTLSs works fine. I have added some additional print statements to see where the issue might lie. The code gets past the Init, and SetOption, but then dies on the StartTLSs.
SetOption=Success
-11,ldap_StartTLSs(Certificate) - Connect error
I went ahead and opened a ticket up with WRC to see if they could help. Thanks everyone.
I am still struggling to get this to work. If I go through %SYS and manually try to start a TLS connection in AIX to my LDAP server I am getting...
Does the certificate need to be in a certain directory for this to work as the examples suggested " /usr/share/ssl/certs/...."?
I was able to track down the error to
i Status'=$$$LDAPSUCCESS{
s Status=Status_",ldap_setoption(Certificate) - "_##class(%SYS.LDAP).Err2String(Status)
w Status,!
g Error
}
I was able to track down the error to
i Status'=$$$LDAPSUCCESS{
s Status=Status_",ldap_setoption(Certificate) - "_##class(%SYS.LDAP).Err2String(Status)
w Status,!
g Error
}
That's the part I am unsure of, because it is not logging to the Audit Database. How can I run this and put breakpoints in to verify where it might be getting stuck?
Thanks.
I am now to the point where I am getting Error message: LDAP error: 0 - Success. How can a Success be a Failure?
ZAUTHENTICATE(ServiceName,Namespace,Username,Password,Credentials,Properties) PUBLIC {
#include %occErrors
#include %sySecurity
#include %sySite
#include %syLDAP
#define LDAPServer $Get(^OSUMCLDAP("Server"))
#define WindowsLDAPServer 1
#define WindowsCacheClient 0
#define UseSecureConnection 1
#define UnixCertificateFile $Get(^OSUMCLDAP("LDAPKey"))_"certnew.pem"
#define WindowsBaseDN "dc="_$Get(^OSUMCLDAP("Domain"))_",dc=edu"
#define WindowsFilter "sAMAccountname"
#define WindowsAttributeList $lb("displayName","department","mail")
s $zt="Error"
s Status = 0
i Password="" {
s Status= $SYSTEM.Status.Error($$$InvalidUsernameOrPassword)
g Error
}
i $$$WindowsLDAPServer{
s AdminDN=$Get(^OSUMCLDAP("User"))
s AdminPW=$Get(^OSUMCLDAP("Pass"))
}
#;The following line sets up the internal LDAP structures.
i $$$ISWINDOWS,$$$UseSecureConnection {
s LD=##Class(%SYS.LDAP).Init($$$LDAPServer,636)
} else {
s LD=##Class(%SYS.LDAP).Init($$$LDAPServer)
}
i LD=0 {
s Status=##Class(%SYS.LDAP).GetLastError()
s Status="Init error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
g Error
}
s Status=##Class(%SYS.LDAP).SetOption(LD,$$$LDAPOPTXTLSCACERTFILE,$$$UnixCertificateFile)
i Status'=$$$LDAPSUCCESS{
s Status ="SetOption error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
g Error
}
s Status=##class(%SYS.LDAP).StartTLSs(LD)
i Status'=$$$LDAPSUCCESS{
s Status=Status_",ldap_setoption(Certificate) - "_##class(%SYS.LDAP).Err2String(Status)
g Error
}
s Status=##Class(%SYS.LDAP).SimpleBinds(LD,AdminDN,AdminPW)
i Status'=$$$LDAPSUCCESS
{
s Status = Status_", ldap_Simple_Bind(AdminDN) - "_##Class(%SYS.LDAP).Err2String(Status)
#;w !,Status
g Error
}
i $$$WindowsLDAPServer {
s Filter=$$$WindowsFilter_"="_Username
}
i $$$WindowsLDAPServer {
s AttributeList=$$$WindowsAttributeList
}
i $$$WindowsLDAPServer {
s BaseDN=$$$WindowsBaseDN
}
s SearchScope=$$$LDAPSCOPESUBTREE
s Timeout=30
s SizeLimit=1
s Status=##Class(%SYS.LDAP).SearchExts(LD,BaseDN,SearchScope,Filter,AttributeList,0,"","",Timeout,"",.SearchResult)
i Status'=$$$LDAPSUCCESS {
i Status=$$$XLDAPFILTERERROR {
s Status="1,User "_Username_" does not exist"
w !,Status
} else {
s Status=Status_",ldap_Search_Ext - "_##Class(%SYS.LDAP).Err2String(Status)
}
g Error
}
s NumEntries=##Class(%SYS.LDAP).CountEntries(LD,SearchResult)
i NumEntries=-1 {
s Status=##Class(%SYS.LDAP).GetError(LD)
s Status=Status_",ldap_Count_Entries - "_##Class(%SYS.LDAP).Err2String(Status)
g Error
}
i NumEntries=0 {
s Status="1,User "_Username_" does not exist"
g Error
}
i NumEntries>1 {
s Status="1,LDAP Filter is not unique"
g Error
}
s CurrentEntry=##Class(%SYS.LDAP).FirstEntry(LD,SearchResult)
i CurrentEntry=0 {
s Status=##Class(%SYS.LDAP).GetError(LD)
s Status=Status_",ldap_FirstEntry - "_##Class(%SYS.LDAP).Err2String(Status)
g Error
}
s DN=##Class(%SYS.LDAP).GetDN(LD,CurrentEntry)
i Password="" {
s Status="1,ldap_Simple_Bind("_DN_") - password cannot be null"
g Error
}
s Status=##Class(%SYS.LDAP).SimpleBinds(LD,DN,Password)
i Status'=$$$LDAPSUCCESS {
s Status=Status_",ldap_Simple_Bind("_DN_") - "_##Class(%SYS.LDAP).Err2String(Status)
g Error
}
s Attribute=##Class(%SYS.LDAP).FirstAttribute(LD,CurrentEntry,.Ptr)
while (Attribute'="") {
s Values=##Class(%SYS.LDAP).GetValuesLen(LD,CurrentEntry,Attribute)
#;Values:"_Values
s Properties("Attributes",Attribute)=Values
s Attribute=##Class(%SYS.LDAP).NextAttribute(LD,CurrentEntry,.Ptr)
}
s Properties("Username")=Username
s Properties("FullName")=$li(Properties("Attributes","displayName"))
k Properties("Attributes","displayName")
s Properties("Comment")=$li(Properties("Attributes","department"))
k Properties("Attributes","department")
s Properties("EmailAddress")=$li(Properties("Attributes","mail"))
k Properties("Attributes","mail")
i $d(SearchResult) d ##Class(%SYS.LDAP).MsgFree(SearchResult)
s GroupFilter="(&(objectClass=group)(member:1.2.840.113556.1.4.1941:="_DN_"))"
s GroupAttributes=""
s Status=##Class(%SYS.LDAP).SearchExts(LD,BaseDN,$$$LDAPSCOPESUBTREE,GroupFilter,GroupAttributes,0,"","",10,0,.GroupSearchResult)
#;GroupSearch Status: "_Status
i Status'=$$$LDAPSUCCESS {
w !,"SearchExts error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
g Error
}
s GroupNumEntries=##Class(%SYS.LDAP).CountEntries(LD,GroupSearchResult)
i GroupNumEntries=-1 {
s Status=##Class(%SYS.LDAP).GetError(LD)
s Status=##Class(%SYS.LDAP).Err2String(Status)
g Error
}
w !
i GroupNumEntries=0 {
w !,"No nested groups for "_Username_" found"
g Done
}
i GroupNumEntries>0 {
}
s GroupCurrentEntry=##Class(%SYS.LDAP).FirstEntry(LD,GroupSearchResult)
i GroupCurrentEntry=0 {
s Status=##Class(%SYS.LDAP).GetError(LD)
w !,"FirstEntry error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
g Error
}
s Groups=""
While (GroupCurrentEntry'=0) {
s GroupDN=##Class(%SYS.LDAP).GetDN(LD,GroupCurrentEntry)
i GroupDN="" {
s Status=##Class(%SYS.LDAP).GetError(LD)
w !,"GetDN Group error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
g Error
}
s CN=$p(GroupDN,",",1)
s AD=$p(CN,"=",2)
s AD=$zcvt(AD,"L")
s exists=''$d(^|"%SYS"|SYS("Security","RolesD",AD))
i exists{
s Properties("Roles") = AD
}
s GroupCurrentEntry=##Class(%SYS.LDAP).NextEntry(LD,GroupCurrentEntry)
}
Done
i +$d(LD) d ##Class(%SYS.LDAP).UnBinds(LD)
#;w !,"SystemOK "_$SYSTEM.Status.OK()
q $SYSTEM.Status.OK()
Error s $zt=""
i $d(SearchResult) d ##Class(%SYS.LDAP).MsgFree(SearchResult)
i $d(GroupSearchResult) d ##Class(%SYS.LDAP).MsgFree(GroupSearchResult)
i +$d(LD) s Status=##class(%SYS.LDAP).UnBinds(LD)
i $ze'=""{
q $SYSTEM.Status.Error($$$CacheError,$ze)
} else{
q $SYSTEM.Status.Error($$$GeneralError,"LDAP error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status))
}
}
Haven't tried that. Wasn't sure if it was going to make me do the Authentication before I connect to the external database, or while connecting to the external database.
Maybe I am making a mountain out of a mole hill.
After many TRACE statements found I was missing (1) after the FT1 in my syntax. So it should be... request.GetValueAt("FT1(1):16.4.2")
When I look at the message in Message viewer it is showing 06CL as FT1:16.4.2
What type of database is the stored procedure on? If it is Microsoft have you tried VARCHAR(8000)? MAX does not exist in some SQL languages so sometime you have to limit it down to the number of bytes I believe. Though I might be wrong.