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

In a lot of places I use...

ConvertDateTime (val,in,out,file)

 

..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.

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 = 1
            Set tFound = 0
            //get new values
            set tval=""
            while ((<= tSegCount) && (tval="")) {
                         
                        set tSeg = pHL7Msg.GetSegmentAt(i)
                        if (tSeg.Name = pSegment) {
                                    set tID = tSeg.GetValueAt(pField)
                                    set tval= ..Lookup(pLookupTable, tID)
                                                            
                        }
                        set = + 1
            }
            if (tval '= "")
            {
                        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 = 1
            Set tFound = 0
            //get new values
            set tval=""
            while ((<= tSegCount) && (tval="")) {
                         
                        set tSeg = pHL7Msg.GetSegmentAt(i)
                        if (tSeg.Name = pSegment) {
                                    set tID = tSeg.GetValueAt(pField)
                                    set tval= ..Lookup(pLookupTable, tID)
                                                            
                        }
                        set = + 1
            }
            if (tval '= "")
            {
                        1
            }
            quit 0
}

Not sure how you would do that with XECUTE

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.

LD=1
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...

s Status=##Class(%SYS.LDAP).SetOption(LD,$$$LDAPOPTXTLSCACERTFILE,"/ensemble/TestClin/mgr/LDAPKeyStore/OSUWMC_CA.pem") - Error <SYNTAX>

Does the certificate need to be in a certain directory for this to work as the examples suggested " /usr/share/ssl/certs/...."?

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")
$zt="Error"
 
 Status = 0

 Password="" {
Status= $SYSTEM.Status.Error($$$InvalidUsernameOrPassword)
Error
 }
 $$$WindowsLDAPServer{
AdminDN=$Get(^OSUMCLDAP("User"))
AdminPW=$Get(^OSUMCLDAP("Pass"))
 }

 #;The following line sets up the internal LDAP structures.
 $$$ISWINDOWS,$$$UseSecureConnection {
LD=##Class(%SYS.LDAP).Init($$$LDAPServer,636)
 else {
LD=##Class(%SYS.LDAP).Init($$$LDAPServer)
 }
 LD=0 {
Status=##Class(%SYS.LDAP).GetLastError()
Status="Init error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 }
 Status=##Class(%SYS.LDAP).SetOption(LD,$$$LDAPOPTXTLSCACERTFILE,$$$UnixCertificateFile)
 Status'=$$$LDAPSUCCESS{
Status ="SetOption error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 
 Status=##class(%SYS.LDAP).StartTLSs(LD)
 Status'=$$$LDAPSUCCESS{
Status=Status_",ldap_setoption(Certificate) - "_##class(%SYS.LDAP).Err2String(Status)
Error
  }
 
 Status=##Class(%SYS.LDAP).SimpleBinds(LD,AdminDN,AdminPW)
 Status'=$$$LDAPSUCCESS 
  {
Status = Status_", ldap_Simple_Bind(AdminDN) - "_##Class(%SYS.LDAP).Err2String(Status)
#;w !,Status
Error
  }

 $$$WindowsLDAPServer {
Filter=$$$WindowsFilter_"="_Username
 }
 $$$WindowsLDAPServer {
AttributeList=$$$WindowsAttributeList

 
 $$$WindowsLDAPServer {
BaseDN=$$$WindowsBaseDN

 
 
 SearchScope=$$$LDAPSCOPESUBTREE
 Timeout=30
 
 SizeLimit=1
 
 Status=##Class(%SYS.LDAP).SearchExts(LD,BaseDN,SearchScope,Filter,AttributeList,0,"","",Timeout,"",.SearchResult)
 Status'=$$$LDAPSUCCESS {

Status=$$$XLDAPFILTERERROR {
Status="1,User "_Username_" does not exist"
!,Status
else {
Status=Status_",ldap_Search_Ext - "_##Class(%SYS.LDAP).Err2String(Status)
}
Error
 }

 NumEntries=##Class(%SYS.LDAP).CountEntries(LD,SearchResult)
 NumEntries=-1 {
 Status=##Class(%SYS.LDAP).GetError(LD)
 Status=Status_",ldap_Count_Entries - "_##Class(%SYS.LDAP).Err2String(Status)
 Error
 }
NumEntries=0 {
Status="1,User "_Username_" does not exist"
  Error
 }
 
 NumEntries>1 {
Status="1,LDAP Filter is not unique"
  Error
 }
 
 CurrentEntry=##Class(%SYS.LDAP).FirstEntry(LD,SearchResult)
 CurrentEntry=0 {
Status=##Class(%SYS.LDAP).GetError(LD)
Status=Status_",ldap_FirstEntry - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 }
 
 DN=##Class(%SYS.LDAP).GetDN(LD,CurrentEntry
 Password="" {
Status="1,ldap_Simple_Bind("_DN_") - password cannot be null"
Error
 }
 
 Status=##Class(%SYS.LDAP).SimpleBinds(LD,DN,Password)
 Status'=$$$LDAPSUCCESS {
Status=Status_",ldap_Simple_Bind("_DN_") - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 }

 Attribute=##Class(%SYS.LDAP).FirstAttribute(LD,CurrentEntry,.Ptr)

 while (Attribute'="") {
   Values=##Class(%SYS.LDAP).GetValuesLen(LD,CurrentEntry,Attribute)
   #;Values:"_Values
   Properties("Attributes",Attribute)=Values
  Attribute=##Class(%SYS.LDAP).NextAttribute(LD,CurrentEntry,.Ptr)
 }
 Properties("Username")=Username
 Properties("FullName")=$li(Properties("Attributes","displayName"))
 Properties("Attributes","displayName")
 Properties("Comment")=$li(Properties("Attributes","department"))
 Properties("Attributes","department")
 Properties("EmailAddress")=$li(Properties("Attributes","mail"))
 Properties("Attributes","mail")
 
 $d(SearchResult) ##Class(%SYS.LDAP).MsgFree(SearchResult)
 
 GroupFilter="(&(objectClass=group)(member:1.2.840.113556.1.4.1941:="_DN_"))"
 GroupAttributes=""
 Status=##Class(%SYS.LDAP).SearchExts(LD,BaseDN,$$$LDAPSCOPESUBTREE,GroupFilter,GroupAttributes,0,"","",10,0,.GroupSearchResult)
 #;GroupSearch Status: "_Status
 Status'=$$$LDAPSUCCESS {
!,"SearchExts error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 }
 GroupNumEntries=##Class(%SYS.LDAP).CountEntries(LD,GroupSearchResult)
 GroupNumEntries=-1 {
Status=##Class(%SYS.LDAP).GetError(LD)
Status=##Class(%SYS.LDAP).Err2String(Status)
Error
 }
!
 GroupNumEntries=0 {
!,"No nested groups for "_Username_" found"
Done
 }
 GroupNumEntries>0 {
 }
 
 GroupCurrentEntry=##Class(%SYS.LDAP).FirstEntry(LD,GroupSearchResult)
 GroupCurrentEntry=0 {
Status=##Class(%SYS.LDAP).GetError(LD)
!,"FirstEntry error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
Error
 }
 Groups=""
 While (GroupCurrentEntry'=0) {
GroupDN=##Class(%SYS.LDAP).GetDN(LD,GroupCurrentEntry)
GroupDN="" {
Status=##Class(%SYS.LDAP).GetError(LD)
!,"GetDN Group error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status)
Error
}
CN=$p(GroupDN,",",1)
AD=$p(CN,"=",2)
AD=$zcvt(AD,"L")
exists=''$d(^|"%SYS"|SYS("Security","RolesD",AD))
exists{
Properties("Roles") = AD

}


  GroupCurrentEntry=##Class(%SYS.LDAP).NextEntry(LD,GroupCurrentEntry)
 }
Done
+$d(LD) ##Class(%SYS.LDAP).UnBinds(LD)
 #;w !,"SystemOK "_$SYSTEM.Status.OK()
 $SYSTEM.Status.OK()
Error $zt=""
 $d(SearchResult) ##Class(%SYS.LDAP).MsgFree(SearchResult)
 $d(GroupSearchResult) ##Class(%SYS.LDAP).MsgFree(GroupSearchResult)
 +$d(LD) Status=##class(%SYS.LDAP).UnBinds(LD)
 $ze'=""{
 $SYSTEM.Status.Error($$$CacheError,$ze)
 else{  
  $SYSTEM.Status.Error($$$GeneralError,"LDAP error: "_Status_" - "_##Class(%SYS.LDAP).Err2String(Status))
 }
}