go to post Nigel Salm · Jul 24, 2020 Hi I have an example of exactly what you are trying to do. It makes use of the IRIS 2019.1 9or later) FHIR Bundle resource, it handles stateid, paging and so on. I have a meeting I have to attend online very shortly and then I will put the code together and update this thread. Nigel
go to post Nigel Salm · Jul 21, 2020 Hi What are your settings for charset, content type and content encoding? I would expect to see something like this: ContentEncoding = "HL7-ER7" ContentCharset = "UTF-8" ContentType = "application/hl7-v2" The most common type of framing is MLLP. If you are acting as an HL7 server tand you don't know what the client framin is then set framing to flexible. that way ensemble will try and detect the framing based on the properties listed above and by looking for tell tale characters (segment terminators) such as LF $c(10) or CR,LF $c(13,10). Depending on the properties listed above you may see the terminator represented as "/r". If you are the HL7 client then you can get away with framing = none provided both you and the 3rd party server are consistent on the content type, charset and encoding. I hope that gives you some ideas of what to look out for and the questions you need to ask the 3rd party application you are trying to communicate with. Yours Nigel
go to post Nigel Salm · Jul 20, 2020 Hi Carl Ok, thank you for the additional information. Unfortunately I don' have an answer for the issue you are facing. I suggest you open an issue with the WRC. Yours Nigel
go to post Nigel Salm · Jul 18, 2020 Hi I am wondering if this is a user security level issue. As you know you need Windows/Unix Administrator rights to install Cache/Ensemble/IRIS. The same is true if you want to run any of the executables in the 'bin' directory such as cstart cachesystray and so on. I am not a UNIX expert and so I can only speak from my Windows experience but assuming this is windows close the Cache/Ensemble/IRIS systeray icon and then from the 'bin' directory fine th csystray.exe, right click and slect 'run as administrator', then see if you can start or shut down your instance. If that fails and all other suggestions from the Developer community uninstall C/E/IRIS and reinstall it making sure you run the installation as 'Administrator' The final suggection is check your cache.key or iris.key and make sure your license is still valid. Yours Nigel
go to post Nigel Salm · Jul 15, 2020 sorry, let me correct the parameter declaration as method ABC(myContext as %RegisteredObject) as %Status ... Nigel
go to post Nigel Salm · Jul 15, 2020 Hi Can you upload the class definition of the table that contains the data as well as the routines that were generated by the sql compiler i.e. the classes and routines for *.SMTKTUAT.*.* (.cls, *.int) Have you tried accessing the data through the Management Portal->Stystem Explorer->SQL->Execute Query? Have you tried setting up an ODBC DSN and then accessing the table from within say Excel? If you set up a Windows ODBC DSN you can turn on logging for the DSN To resolve this issue you need to isolate whether the issue lies within the code generated by IRIS for the sql statement, or whether it is the ODBC/JDBC connection functionality. Have you written a simple class method using %Library.ResultSet as in classmethod TestQuery() as %Status { set tSC=$$$OK try { set rs=##class(%ResultSet)).%New("%DynamicQuery:SQL") set tSC=rs.Prepare("select col1, col2, ...., colN from Table where ....") if 'tSC quit set tSC=rs.Execute() if 'tSC quit while rs.Next(.tSC) { if 'tSC quit write !,rs.Data("Col1")," ",rs.Data("Col2")," ", ...., rs.Data("ColN") } } catch ex {set tSC=ex.AsStatus()} if 'tSC write !,$system.Status.GetErrorText(tsc) quit tSC } Nigel
go to post Nigel Salm · Jul 7, 2020 Hi Bear in mind that when you are working with DTL's when you invoke the Transform() method there is a third parameter called aux. The aux object can be an instance of any class you design and can contain any properties you desire. These are typically values that you want to use in the DTL that are not part of your request object. When you call the DTL you create a new instance of your aux class and then when you invoke the DTL Transform you can write the following code: set tSC=##class({Your DTL}).Transform(request,.response, .aux) where aux is an instance of your custom aux class. This is true also of DTL's called from a BPL with one exception. If the DTL is invoked from a Business Rule then the Business rule creates an instance of a system defined aux object that contains information about which rule invoked the DTL and so on. I am busy trying to convert a Custom Code Business Process that will invoke a DTL and am still trying to get my head around what variables/objects are available in the BPL (Context) and the DTL. If you resolve how to create a BPL using the context object and then invoke a DTL into which you can pass data other than the request and response message I would be interested to know how if you have success and how you managed to get it to work. Yours Nigel
go to post Nigel Salm · Jul 5, 2020 Hi Here is an example of a HTTP Operation POSTing HL7 messages. this HTTP request uses HTTPS and a Proxy Server. The lines I have highlighted in Yellow will be different in your case as you are sending JSON. Not clear if you are using FHIR. However your ContentType will most likely be application/json or application/json+fhir set tSC=$$$OK,pResponse="" try { set message=pRequest.OutputToString(,,.tSC) if 'tSC quit set tResponse = ##class(%Net.HttpResponse).%New(),tResponse.ContentType="application/hl7-v2" if '$IsObject(..HTTPRequest) { set pHttpRequest=##class(%Net.HttpRequest).%New() set pHttpRequest.Server=..Adapter.HTTPServer set pHttpRequest.Port=..Adapter.HTTPPort set pHttpRequest.ProxyServer=..Adapter.ProxyServer set pHttpRequest.ProxyPort=..Adapter.ProxyPort set pHttpRequest.ProxyTunnel=..Adapter.ProxyHttpTunnel set pHttpRequest.ProxyHTTPS=1 set pHttpRequest.SSLConfiguration=..Adapter.SSLConfig set pHttpRequest.UserAgent="curl/7.29.0" set pHttpRequest.ContentEncoding="HL7-ER7" set pHttpRequest.ContentCharset="UTF-8" set pHttpRequest.ContentType="application/hl7-v2" set pHttpRequest.AcceptGzip=0 set pHttpRequest.WriteRawMode=0 set pHttpRequest.ReadRawMode=0 set pHttpRequest.OpenTimeout=..Adapter.ConnectTimeout set pHttpRequest.Timeout=..Adapter.ResponseTimeout set pHttpRequest.WriteTimeout=..Adapter.WriteTimeout set pHttpRequest.SocketTimeout=115 set ..HTTPRequest=pHttpRequest } set ..HTTPRequest.HttpResponse=tResponse do ..HTTPRequest.EntityBody.Write(message) set tSC=..HTTPRequest.Post(..Adapter.URL,0,1) if 'tSC { set sc=$$$DebugLog("HTTP Write","Error: "_$$$GetErrorText(tSC)) } else {do $$$DebugLog("HTTP Write","Post Sucessful)} set response=..HTTPRequest.HttpResponse $$$TRACE("HTTP Response Status: "_response.StatusCode) if response.StatusCode=200 { if $IsObject(response.Data) { set message="" while 'response.Data.AtEnd {set message=message_response.Data.Read(,.tSC) if 'tSC quit} set pResponse=##class(EnsLib.HL7.Message).ImportFromString(message,.tSC) if 'tSC $$$TRACE("An error occurred creating Respnse Message: "_$system.Status.GetErrorText(tSC)) } } else { set message="" if $IsObject(response.Data) {set message="" while 'response.Data.AtEnd {set message=message_response.Data.Read(,.tSC) if 'tSC quit}} set tSC=$$$ERROR(5001,"HTTP Response Status is "_response.StatusCode_" with Error Text: "_response.ReasonPhrase_" with Content: "_message) quit } } catch ex { set tSC=ex.AsStatus() } if 'tSC,'$IsObject(pResponse) { // Here I create a NACK HL7 message if I didn't get a valid response from the remote server. Possibly because the server is down or the //server has crashed. I have a DTL that takes the inbound HL7 request message and transforms it into an HL7 ACK message. I force the ACK // Code to "AE" and use the contents of tSC (error status) as the Error Message. Note I make use of the 3rd parameter in the Transform() // method that allows you to pass in an object containing any properties you want. This is a useful way of getting data into the DTL that // doesn't exist in either your sourse or target objects. set pResponse=##class(EnsLib.HL7.Message).%New(),aux=##class(HPRS.Transformations.CreateNACKDTL.AUX).%New() set aux.ACKCode="AE",aux.ACKMessage=$system.Status.GetErrorText(tSC) set sc=##class(HPRS.Transformations.CreateNACKDTL).Transform(pRequest,.pResponse,.aux) if 'sc $$$TRACE("Unable to Create NACK Response HL7 Message") } $$$TRACE("Outcome of HTTP Operation: "_$s(tSC:"Ok",1:"Error: "_$$$GetErrorText(tSC))) quit $$$OK Yours Nigel Salm
go to post Nigel Salm · Jan 22, 2020 Hi The short answer is yes, you are constrained by the 3.6Mb string size limit and bear in mind that if you are exposing that property to SQL and ODBC you are further constrained by the limitations within ODBC itself. I have been giving this whole concept a lot of thought recently. My context is slightly different as I am working in the context of FHIR and JSON and for example you can send in a patient's photo which in JSON has to be represented as a string of Base64Encoded Binary . In principal that photo could be of any size but when the JSON string is converted into a FHIR Patient Object the underlying datatype of the photo.data.value is ultimately derived from a class called %xsd.Base64Binary which is esentially a string and therefore has the size limitation. It doesn't really matter what my underlying persisted datatype is i.e. %GlobalBinaryStream because I am working with the IRIS FHIR Classes as intemediary object classes between my JSON and my underlying persisted classes I have to work with the constraint that the JSON Base64Binary content will fail if it's length exceeds the 3.6Mb (something I wish to address with ISC/WRC at some point). The alternative of course, to persisting larger data content of something link an image, is to have a url that points to the image location and can be retrieved from the image server for presentation purposes. So where I know that my images are not going to be that large I read in or write out the base64binary from/to my JSON message but where I know the image is larger such as an x-ray or histo image then that content lives on the appropriate image server as is retirieved when required for presentation purposes. Nigel Salm
go to post Nigel Salm · Jan 2, 2020 Hi Remember that not only messages contribute to the volume of ensemble generated data. If you are using $$$TRACE in your production then this will generate a lot of data in the Ensemble namespace . If you have lots of TRACE statements then this can generate a lot of data. There is a class method do ##class(Ens.Purge).PurgeEventLogsByDate({NumberOfDaysToRetainTraceData},.count) There are other methods in this class to purge other management data such as messages Trace information is stored in the global ^Ens.Util.LogD and ^Ens.Util.LogI Nige;
go to post Nigel Salm · Dec 20, 2019 My guess is that you need to specify Exception as a Status i.e.: Exceptuion.AsStatus() and then your code should read set pOutput=##class(MyResponse).%New() set sc=Exception.AsStatus() set pOutput.errorString=$system.GetErrorText(sc) but another thought: If your method quits with tSC (as a %Status) then presumably your method quits with quit tSC in which case instead of trowing tSC just quit your Try {} with quit tSC and in your catch write it as follows: catch Exception { set tSC=Exception .As Status() } set pOutput=##class(MyResponse).%New() set pOutput.errorString=$s(tSC:"",1:$system.Status.GetErrorText(tSC)) quit tSC
go to post Nigel Salm · Nov 17, 2019 Hi I certainly concur that you do not want to go changing names in any InterSystems Library or System Classes. To be quite honest in my experience export the classes or project that contain all of the classes you want to manipulate and then open that XML export file in NotePad ++ . Bear in mind that classnames, property names, method names, and storage definitions will all be modified and you should be certain that that is acceptable and desirable otherwise you will need to go through the painful task of working your way through the XML file instance by instance and confirm each replace. Also bear in mind that if your Class Export references other IRIS classes other than your own application classes then you need to be careful that you don't change an IRIS classname/property name etc... as you may well find that your system no longer works. Having done the search and replace I suggest that you create a blank database/namespace and import the modified xml file and check any error messages thrown up by the import process before attempting to import into your proper DEV/UAT database/namespace(s) Nigel
go to post Nigel Salm · Nov 17, 2019 Hi Follow this link to the InterSystems Documentation. It details many utilities that can be run from the Cache Terminal. Those that start with a '%' character can be run from any NameSpace. Those without will typically only run in the %SYS NameSpace https://cedocs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GSTU Bear in mind that many command line utilities have been encapsulated in the %SYS, %SYSTEM, %SQL, %Dictionary and other system Packages. Most of the functionality of the Management Portal is linked to underlying classes and most of them have Methods that can be called programmatically; for example creating resources, roles and users in the security module. Most database and Namespace functionality can be accessed through the %SYS and %SYSTEM packages If you are looking for specific functions that you would like (if they exist) please list them and I'll see if I can point you in the right direction Yours Nigel Salm
go to post Nigel Salm · Sep 29, 2019 Here is a solution I have knocked up that uses the functionality of the Ensemble File Adapter and the HL7 File Operation class Class User.ExampleHL7FileOperation Extends (Ens.BusinessOperation, EnsLib.HL7.Operation.FileOperation) [ Language = objectscript ]{ Parameter ADAPTER = "EnsLib.File.OutboundAdapter"; Property Adapter As EnsLib.File.OutboundAdapter; Parameter INVOCATION = "Queue"; Method WriteMessage(pRequest As EnsLib.HL7.Message, Output pResponse As EnsLib.HL7.Message) As %Status{ // Initialise your return status variable and a variable called file // I use $ztrap to trap code errors though TRY/CATCH would be the more modern approach set tSC=$$$OK,$ztrap="Error",file="" // Create your file name and append to the Adapter Attribute 'FilePath' // if working with UNIX change the next line of code accordingly if $e(..Adapter.FlePath,*)'="\" set ..Adapter.FilePath=..Adapter.FilePath_"\" set file=..Adapter.FilePath_"ZLOG_FILE_"_pRequest.GetValueAt("MSH::MessageType.MessageStructure",,tSC)_$tr($zdt($h,3),"-: ","")_".txt" if 'tSC quit tSC // You can use the appropriate method in the File Outbound Adapter though I have used the OPEN // command open file:("WNS"):0 else set tSC=$system.Status.Error(5001,"Cannot create File: "_file) goto End // Invoke the outputDocument method inherited from the class 'EnsLib.HL7.Operation.FileOperation' set tSC=..outputDocument(file,pRequest) if 'tSC goto EndEnd ; // Close the file if it exists if file'="" close file set pResponse=##class(EnsLib.HL7.Message).%New() // Populate the response HL7 message as you see fit. Either send back an HL7 ACK or NACK would be // the most appropriate quit tSCError ; set $ztrap="",tSC=$system.Status.Error($$$GeneralError,"Code Error: "_$ze) goto End} XData MessageMap { <MapItems> <MapItem MessageType="EnsLib.HL7.Message"> <Method>WriteMessage</Method> </MapItem> </MapItems> } } I have not trested the code but hopefully my coments will set you on the right path to this solution
go to post Nigel Salm · Sep 29, 2019 Many of the terminal based utilities use '^' <enter> to return to the previous field. In older versions of the Cache utilities it really depends on who the developer was who wrote the program as well as which area of the product the program was writtren for. There isn't necessarily consistancy between the developers or functionality of the programs. Most interactive utilities are now accessed through the %SYSTEM package which is accessed using the notation $system.... e.g. set status=$system.Status.Error(5001,"This is a general Error") Various configuration items can be accessed through this package and the classes therein. Another package worth noting is %Dictionary that gives you access to all aspects of class definitions, methods, properties, compiled classes etc... and finally the package %SYS contains may more system related classes The only other comment is that many system functions require you to be in the %SYS namespace in order to execute the function you require and will also require that you have sufficient roles assigned to your user account to perform such actions.
go to post Nigel Salm · Jun 5, 2019 You can't use $get or $data on an object property. What you should do is as follows, If $IsObject(ref) {set ^AK(1)=ref.Title} Else {set ^AK(1)=""} // or whatever you want to do if ref is not an object You could also do this: If $IsObject(ref),$l(ref.Title) {set ^AK(1)=ref.Title}Else {set ^AK(1)=""} // or whatever you want to do if ref is not an object or ref is an object but the property title is null
go to post Nigel Salm · Oct 3, 2017 Hi WRC helped answer this: Here is the code to build into your TablePane form: ClientMethod onloadHandler() [ Language = javascript ]{zenPage.IntervalRefresh();myVar1 = setInterval(zenPage.IntervalRefresh,1000);}ClientMethod IntervalRefresh() [ Language = javascript ]{var table = zenPage.getComponentById('TableName');//Optional if Snapshot is usedtable.executeQuery()table.refreshContents()}Note that the line table.executeQuery() is only required if your TablePane uses snapshot mode Nigel
go to post Nigel Salm · May 19, 2017 If you specifically wanted to make use of the Sample Classes in an Ensemble context then I would suggest one of two approches:1) Export the Sample Classes and Data and import them into the ENSDEMO namespace though bear in mind that were you to reinstall Ensemble the ENSDEMO database might be replaced2) The better approach would be to create a new database/namespace which will automatically inherit the Ensembele mappings and then import the SAMPLES classes and data into that new namespace/database