#Tips & Tricks

12 Followers · 333 Posts

Pieces of experience in InterSystems Technology which solve some particular problem in elegant or unusual way.

Article Kurro Lopez · Oct 23, 2025 1m read

Hi all,

This is a quick tip about how to use case insensitive URL in REST API.

If you have a class that extends from %CSP.REST and Ens.BusinessService, to create a REST API service, and you have defined your WebApplication in lowercase

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
    <Route Url="/user" Method="POST" Call="User"/>
    <Route Url="/login" Method="POST" Call="Login"/>
</Routes>
}

Only accepts the url in lowercase, i.e. http://myserver/myproduction/user

If you have any uppercase character, the url doesn't work.

2
0 133
Article Pietro Di Leo · Nov 16, 2023 5m read

Introduction

Since InterSystems has recently announced the discontinuation of support for InterSystems Studio starting from version 2023.2 in favor of exclusive development of extensions for the Visual Studio Code (VSC) IDE, believing that the latter offers a superior experience compared to Studio, many of us developers have switched or are beginning to use VSC. Many may have wondered how to open the Terminal to perform operations, as VSC does not have an Output panel like Studio did, nor an integrated feature to open the IRIS terminal, except by downloading the plugins developed by InterSystems.

10
12 2485
Article Megumi Kakechi · Oct 2, 2025 2m read

InterSystems FAQ rubric

The ^%GCMP utility can be used to compare the contents of two globals.

For example, to compare ^test and ^test in the USER and SAMPLES namespaces, it would look like this:
*In the example below, 700 identical globals are created in the two namespaces, and the contents of one of them is changed to make it the detection target.

0
1 137
Article Kurro Lopez · Sep 29, 2025 13m read

I am truly excited to continue my "InterSystems for Dummies" series of articles, and today, we want to tell you everything about one of the most powerful features we have for interoperability.

Hey, even if you have already had a go, we plan to take a really close look at how to get the most out of them and make our production even better.

2
5 340
Article Megumi Kakechi · Sep 25, 2025 2m read

InterSystems FAQ rubric

One way to optimize query performance is to use query parallelism on a per-query or system-wide basis (a standard feature).

This is a technique for dividing the execution of a particular query among processors on a multi-processor system. The query optimizer will execute parallel processing only if there is a possibility of benefiting from parallel processing. Parallel processing is only applicable to SELECT statements.

Note that the number of parallel processes cannot be specified, as it is automatically adjusted according to the number of CPUs.

0
0 129
Article Victoria Castillo · Mar 19, 2024 5m read

I have been walking through this with a few team members and as such I thought there might be others out there who could use it, especially if you work with HL7 & Ensemble/HealthConnect/HealthShare and never venture out past the Interoperability section. 

First, I would like to establish that this is an extension of the already established documentation on importing and exporting SQL data found here: https://docs.intersystems.com/iris20241/csp/docbook/DocBook.UI.Page.cls?KEY=GSQL_impexp#GSQL_impexp_import

2
1 795
Article Derek Gervais · Sep 8, 2025 3m read

Hey folks! Having recently onboarded to InterSystems, I realized that despite having a totally free and awesome Community Edition, it's not super clear how to get it. I decided to write up a guide highlighting all the different ways you can access the Community Edition of InterSystems IRIS:

Get InterSystems IRIS Community Edition as a Container

Working with a containerized instance of the Community Edition is the recommended approach for folks who are new to developing on InterSystems IRIS, and in my opinion it's the most straightforward. InterSystems IRIS Community Edition can be found on DockerHub; if you have an InterSystems SSO account, you can also find it in the InterSystems Container Registry.

In either case, you'll want to pull the image you want using the docker CLI:

docker pull intersystems/iris-community:latest-em
// or
docker pull containers.intersystems.com/intersystems/iris-community:latest-em

Next, you'll need to start the container: In order to interact with IRIS from outside the container (for example, to use the management portal) you'll need to publish some ports. The following command will run the IRIS Community Edition container with the superserver and web server ports published; note that you can't have anything else running that depends on ports 1972 or 52773!

docker run --name iris -d --publish 1972:1972 --publish 52773:52773 intersystems/iris-community:latest-em
0
4 630
Article Megumi Kakechi · Dec 5, 2024 1m read

InterSystems FAQ rubric

If you want to raise an arbitrary custom error in a TRY block, you can pass an exception with a throw as follows. In the following example, a custom error is raised if Stcount is less than 1.

ClassClassMethodtry

In the above example, if Stcount is less than 1, an error like the following will be output:

USER>

For more information, see the following documentation:
ObjectScript command _THROW

If you want to create an arbitrary status code, do the following:

1
2 590
Article Megumi Kakechi · Sep 4, 2025 2m read

InterSystems FAQ rubric

In InterSystems IRIS, you can create linked tables using commands, instead of using System Explorer > SQL > Wizard > Linked Tables in the Management Portal:

To create a linked table, use the CreateLinkedTable method of the %SYSTEM.SQL.Schema class. See the class reference for details.

To execute it, follow these steps:

set$SYSTEM"<dsn>"
0
1 138
Article Ashok Kumar Thangavel · Jul 21, 2025 13m read

This article is a continuation of the IRIS JSON project and features additional methods and insights.

Let's continue with the instance methods

%GetTypeOf(Key)

This instance method is used to determine the JSON data type of the %DynamicObject or %DynamicArray.

It returns one of the following strings:

"null" - JSON null
"boolean" - Either "true" or "false"
"number" - Any numeric value
"oref" - An %ObjectHandle (an ObjectScript oref)
"object" - A nested object
"array" - A nested array
"string" - Normal text string
"unassigned" - The value is unassigned

USER>Set1

%GetIterator()

1
7 449
Article Mihoko Iijima · Oct 3, 2024 3m read

InterSystems FAQ rubric

You can check the free disk space at any time using the system utility class: SYS.Database and query: FreeSpace.

Here's how to try it in the IRIS terminal (go to the %SYS namespace and then run it):

zn"%SYS"set

The output result example is as follows:

*In the command execution example, all databases are located on the same disk, so the free disk space (DiskFreeSpace) returns the same value.

159

If you want to specify the database directory you want to refer to, run the following:

1
1 371
Question Dmitrii Baranov · Jul 15, 2025

I need to implement a retry policy for an incoming message queue containing thousands of relatively small messages.

Successfully processed messages should be immediately removed from the queue.

If an error occurs while processing a message, the message should be sent back at the end of the queue, and the pause before re-processing this message should increase geometrically (1-2-4-8-16 seconds, and so on). In languages that support the async/await pattern, I'd simply create a delayed timer that triggers a fire-and-forget task. This would prevent blocking the main thread.

8
0 217
Article David Hockenbroch · Sep 11, 2024 9m read

Do not let the title of this article confuse you; we are not planning to take the InterSystems staff out to a fine Italian restaurant. Instead, this article will cover the principles of working with date and time data types in IRIS. When we use these data types, we should be aware of three different conversion issues:

  1. Converting between internal and ODBC formats.
  2. Converting between local time, UTC, and Posix time.
  3. Converting to and from various date display formats.
4
5 868
Article Stephen Canzano · Jun 28, 2025 3m read

Maybe this is well known but wanted to help share.

Consider that you have the following persistent class defintions

An Invoice Class with a property reference to Provider

ClassExtends%PersistentAs

and Provider

If you call the Build method in Sample.Invoice you can query this with SQL

As

and see

The area this article discusses is deciding how to create a dimension on Provider.

What I have found works well is to following this pattern

What this does is 

1.

0
2 261
Discussion Harshitha · May 30, 2025

Hey everyone,

I'm diving deeper into Caché ObjectScript and would love to open a discussion around the most useful tips, tricks, and best practices you’ve learned or discovered while working with it.

Whether you're an experienced developer or just getting started, ObjectScript has its own set of quirks and powerful features—some well-documented, others hidden gems. I’m looking to compile a helpful set of ideas from the community.

3
4 249
Question Eric Tulowetzke · May 23, 2025

Hi all,

My team is exploring options for handling timezone offsets in DTL and we’re wondering if there are any built-in methods available — ideally low-code or no-code solutions. Specifically, we're looking for a way to adjust timestamps based on the date and whether Daylight Saving Time (DST) is in effect.

For example, if an HL7 message has an MSH-7 value of 20250518144529, it should be converted to 20250518144529-0500 (Central Daylight Time), but if the timestamp were 20250218144529, it should be 20250218144529-0600 (Central Standard Time).

6
1 231
Article Luis Angel Pérez Ramos · May 16, 2024 3m read

Reviewing the different articles that I have published, I realized that I needed to explain a very practical functionality within our EMPI (Enterprise Master Patient Index) and it is none other than the notification of registrations and links to systems external to the EMPI.

This functionality is frankly useful in a tool such as EMPI and especially in environments such as healthcare in which it is very common for the same patient to have their data duplicated in different systems and in the end it is necessary to uniquely identify it.

1
0 277
Article David Hockenbroch · Apr 22, 2025 7m read

The Good Old Days

The %Library.DynamicObject class has been in IRIS since before it became IRIS. If you have been using it since the Cache days, you may want to brush up on some of its changes.

In Cache 2018, the %Get method only had one argument. It was the key to retrieving from the JSON, meaning that if your JSON object called myObj, it would look like the following:

3
3 429
Article Kurro Lopez · Apr 14, 2025 14m read

As we all know, InterSystems is a great company.

Their products can be just as useful as they are complex.

Yet, our pride sometimes prevents us from admitting that we might not understand some concepts or products that InterSystems offers for us.

Today we are beginning a series of articles explaining how some of the intricate InterSystems products work, obviously simply and clearly.

In this essay, I will clarify what Machine Learning is and how to take advantage of it.... because this time, you WILL KNOW for sure what I am talking about.

1
10 413
Question PagerianDeveloper · Mar 17, 2025

Is there a way to use a property of the type %Persistent class in a  %ZEN.Component.page class?
Example:

// Data classClassExtends
Class


The problem is that when using it the described in the example.
The property can be set in a Method like this:

Method DoStuff() 


But when reading the property in an other Method the content of it is not set:

Is it generally possible to work like this?
Or have I overlooked a special handling?

3
0 207
Question Colin Brough · Mar 25, 2025

Is there a generic process for "walking" the structure of a virtual document - eg an HL7 message (EnsLib.HL7.Message) or an XML document (EnsLib.EDI.XML.Document).

At least we'd want to be able to visit all "nodes" (HL7 fields or sub-fields, XML nodes) in the virtual document and be able to work out/generate the Property Path (so we could call "GetValueAt"). 

We can just about come up with something generic for HL7, since it only nests down to 4 levels within each segment, though we're using numeric Property Path's at that point rather than symbolic ones (MSH:1.3 etc).

7
0 180
Article Brett Saviano · Dec 21, 2023 2m read

Have you ever been editing files in VS Code, but needed to check a global value or run a few ObjectScript commands? Now you can, with no setup required! If you have vscode-objectscript extension version 2.10.0 or later and are connected to InterSystems IRIS 2023.2 or later, you can now open a terminal connection to your server, regardless of where it's located.

7
11 1974
Article Colin Langella · Mar 11, 2025 2m read

Intro

In the process of trying to get more familiar with Objectscript I decided to try to build a general priority queue since I wasn't able to find an implementation anywhere. My though process for implementing this followed this general path.

Binary Heap

My first though to try to make this work quickly was to implement a binary heap and my first attempt at this used a multidimensional to build it. This version was relatively efficient, worked for strings/numbers natively, and worked for objects be letting the user override the comparitor.

Class pqueue.Queue Extends %RegisteredObject
{

Property Data As %Any [ MultiDimensional ];

Property Size As %Integer [ InitialExpression = 0 ];

Property Comparitor As %String [ InitialExpression = "(a,b) return a < b" ];
    
    Method Swap(i As %Integer, j As %Integer) As %Status [ Private ]
    {
    set temp = ..Data(i)
    set ..Data(i) = ..Data(j)
    set ..Data(j) = temp
    }
    
    Method Comp(x As %Any, y As %Any) As %Boolean [ Private ]
    {
    return $XECUTE(..Comparitor, x, y)
    }
    
    Method PercolateUp(idx As %Integer) [ Private ]
    {
    while idx > 0 {
    set newidx = (idx-1)\2

    if ..Comp( ..Data(idx), ..Data(newidx) ) do ..Swap( idx, newidx )
    else                                     Quit

    set idx = newidx
}
}

Method PercolateDown() [ Private ]
{
set idx = 0

while ((idx+1)*2) < ..Size {
        if ..Comp( ..Data(idx*2+2), ..Data(idx*2+1) ) set newidx = idx*2+2
        else                                          set newidx = idx*2+1
    
        if ..Comp( ..Data(idx), ..Data(newidx) ) Quit
    
        do ..Swap( idx, newidx )
        set idx = newidx
    }
    
    if ( (idx*2+1 < ..Size) && ..Comp( ..Data(idx*2+1), ..Data(idx) ) ) do ..Swap( idx, idx*2+1 )
    }
    
    Method IsEmpty() As %Boolean
    {
    return ..Size = 0
    }
    
    Method Top() As %Any
    {
    if ..IsEmpty() return ""
    return ..Data(0)
    }
    
    Method Put(inp As %Any) As %Status
    {
    set sts = $$$OK
    
    set ..Data( ..Size ) = inp
    do ..PercolateUp( ..Size )
    set ..Size = ..Size + 1
    
    return sts
    }
    
    Method Get(Output obj As %Any) As %Status
    {
    set sts = $$$OK
    if ..IsEmpty() {
        set obj = ""
        return $$$ERROR( "Cannot Get() from empty Queue" )
    }
    
    set obj = ..Data( 0 )
    set ..Size = ..Size - 1
    set ..Data( 0 ) = ..Data( ..Size )
    do ..PercolateDown()
    kill ..Data( ..Size )
    return sts
    }
    
    Method GenerateComparitor(operator As %String = "<", transform As %String = "") As %Status
    {
    set ..Comparitor = "(a,b) return a" _ transform _ " " _ operator _ " b" _ transform
    return $$$OK
    }
    
    }

After getting this working I wanted to try out different internal arrays since I assumed multidimensional arrays must be slower than a simple integer indexed array. So I modified the above code to use

*   `Property Data As list Of %Any;` : This works OK but it is about 3-4 times slower than using a multidimensional making it pointless.
*   `Property Data As %DynamicArray;` : I assumed this would be relatively fast but proved to be slow to the point of absurdity. When the amount of data stored in the queue is small it is around as fast as the `list of %Any`, but as the data grows the time it takes to make inserts and gets grows linearly which makes it pointless to build a heap on top of.

## Using the Multidimensional Array's Self-sorting

On its face this idea seems pretty simple, use the fact that the multidimensional array is always sorted to grab the lowest cost (highest priority) item. A problem with this are that indexing by an object simply uses the string representation of that object which isn't useful. To handle this a customer `evaluator` function is needed to return the integer or string evaluation of an object which is then sorted, it is then stored as `data( evaluation, obj_str_rep ) = object` which ensures that objects are correctly sorted even when two objects evaluate to the same value.

    Class pqueue.SparseQueue Extends %RegisteredObject
    {
    
    // Parameter Comp(a,b) As $XECUTE(..Comparitor, a, b);
    
    Property Data As %Any [ MultiDimensional ];
    
    Property Size As %Integer [ InitialExpression = 0 ];
    
    Property Evaluator As %String [ InitialExpression = "(a) return a" ];
    
    Method IsEmpty() As %Boolean
    {
        return ..Size = 0
    }
    
    Method Top() As %Any
    {
        if ..IsEmpty() return ""
        return $Order( ..Data("") )
    }
    
    Method Put(inp As %Any) As %Status
    {
        set sts = $$$OK
    
        set ..Data( $XECUTE(..Evaluator, inp), inp ) = inp
        set ..Size = ..Size + 1
    
        return sts
    }
    
    Method Get(Output obj As %Any) As %Status
    {
        set sts = $$$OK
        if ..IsEmpty() {
            set obj = ""
            return $$$ERROR( "Cannot Get() from empty Queue" )
        }
    
        set loc = $ORDER( ..Data("") )
        set obj = ..Data(loc, $ORDER( ..Data(loc, "")))
    
        set ..Size = ..Size - 1
        kill ..Data( loc, obj )
        return sts
    }
    
    Method GenerateEvaluator(transform As %String = "") As %Status
    {
        set ..Evaluator = "(a) return a" _ transform
        return $$$OK
    }
    
    }

This method proved to be by far the fastest. It has some slight disadvantages in that it can be harder to write an evaluator than a comparitor and, in the form given above, it cannot hold the same object at the same value twice (this is a rare case but could theoretically be a problem or a benefit).

## Speed Test

To test these out I wrote a simple script that generates a large randomized weighted directed graph and runs [Dijkstra's shortest path algorithm](https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/) using a given queue object. Using a graph with `150000` vertices where each has `10` neighbors, the output is printed below. Here while the algorithm is running an update is printed every `10000` edges checked, where the time since the last 10 thousand and size of the priority queue is printed, with some final stats at the end. The order they are run in is

*   Self-sorting Multidimensional

*   Heap Multidimensional

*   Heap Dynamic Array

*   Heap List of Object

> Generated Random Graph
0
0 249
Question Colin Brough · Feb 25, 2025

We have some ObjectScript code in a custom business process:

When Log Trace Events is ticked on the business process in the Production view in the management portal, the argument is obviously computed.

Our question is whether the argument is computed when Log Trace Events is not ticked? Don't want to accidentally include something in a $$$TRACE() statement that takes enough computation to make a performance difference when released to production, even though the final output is not written to the event log.

3
0 165