Evgeny Shvarov · Jul 12, 2025 go to post

Exciting initiative!

I think this line in Update is "orphaned":

set myobj = ##class(%Library.DynamicObject).%FromJSON(%request.Content)  
Evgeny Shvarov · Jul 10, 2025 go to post

@Justin Millette, there are more settings to enable in the system to allow delegated access, e.g. a system-wide setting, mentioned in this great @Pravin Barton's article , also there is another one from @Yuri Marx 
 

Also, I don't recommend using the WebApplication tag as it is not working properly yet; there is at least one important bug not solved: for example , CSPApplication works quite well. 

Also, I see %all - I hope this is for development/demo usage only, as it is quite a generous role to use.

Evgeny Shvarov · Jul 1, 2025 go to post

I agree. I changed it to "not read-only" as I wasn't to manage unit-tests without it :) 

Don't know how to mark an object "modified" - otherwise, %Save() doesn't trigger the calculated property to update.

But I agree - read only is much better.

Evgeny Shvarov · Jul 1, 2025 go to post

Thank you, Kai! Do you have any examples where the case-sensitive principle can be used, e.g., with C++ or C# and InterSystems ObjectScript class properties? 

Evgeny Shvarov · Jun 30, 2025 go to post

Right. So, what is the reason, or if you may, what are the benefits of properties to be case sensitive?

Evgeny Shvarov · Jun 30, 2025 go to post

Exactly. And as I mentioned above, you cannot compile such a class with properties that differ only in case. What are the benefits of properties being case sensitive? Don't see any.

Evgeny Shvarov · Jun 30, 2025 go to post

How do you mean "use case"? You just shouldn't bother about the case of property names in IRIS while sending a JSON from your frontend to the IRIS REST-API. Like you don't care while sending it vs any SQL engine backend.

Evgeny Shvarov · Jun 30, 2025 go to post

Thank you, @Enrico Parisi ! But are you sure about 1.?

I've just created a class:

Class dc.sample.ObjectScript
{

property Name As %String;
property name as %String;

}

}

And have a compilation error:

ERROR! In class 'dc.sample.ObjectScript' Property 'Name' from 'dc.sample.ObjectScript' and 'name' from 'dc.sample.ObjectScript' have the same name but differ in case.
Evgeny Shvarov · Jun 27, 2025 go to post

A yet another workaround for non-obvious caveat of using %JSON.Adapter  and JSON transport around persistent data is a necessity to add an ID related property to your persistent class, like PersonId in this case:

Property PersonId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ];

This will allow to export ID of a record in DB automatically.

Same when you do updates with records, you need to remove this PersonId JSON from an update request, .e.g like this:

set personDynObj= {}.%FromJSON(person.Read())

do personDynObj.%Remove("PersonId") // Remove PersonId if it exists, as it is calculated

set sc = personObj.%JSONImport(personDynObj)

set sc = personObj.%Save()
Evgeny Shvarov · Jun 27, 2025 go to post

The simplest way to programmatically create a database in IRIS is:

do $SYSTEM.SQL.Execute("CREATE DATABASE MYDB")
Evgeny Shvarov · Jun 26, 2025 go to post

And 3 parameters for the spec class that help: HandleCorsRequest - it is most likely CORS will be needed, applicaton/json to support JSON content and ExposeServerExceptions for debug reasons:

Class shvarov.person.spec Extends %REST.Spec [ ProcedureBlock ]

{

Parameter HandleCorsRequest = 1;
Parameter CONTENTTYPE = "application/json";
Parameter ExposeServerExceptions = 1;
...
Evgeny Shvarov · Jun 26, 2025 go to post

also I always add the same _spec GET endpoint to let swagger have a working specification in docker - the default one doesn't work in docker as IRIS default spec one overrides the host variable to one, that doesn't work.

ClassMethod GetSpec() As %DynamicObject
{

set specname=$p(..%ClassName(1),".impl")

Set spec = {}.%FromJSON(##class(%Dictionary.CompiledXData).%OpenId(specname_".spec||OpenAPI").Data)

Set url = $Select(%request.Secure:"https",1:"http") _ "://"_$Get(%request.CgiEnvs("SERVER_NAME")) _ ":" _ $Get(%request.CgiEnvs("SERVER_PORT")) _ %request.Application
Set spec.servers = [{"url" : (url)}]

Quit spec

}
Evgeny Shvarov · Jun 26, 2025 go to post

@Ben Spead it's great you mentioned %OnAddToSaveSet() triggers - how do you manage cases when records were changed by CREATE/UPDATE SQL query? These triggers not fire in this case, right?

Evgeny Shvarov · Jun 24, 2025 go to post

Just've published the shvarov-persistent package once installed by
USER>zpm "install shvarov-persistent"

will add shvarov.persistent.base class which can be used as an ancestor after %Persistent, like:

Class yourclass Extends (%Persistent, shvarov.persistent.base)

, which will add two properties:

Property CreatedAt As %TimeStamp [ InitialExpression = {$ZDT($H, 3)} ];

Property LastUpdate As %TimeStamp [ SqlComputeCode = {set {*}=$ZDATETIME($HOROLOG,3)}, SqlComputed, SqlComputeOnChange = (%%INSERT, %%UPDATE) ];
Evgeny Shvarov · Jun 24, 2025 go to post

Hi @Luis Petkovicz!

Consider to try csvgen also?

it will be:

USER>zpm "install csvgen"

to install the package, and here is the usage:

USER>do ##class(community.csvgen).Generate("/folder/filename.csv")

to generate class and import the data into it from an arbitrary csv.

 

Evgeny Shvarov · Jun 23, 2025 go to post

Also this could be a typical copy-paste for a REST API app created in a module.xml in a <module> section:

<CSPApplication 
        Url="/travel/api"
        PasswordAuthEnabled="0"
        UnauthenticatedEnabled="1"
        DispatchClass="shvarov.travel.disp"
        MatchRoles=":{$dbrole}"
        Recurse="1"
        UseCookies="2"
        CookiePath="/travel/api"
       />

where /travel/api is the app name, and shvarov.travel.disp - a generated class vs the swagger spec file and shvarov.travel.spec class.

Evgeny Shvarov · Jun 23, 2025 go to post

Another useful comment: while generating swagger spec ask GPT to provide meaningful OperationId for every endpoint, otherwise the generated impl class will come with generated names for implementation methods like that:

Evgeny Shvarov · Jun 23, 2025 go to post

I think it is a good use-case for embedded python. I asked gpt and it suggested the following python code:

from datetime import datetime
from zoneinfo import ZoneInfo

# Original string
input_str = "Thu Jul 03 08:20:00 CEST 2025"

# Strip the abbreviation since it's not useful for parsing
# Replace it with an IANA timezone
# Let's assume "CEST" corresponds to Europe/Paris
input_str_cleaned = input_str.replace("CEST", "").strip()

# Parse the datetime
dt_naive = datetime.strptime(input_str_cleaned, "%a %b %d %H:%M:%S %Y")

# Localize to the correct zone
dt_aware = dt_naive.replace(tzinfo=ZoneInfo("Europe/Paris"))

# Format in ISO format with UTC offset
print(dt_aware.isoformat())  # e.g., '2025-07-03T08:20:00+02:00'

Also it suggested to make a mapping for CEST/CET:

tz_abbreviation_map = {
    "CEST": "Europe/Paris",
    "CET": "Europe/Paris",
    "EDT": "America/New_York",
    "EST": "America/New_York",
    "PST": "America/Los_Angeles",
    # Add more mappings as needed
}