Nigel Salm · Jan 3, 2017 go to post

Here are a couple more hints:

1) Review your code for $$$LOGINFO,  $$$LOGWARNING, $$$LOGERROR and $$$TRACE statements. Remove those that might have been useful during development and testing

2) If you create temporary globals make sure they are mapped to CACHETEMP

3) Depending on the nature of your application is there transactional data that can be summarized for future analysis and purge the original class data. For example: I have a production that processes Pharmacy Prescriptions. When I unpack the HL7 OMP message I create a hierarchy of parent-child classes objects that consisting of data from the HL7 message as well as  chunk of of other data, flags, etc... Once the order has been processed most of this data becomes irrelevant and so I extract the salient data, Patient ID, Prescription ID, Item Code, Quantities ordered and Quantities Dispensed and an overall Order Status. I write this to an archive class and purge the original data after 7 days.

Nigel Salm · Oct 3, 2017 go to post

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 used
table.executeQuery()
table.refreshContents()
}

Note that the line table.executeQuery() is only required if your TablePane uses snapshot mode

Nigel

Nigel Salm · Jun 18, 2019 go to post

I would suggest that adding the %All role, though it would work, is a bit like crushing a nut with a sledgehammer. It effectively opens the door to any unwanted intruder to gain access the Cache/Ensemble/IRIS. For the purposes of a demo test application %All role will work however the deve;loper should be aware that there are more appropriate security mechanisms available to handle user authentication.

Nigel Salm · Nov 5, 2019 go to post

Having gone through the pain of Installing Docker for Windows and then installing the InterSystems IRIS for HEALTH 2019.3 image and having got hold of a copy of the 2019.3 Studio I was please when I saw this announcement and excitedly went looking for my 2019.3......exe only to find out there is none and a small note at the end off the announcement to say that 2019.3 InterSystems IRIS and InterSystems IRIS for Heath will only be released in CD form.

Yours

Nigel Salm

Nigel Salm · Dec 3, 2019 go to post

Hi

When I was first exploring FHIR support In IRIS for Health I came across a very good Learning Services  Tutorial on the steps to add the extension to the FHIR Resource and then what you have to do to modify sda3 so that the FHIR STU3->SDA3 and the SDA3 -> FHIR STU3. However I did not bookmark the tutorial and despite searching Learning Services I cannot find that  tutorial.

If you know of any tutorial that covers this functionality please can you send me the link

Yours Hopefully

Nigel Salm

Nigel Salm · Jan 2, 2020 go to post

Hi

Would it be possible to send me your Business Operation code. It is difficult to debug these things without a complete picture of what you are attempting to do,

You can either attach the xml export of the class to this thread or mail it to me at nigel.salm@outlook.com

I get the idea that if the FTP or SMTP servers are not defined you will get the error you get. Is there a reason why they are not specified?

In your code you can always test to see if the ..Adapter.{server} is defined and throw an elegant error rather than wait for the adapter to go through the process of attempting to connect to the the server and then failing,

You can always play with the connection time outs etc so a screen shot of you  business operation production item values would be helpful

Yours

Nigel

Nigel Salm · May 19, 2017 go to post

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 replaced

2) 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

Nigel Salm · Jun 5, 2019 go to post

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

Nigel Salm · Sep 22, 2019 go to post

It is most likely that you are trying to do a POST but by default the browser is invoking a GET. An alternative to POSTMAN is  Advanced REST Client for Chrome which can be invoked from within Chrome or you can download a Windows version as well. It is useful as you can save data to Google Drive and therefore make the data available to other devices that support chrome.

Nigel Salm · Sep 29, 2019 go to post

I'm glad you resolved your issue. For the record there is another approach you could use and that is the %Library.ResultSet (or %ResultSet) class.

You can use this class to run Class Queries or Dynamic SQL

Here is an example from the Class Documentation with some liberal editing from myself

Set result=##class(%ResultSet).%New("%DynamicQuery:SQL")
	Set sc=result.Prepare("SELECT %ID, Name, Salary FROM Sample.Employee WHERE Salary > ?")
	If $$$ISERR(sc) Do $system.Status.DisplayError(sc)Quit
        // Get the first 10000 rows
	Set sc=result.Execute(10000) If $$$ISERR(sc) Do $system.Status.DisplayError(sc)Quit
        // To get all rows call the Execute Method with no parameter
	While result.Next(.sc) {
		If $$$ISERR(sc) Quit
		Write result.Data("Name"),result.Data("Salary"),!
	}
	If $$$ISERR(sc) Do $system.Status.DisplayError(sc)Quit
Nigel Salm · Sep 29, 2019 go to post

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.

Nigel Salm · Sep 29, 2019 go to post

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 End
End ;
        // 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 tSC
Error ;
        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

Nigel Salm · Nov 17, 2019 go to post

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

Nigel Salm · Nov 17, 2019 go to post

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

Nigel Salm · Dec 20, 2019 go to post

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

Nigel Salm · Jan 2, 2020 go to post

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;

Nigel Salm · Jan 22, 2020 go to post

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

Nigel Salm · Jun 16, 2020 go to post

I have taken a similar approach. I have a root directory 'Visual Studio Code' and under that I have a number of sub directories. Each of which contains a VS Code workspace file which looks like this:

{
    "folders": [
        {
            "path": "."
        },
        {
            "name": "XXX-XXXX-Interface-GIT",
            "path": "..\\..\\XXX-XXXX-Interface-GIT"
        }
    ],
    "settings": {
        "objectscript.conn.ns": "XXXX-QC",
        "objectscript.conn.password": "**********",
        "objectscript.conn.username": "*******",
        "objectscript.conn.active": true,
        "objectscript.conn.host": "NN.NN.NN.NN",
        "objectscript.conn.docker-compose.internalPort": 57772,
        "objectscript.conn.port": 57772,
        "objectscript.serverSideEditing": true,
        "objectscript.suppressCompileErrorMessages": true
    }
}

I have used 'X''s to obscure my actual Git, Namespace and Server settings and '*''s for my username and password.

Any settings that are universal I put into the VS Code .settings file which is stored in the windows->users->local-> ... directory

Settings such as Objectscript code snippets live in a .vscode file in my windows user settings directory.

This doesn't allow for multiple workspaces to be open at the same time but you can have multiple instanv=ces of VS code open, each one pointing to a different server/namespace where you are working.

Nigel Salm · Jul 5, 2020 go to post

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
 

Nigel Salm · Jul 5, 2020 go to post

Hi Anthony

That's great.

If you have other questions relating to Adapters and all things Ensemble then Post them in the Dev Community and I'll keep an eye out for them.

Yours

Nigel

Nigel Salm · Jul 7, 2020 go to post

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

Nigel Salm · Jul 9, 2020 go to post

Hi Goran

I am going to attach a set of classes from a real life application. I am going to put the class definitions into a word document. I would send you the XML but if you import the XML the classes won'r compile as there are too many claseses referenced in my code that I can't include.

The Basic overview of this production is that I have a Business Service that is processing a queue of messages that are created when data is trickle fed into a Data Warehouse. In my Business Process my request object contains a single property that is the MessageID of the message processed by the Business Service. 

In the Business service I open up the Message and from that I extract properties such as the Patient ID, three key fields LogType (where the data came from: PMI, In-Patient, Out-Patient...), a TransactionType that tells me more about what table in the Data Store is being Updated and an Action which is Add/Revise/Delete.

The Business Process  opens a configuration record from which it gets certain fields that give this Production Context.  I then find the correct Patient Object and I use a DTL to assign fileds in my Patient Class and other linked classes and populate a Standard HL7 ADT Message. The configuration settings include fields like Sending Facility, Sending Application, Receiving Application, Receiving Facility. These need to be sent into the DTL to populate these fields in the HL7 MSH header record. So I have created a custom AUX class which I can populate these fields within the DTL.

I then do another check to see if the data I am processing belongs to In-Patients or Out-Patients in which case I want to populate the Facility Code in the Visit Segment with the Facility code which I have transformed from an Application specific value into a National Facility Code.

Finally, if the data being processed is a Patient Merge then the ADT message structure has a different structure so I invoke another DTL to convert the ADT_A01 message into an ADT_A39 structure.

Finally I send the resultant message to an HTTP Operation and optionally to a File Operation.

I also have a build in Debugging class where I can write selected Debug information. In Development and UAT I want debugging turned on but in Production I don't so I have a property in the configuration that is a boolean flag that determines whether the debug message should be created or not.

Finally the configuration record also tells me how long I want to retain Debug Messages, Message Queue Messages, Ensemble Messages and Ensemble  Trace Logs and I have a business service that runs once a day and clears down any data that is older than the number of days I want to retain this data.

I have included the class definitions for all of the major classes I have described above.

Yours

Nigel 

Nigel Salm · Jul 9, 2020 go to post

Here is the attachment . I can't see if the attatchement has been uploaded. If not please send me an email address I can send the file to you.

Nigel

Nigel Salm · Jul 15, 2020 go to post

The first thought that came to me on this would be to define a class named MyContextClass which contains all of the many properties, collections, serial objects and so on and then define the Context Object to have one Property, 'Properties' whose data type is MyContextClass.

Then in the Business Rule you can use the syntax context.Properties.PropA and so on

Nigel

Nigel Salm · Jul 15, 2020 go to post

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

Nigel Salm · Jul 15, 2020 go to post

Sure so call your function which has one parameter:

method ABC(myContext as context.Properties) as %Status

{

  if myContext.PropA="Hello" write !,myContext.PropA," ","Nigel"

...

....

 quit $$$OK

then in your rule call ABC(context.Properties)

or am i missing something here?

Nigel

}

Nigel Salm · Jul 15, 2020 go to post

sorry, let me correct the parameter declaration as

method ABC(myContext as %RegisteredObject) as %Status

...

Nigel

Nigel Salm · Jul 15, 2020 go to post

Cool, let me know if it works. I have a similar situation for a BPL I am intending to write and I know I will have the same issue you are trying to resolve so I will be keen to know if this approach works because it is something I have been thinking about in anticipation of writing my BPL. My BPL will have a call to a DTL and I want to pass my context object to the Business Rule and then pass it into the DTL as the 'aux' object which is the 3rd parameter in the Transform() method as in ##class(MyDTL).Transform(pRequest,.pResponse,aux)

This works fine in custom code in a Business Process as aux can be any instance of a class but if the DTL is invoked from a Business Rule the aux is a specific object instance that holds properties that tell you about the rule that invoked the DTL  and I'm not sure I can pass my context object into the Transform as AUX if the DTL is instantiating it's own AUX object

I guess if I seemlesly pass the context object into the DTL via a Business Rule then I'll just have to invoke the DTL as a line of custom code in the BPL rather than as a Business Rule.

Nigel

Nigel Salm · Jul 16, 2020 go to post

Hi

You have to differentiate between resources and roles. Assigning database resource to a user with RW access will do exactly as it says, were the user be able to access the database they would indeed be able to read and write data from/to the database. However what you want to do is give them access to a select set of Management Portal menu options and forms and for that you need to assign the appropriate %{roles}. There are a number of Ensemble Roles available including the following:

Ensemble Administrator _SYSTEM   %EnsRole_AlertAdministrator Ensemble user with administrative Alert access _SYSTEM   %EnsRole_AlertOperator Ensemble user with Alert access _SYSTEM   %EnsRole_Developer Ensemble Developer _SYSTEM   %EnsRole_Monitor Ensemble Monitor _SYSTEM   %EnsRole_Operator Ensemble Operator _SYSTEM   %EnsRole_PubSubDeveloper Ensemble PubSub Developer _SYSTEM   %EnsRole_RegistryManager Administrator of the Public Registry _SYSTEM   %EnsRole_RegistrySelect Role for viewing Public Registry tables _SYSTEM   %EnsRole_RulesDeveloper Ensemble Rules Developer _SYSTEM   %EnsRole_WebDeveloper Ensemble Web Developer _SYSTEM

 There are other roles that give access to the general administration of your Cache/Ensemble/IRIS instance. These roles allow your user to do anything from being able to Monitor the system, perform system operator functions (Create Task Manager Tasks, manage Journals and other system related tasks). Theses roles include:

  %Manager A role for all System Managers _SYSTEM
  %Operator System Operators _SYSTEM

Then there are SQL related roles:

  %SQL Role for SQL access _SYSTEM
  %SQLTuneTable Role for use by tunetable to sample tables irrespective of row level security _SYSTEM

These roles would allow the user to run SQL queries in the Management Portal -> System Explorer -> SQL and perform other DB Administrator functions like Tuning a Table which is a process where by Cache/Ensemble/IRIS will analyse a class/table definition and the data in the table and table indices and based on this will add Selectivity information into the class definition which assists the SQL query generator to choose the least costly and most efficient use of standard indices, bitmap indices and iFind indices to retrieve the requested data.

Finally you have the %All role which gives the user access to everything and should only be granted to the very select group of Managers/Developers who need the flexibility of accessing all aspects of your Cache/Ensemble/IRIS installation. This role should be used with great caution because of the possibility of misuse in the wrong hands.

As the previous commentator wrote, check out the documentation on 'Controlling Access to the Management Portal Functions' but hopefully my response should give you a quick overview and understanding of resources and roles in general.

Nigel

Nigel Salm · Jul 18, 2020 go to post

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