go to post Nigel Salm · Jan 1, 2022 Hi Michael, I have replied by email. Thank you for the offer. Yours Nigel
go to post Nigel Salm · Jan 1, 2022 That's very cool and a very useful way of handling security and access to specific CALLS in the REST dispatch class. Impressed
go to post Nigel Salm · Dec 27, 2021 Hi In Cache/Ensemble/IRIS there is a %NOLOCK clause that you can use in an Insert, Update or Delete. But that disables locking in these oerations. According to the documentation for TSQL the following documentation exists for LOCK TABLE: Lock Table Enables the current user to lock a table. LOCK TABLE tablename IN {SHARE | EXCLUSIVE} MODE [WAIT numsecs | NOWAIT] The LOCK TABLEstatement locks all of the records in the specified table. You can lock a table in SHARE MODE or in EXCLUSIVE MODE. The optional WAIT clause specifies the number of seconds to wait in attempting to acquire the table lock. The LOCK TABLE statement immediately releases any prior lock held by the current user on the specified table. LOCK TABLEis only meaningful within a transaction. It locks the table for the duration of the current transaction. When not in a transaction, LOCK TABLE performs no operation. Specify tablename as described in Table References. LOCK TABLE supports locking a single table; it does not support locking multiple tables. LOCK TABLE supports SHARE and EXCLUSIVE modes; it does not support WRITE mode. LOCK TABLE does not support the WITH HOLD clause. WAIT time is specified as an integer number of seconds; LOCK TABLE does not support WAIT time specified as clock time. The Documentation on Table Names reads a follows: Table References InterSystems TSQL supports table references with the InterSystems IRIS® data platform SQL format: schema.table The only mandatory table reference component is table. If the schema is omitted, TSQL uses the default schema name. Other forms of Transact-SQL may use table references with up to four components, separated by dots: server.database.owner.table. Here is how a Transact-SQL table reference is processed: The server. component, if present, is ignored. If the database. component is present and the owner. component is omitted, database is mapped to the schema name. Therefore, database..table maps to schema.table. This conversion is not performed if the database name is 'master'. If the owner. component is present, it is mapped to the schema name. For the purposes of name translation, a field name has the field suffix removed while translation is performed and then replaced afterwards. Temporary Tables InterSystems TSQL supports #tablename temporary tables. A #tablenametemporary table is visible to the current procedure of the current process. It is also visible to any procedure called from the current procedure. #tablename syntax is only supported in TSQL procedures (class methods projected as procedures with language tsql). A temporary table is defined by using CREATE TABLE with a table name starting with "#". The temporary table is created at runtime. A #tablenametable definition goes out of scope when you exit the procedure. All temporary table definitions go out of scope when the connection is dropped. You can also explicitly delete a temporary table using DROP TABLE. However, if a temporary table is referenced by an active result set, the temporary table may become invisible to the process, but the data and definition are retained until the result set goes out of scope. A #tablenametemporary table is visible both to the creating procedure and to any procedures called from that procedure. Temporary tables are visible to nested procedure calls. It is not necessary to declare the temporary table in the called procedure. If the called procedure also creates a temporary table with the same name, InterSystems IRIS uses the most recently created table definition. Because a temporary table is defined using an ObjectScript local variable, the creation, modification, and deletion of these tables are not journaled transaction events; rolling back the transaction has no effect on these operations. System Tables System tables exist per InterSystems IRIS namespace. Systypes Partially supported. Nigel
go to post Nigel Salm · Dec 27, 2021 Hi I think that there is a 'DOS CSV' file format that dows use COMMAS but I am not sure how you would specify it. In Excel, it is one of the options when exporting a spreadsheet to a delimited text file. Nigel
go to post Nigel Salm · Dec 27, 2021 Hi May I ask what O/S you are running your live production on? One of the curious things I discovered where Ubuntu (and other Linux products) differ from Windows is in the way that an Ensemble production will shutdown (and notionally restart). This is especially true if the queues are very long. On Windows, I was used to setting the Timeout to 60 seconds and sometimes even less and so when I had to develop and deploy an application on Ubuntu I got very confused when we attempted to shut down the production (using 60 seconds) and the whole server would freeze and become unresponsive. At the time I knew nothing about Ubuntu (or Linux in general) and it was only when I got the Ubuntu expert to show me how I could monitor the system during Shutdown and what amazed me is that Ensemble spawned off 10's of jobs (up to 100) which I assumed it had down to try and clear the queues before shutting down and all of these extra processes consumed resources, CPU time and memory and of course the machine ground to a halt. The trick. Give the production at least 120 seconds and maybe even 180 seconds to shut down and you will find that it behaves perfectly correctly. Yours Nigel
go to post Nigel Salm · Dec 27, 2021 Hi I would expect the content type to be 'application/json'? (I assume the responseType is the contentType? In every HTTP Operation I have worked with that used json that was the content type). The character set must be set to UTF-8 unless you need to use the Latin character set in which case use Latin. Bear in mind, both the server and the client must be consistent in declaring what they are sending and what they are expecting to receive. I found the following article on Angular and HTTP (or Interceptors as they are called after Angular 5) HttpHeaders We add HTTP Headers using the HttpHeaders helper class. It is passed as one of the arguments to the GET, POST, PUT, DELETE, PATCH & OPTIONS request. To use HttpHeaders in your app, you must import it into your component or service 1 2 3 import { HttpHeaders } from '@angular/common/http'; Then create an instance of the class 1 2 3 4 5 const headers= new HttpHeaders() .set('content-type', 'application/json') .set('Access-Control-Allow-Origin', '*'); And then call the httpClient.get method passing the headers as the argument 1 2 3 return this.httpClient.get(this.baseURL + 'users/' + userName + '/repos', { 'headers': headers }) Note that httpHeaders are immutable. i.e every method on HttpHeaders object does not modify it but returns a new HttpHeaders object. The httpHeaders class has several methods using which you can manipulate the headers. set set(name: string, value: string | string[]): HttpHeaders The Sets method returns a new instance after modifying the given header. If the header already exists, its value is replaced with the given value in the returned object. 1 2 3 4 5 const headers = new HttpHeaders() .set('content-type', 'application/json') .set('Access-Control-Allow-Origin', '*'); httpHeaders are immutable The HTTP headers are immutable. The following example does not work as each set method returns a new header and does not update the original header. 1 2 3 4 5 6 let headers = new HttpHeaders() headers .set('content-type', 'application/json') headers .set('Access-Control-Allow-Origin', '*') console.log(headers); To workaround, you can use the code as follows 1 2 3 4 5 const headers= new HttpHeaders() .set('content-type', 'application/json') .set('Access-Control-Allow-Origin', '*'); You can also use the following code 1 2 3 4 5 6 let headers = new HttpHeaders() headers=headers.set('content-type','application/json') headers=headers.set('Access-Control-Allow-Origin', '*'); console.log(headers) append append(name: string, value: string | string[]): HttpHeaders The append method appends a new value to the existing set of values for a header and returns a new instance. The append method does not check if the value exists. 1 2 3 4 5 6 7 8 9 let headers = new HttpHeaders() headers=headers.append('content-type','application/json') headers=headers.append('Access-Control-Allow-Origin', '*') headers=headers.append('content-type','application/x-www-form-urlencoded') console.log(headers) The above results in content-type header in the request header as content-type: application/json,application/x-www-form-urlencoded has has(name: string): boolean Returns true if the given header with the name already exists in the HttpHeaders. The following code checks if the content-type header present in the request header. If not it adds it. 1 2 3 4 5 6 7 let headers = new HttpHeaders() headers=headers.append('Access-Control-Allow-Origin', '*') if (!headers.has('content-type')) { headers=headers.append('content-type','application/json') } I hope this helps Nigel
go to post Nigel Salm · Dec 27, 2021 Hi I checked and it is in the WRC Internal Distributions under 'Components' and the following releases are available for 2018.1. 4: Yours Nigel
go to post Nigel Salm · Dec 25, 2021 I thought I knew most of the of the debugging tricks in Caché, Ensemble and IRIS, and I have used the sql shell but had not used it the csp shell and I though I have found debugging basic csp pages using a log global and JS popup messages ( simplistic but they worked). However, when it came to Zen bebugging was a nightmare. I could view the page source and inspect the Dom but the sleepless nights I had with hgroups and vgroups and the inheritance of CSS styles could not explain why, on a form containing 15 text boxes, drop-down mists and some check boxes with all my captions neatly aligned left and my data entry controls aligned left in the second inner vgroup (page has outer vgroup, then an hgroup for my heading, and then two vgroups for my captions and data controls) and on one row out of 15, the caption was indented by 5 Characters of the data control would be rightalligned. For absolutely no obvious reason at all. I used the inspector to nest through every page element, the css in play, and the various in-line, align="left" (or equivalent) and I could spend days trying to work out why this one element was misbehaving. I spent more time debugging stupid things like this than I had spent in total in writing all of the Class Zen Get and Set methods, the sql queries to populate lists, getting the correct syntax for selected item vs identifier item and the menus and all the graphics and style sheets put together. I never did find an easy way to debug these layout issues and I wonder if you had any tricks for resolving these silly layout issues that literally cost me days in testing? Nigel
go to post Nigel Salm · Dec 25, 2021 The changes are good and will Allov DC members to create a more 3D picture of of themselves and what they do. Nice changes to the way articles are handled.
go to post Nigel Salm · Dec 24, 2021 In IRIS there is a whole load of JSON functionality that can be ing=herited into a class and for the [properties of the class you can specify the JSONNAME, JSONIGNORE, and various others (similar to the XML qualifiers in the Attributes of an XML Enable class) and so it is very easy to specify how to read a JSON message into an Object and visa versa. Likewise you can deal with null, true, false. I have also discovered, while battling with JSON in Ensemble that the value that gets written to a json string depends on where it comes from: for example, if you use SQL to retrieve your data to populate a json string then the LogicalToODBC method of a property will rer=trun null if the internal value is "" but will return "" if you are using objects. In the same way, a boolean field in SQL will display true or false if the display mode is ODBC. However I agree with Danny that it is best to use the %Set `method to set the correct values into the JSON string for null, true, false. I have been unable to find any other way of doing this in Ensemble. Nigel
go to post Nigel Salm · Dec 17, 2021 That's absolutely brilliant. I had no doubt we would win like so many people comment on how friendly, passionate and useful our community sites are. Special thanks and congratulations to Anastasia, Olga, Evgeny and any others I have missed who put so much effort and enthusiasm into the success of this community. Love you all. Nigel
go to post Nigel Salm · Nov 17, 2021 Hi Ben Once I got my first Raspberry Pi I had to learn Ubuntu, Docker (my one experience of Docker on Windows had not gone well, however, Rich Taylor took exactly 30 minutes to convince me that having 15 IRIS or IRIS for Health containers in Docker for Ubuntu on his Raspberry Pi farm was a very good thing indeed). The introduction of Python, both Native and Embedded along with R and Julia had me scurrying off looking for quick ways to get up to speed on the basics. I invested in a Samsung T5 500GB SSD drive and I studied a couple of articles on the web on how to get my Pi's to boot from a USB SSD only to realise that the people who had followed his instructions ended up with a sticky mess. In the end, I just used my laptop to clone the Micro SD to the SSD and even though it left most of the SSD unallocated which 3 different windows partitioning tools along with the built-in windows diskpart and computer components tools couldn't solve, as soon as I connected the SSD to my Pi and booted from the SSD, Ubuntu very nicely went and expanded the partition for me. I could have used GParted to create more partitions and I suspect that I could probably create 3 separate boot and data configurations for 3 Pti's with a bit of thinking and planning. However, I digress, everywhere I went on this journey I came across cheatsheets for everything and not just programming. I mean everything. There is even a Cheatsheet Site that runs competitions for the best cheat sheets in terms of style, usefulness, readability, sensitivity to people who can't see colours very well. Then Yuri published a DC Post on seeing IRIS through the TOGAF model and he did a great job so I asked him if I could add it to my collection. My aim is to get DC members who a really fond of some particular aspect of ObjectScript, or Adapters, or Devices, or IRIS HL7 and IRIS FHIR to create cheat sheets which I will collect into one volume and have them styled in ISC colours and logo's and add them to the ISC Learning, Documentation, Global Masters repertoire. So by publishing my article and attaching the Python examples I hope to inspire other DC members to start contributing. Nigel
go to post Nigel Salm · Nov 13, 2021 Hi David This is a great article. I am currently working for a company that has used the task manager as a fundamental part of the application architecture. If I had been involved in the design of their application I would probably have used an Ensemble Production with services for each automation and then specify a time when the service should run. The application I am working on has given me a whole different view on how the Task Manager can be used so your article couldn't come at a better time from my point of view. Nigel
go to post Nigel Salm · Nov 13, 2021 Hi Yuri and DC members As you know I have challenged the DC members to come up with cheat sheets for IRIS and this is a perfect example of what I was hoping to see from DC members. With your permission, I would like to include it in my collection of IRIS Cheat/Information sheets. For other DC members reading this post and there is an aspect of IRIS that you are particularly familiar with or passionate about then have a go and see if you can come up with a similar informative diagram. Typically the cheat/information sheets are one-two page long. When it comes to a language explanation then you would typically create a page on commands, another on operators and so on. Let your inner artist guide your layout and colour scheme. Once I have built up a substantial collection of IRIS topics I'll see if Olga, Evgeny and Anastasia and the ISC Experts will vote on the best layout and all cheat/information sheets will be modified to conform to that look. Who knows, they may even reward the winner. Bear in mind that ISC have a certain style, colour scheme and logo's and this should be taken into consideration/ Nigel P.S. Sorry Yuri for high jacking your Article ro further my personal mission.
go to post Nigel Salm · Nov 11, 2021 The Developer Community is my favourite social media site. 30 years ago when I joined InterSystems there were 10 Sales Engineers, we designed our own courses for customers, we bemoaned the fact that there was no IRC channel we could hook into. There was no documentation other than that which came with the product. We had long conversations about how nice it would be if we could share or code, our experiences, the lessons we had learnt. Slowly things began to happen and 20 years later DC was born and even in the last two years it has doubled in size, has reached Discord and Telegram. You can enter any word related to InterSystems or any of their products into Google and you will get pages and pages of results. It is one of the most active threads on LinkedIn. Congratulations to all of you who have made this possible. Thank you so very very much!
go to post Nigel Salm · Nov 10, 2021 Does this by any chance have something to do with connecting a VGAstyle pin connector to a TCP connector?
go to post Nigel Salm · Nov 5, 2021 Hi Ben, I have been thinking very hard about doing this. There are two things that I would like to do, the first is to create a web form that prompts the developer for the properties that will be needed in the message queue that identify the specific source record in the source class/table and the second is to replace the Business Process with a BPL that will execute a sequence of business rules that retrieve the specified data, call a DTL (most likely choice), nd add any other logic. It is possible that you might want to pass the initial document through a second transformation. For example, if you are creating an ADT message and the default structure is an ADT_A01 but the actual structure you need is a Merge so you need to transform the A01 into an A39 and add an MRG segment. The DTL is very simple, it moves the PID, PV1 details into a PID GRP structure and then adds the MRG segment. I think that though this is not strictly necessary it would be a nice option to have. Secondly, the UI would prompt the developer for the Namespace and Database names and locations and I then programmatically create the routine database, global database and the namespace and then programmatically create the Package and Global mappings. The really useful functionality is the test module and that needs some work. I know how I want to represent the properties, lists etc that can be modified for a test condition and then have a UI that allows the developer to select the property, list, related table to the various data manipulation rules that I have defined (bearing in mind that the developer can also write custom methods to manipulate any element) The only issue I have is that, though I am very experienced in CSP and Zen, I would like to use this as an opportunity to build the UI in any of the regular .js frameworks (Angular, React, Vue, Node) and Python Flask. I would really like to use Python as it would be an excellent way of developing my Python skills. I guess there is nothing to stop me from releasing the current version as V1.0 and then spending some time developing the other things I would like to incorporate and bring out a v2.0. I also want to test it on three of my Pi's with the source database on one Pi, the codebase and Interfaces on the second and the target HL7/FHIR server on the third. And I would like to do it using Ubuntu Containers in my Docker for Ubunto which is what I am running on my Pi's Nigel