Hi @Lucrezia Puntorieri 
Yes you can create a method and classmethod programmatically.

Set clsmethodObj = ##class(%Dictionary.MethodDefinition).%New()
Set clsmethodObj.Name="TestClsMethod"
Set clsmethodObj.ClassMethod=1
Do clsmethodObj.Implementation.WriteLine($C(9)_"Set ^test=""Test"" ")
Do clsmethodObj.Implementation.WriteLine($C(9)_"Quit ^test ")

Set methodObj = ##class(%Dictionary.MethodDefinition).%New()
Set methodObj.Name="TestMethod"
Set methodObj.ClassMethod=0
Do methodObj.Implementation.WriteLine($C(9)_"For I=1:1:10 { S ^test(i)=i} ")
Do methodObj.Implementation.WriteLine($C(9)_"Quit ^test ")

Do clsObj.Methods.Insert(clsmethodObj)
Do clsObj.Methods.Insert(methodObj)

Hi Jack

IRIS does not provide built-in functionality to generate classes directly from a JSON Schema, unlike the support available for XML Schema (XSD). However, you can programmatically create and compile classes at runtime using the %Dictionary.ClassDefinition API.

Here is the sample code to generate a class.

ClassMethod CreateClass()
{	
	Set clsObj = ##class(%Dictionary.ClassDefinition).%New()
	Set clsObj.Name="Test.NewClass"
	Set clsObj.Super="%RegisteredObject,%JSON.Adaptor"
	Set clsObj.Description="Class created via code"
	Set clsObj.DdlAllowed = 1
	Set clsObj.Inheritance="left"
	
	Set propObj = ##class(%Dictionary.PropertyDefinition).%New()
	Set propObj.Name="Name"
	Set propObj.Type="%String"
	Set propObj.SqlColumnNumber=2
	Do propObj.Parameters.SetAt(70,"MAXLEN")
	
	Set indexObj = ##class(%Dictionary.IndexDefinition).%New()
	Set indexObj.Name="NameIdx"
	Set indexObj.Properties="Name"
	Do clsObj.Properties.Insert(propObj)
	Do clsObj.Indices.Insert( indexObj)
	Set st=  clsObj.%Save()
	D $SYSTEM.OBJ.Compile("Test.NewClass","ckb")
	If $$$ISERR(st) w $SYSTEM.OBJ.DisplayError(st)
}

Hello @PhoebeK 

If emailAttachmentList is a DynamicArray, then the following property declaration is correct:

Attempt 2 // 
Property emailAttachmentList As List of Request.EmailAttachment(%JSONFIELDNAME = "emailAttachmentList");

It looks like you're trying to set the value directly like:
    callrequest.emailAttachmentList.attachmentClass = "application/xml"

However, since emailAttachmentList is a list, you need to either:
- Use %JSONImport(response) to populate the list properly (e.g., `callrequest.%JSONImport(response)`), or
- Loop through the list and set the property on each individual item, like this:

For i=1:1:callrequest.emailAttachmentList.Count() {
  Set callrequest.emailAttachmentList.GetAt(i).attachmentClass = "application/xml"
}

Hello @Scott Roth 
I hope the target is a object reference of  HS.FHIRModel.R4.Patientand the "name" property in in R4.Patient is an object property(HS.FHIRModel.R4.SeqOfHumanName ) and thisSeqOfHumanName stores the %DynamicArray of  HS.FHIRModel.R4.HumanName object values into property called "list" 

So, First we have to check the name is  $IsObject(r4Patient.name)&&(r4Patient.name.%IsA("HS.FHIRModel.R4.SeqOfHumanName")) and if it's true you can iterate the list (%DynamicArray)   Set iter = r4Patient.name.list.%GetIterator()

You can directly copy and run this example directly and it works for me.

ClassMethod ParseHumanName()
{
    Set r4Patient = ##class(HS.FHIRModel.R4.Patient).%New()
    ;
    Set seqHuman = ##class(HS.FHIRModel.R4.SeqOfHumanName).%New()
    ; create human name for seqHuman
    Set human = ##class(HS.FHIRModel.R4.HumanName).%New()
    Set human.family="pil"
    Set human.text="Ashok,kumar"
    ;
    ;push the HumanName into SeqOfHumanName
    Do seqHuman.add(human)
    
    ; Set SeqOfHumanName into Patient.name
    Set r4Patient.name = seqHuman
    
    If $IsObject(r4Patient.name)&&(r4Patient.name.%IsA("HS.FHIRModel.R4.SeqOfHumanName")) {
        Set iter = r4Patient.name.list.%GetIterator()
        #;
        while iter.%GetNext(,.humanName) {
            zw humanName.toDao()
        }
    }
    quit
}

The HS.FHIRModel.R4.Patient class in  IRIS directly represents the FHIR R4 Patient resource as defined. When a FHIR Bundle is loaded using HS.FHIRModel.R4.Bundle.fromDao(), each resource in the bundle's entry.resource is automatically mapped to the correct HS.FHIRModel.R4.* subclass (e.g., Patient, Encounter, AllergyIntolerance) based on its resourceType. There’s no need for manual casting — the object model handles the typing internally.

here is the sample code

Set bundle={"resourceType":"Bundle","type":"searchset","total":3,"entry":[{"fullUrl":"https://example.org/fhir/Patient/patient-1","resource":{"resourceType":"Patient","id":"patient-1","name":[{"family":"Doe","given":["John"]}],"gender":"male","birthDate":"1985-02-15"},"search":{"mode":"match"}},{"fullUrl":"https://example.org/fhir/Encounter/encounter-1","resource":{"resourceType":"Encounter","id":"encounter-1","status":"finished","class":{"system":"http://terminology.hl7.org/CodeSystem/v3-ActCode","code":"AMB","display":"ambulatory"},"subject":{"reference":"Patient/patient-1"},"period":{"start":"2023-07-01T10:00:00Z","end":"2023-07-01T10:30:00Z"}},"search":{"mode":"include"}},{"fullUrl":"https://example.org/fhir/AllergyIntolerance/allergy-1","resource":{"resourceType":"AllergyIntolerance","id":"allergy-1","clinicalStatus":{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical","code":"active"}]},"verificationStatus":{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/allergyintolerance-verification","code":"confirmed"}]},"type":"allergy","category":["food"],"criticality":"high","code":{"coding":[{"system":"http://snomed.info/sct","code":"227493005","display":"Cashew nuts"}],"text":"Allergy to cashews"},"patient":{"reference":"Patient/patient-1"},"reaction":[{"manifestation":[{"coding":[{"system":"http://snomed.info/sct","code":"271807003","display":"Skin rash"}]}],"severity":"moderate"}]},"search":{"mode":"include"}}]}                                                                                             
set fhirModelBundle = ##class(HS.FHIRModel.R4.Bundle).fromDao(bundle)  
;
Zwrite fhirModelBundle.entry.list.size()
3
;
Zwrite fhirModelBundle.entry.list.get(0).toDao() ; patient
{"fullUrl":"https://example.org/fhir/Patient/patient-1","resource":{"resourceType":"Patient","id":"patient-1","name":[{"family":"Doe","given":["John"]}],"gender":"male","birthDate":"1985-02-15"},"search":{"mode":"match"}}  ; <DYNAMIC OBJECT>                        
;
Zwrite fhirModelBundle.entry.list.get(1).toDao() ; encounter
{"fullUrl":"https://example.org/fhir/Encounter/encounter-1","resource":{"resourceType":"Encounter","id":"encounter-1","status":"finished","class":{"system":"http://terminology.hl7.org/CodeSystem/v3-ActCode","code":"AMB","display":"ambulatory"},"subject":{"reference":"Patient/patient-1"},"period":{"start":"2023-07-01T10:00:00Z","end":"2023-07-01T10:30:00Z"}},"search":{"mode":"include"}}  ; <DYNAMIC OBJECT>                                                                                                                         
;
Zwrite fhirModelBundle.entry.list.get(2).toDao() ; Allergy
{"fullUrl":"https://example.org/fhir/AllergyIntolerance/allergy-1","resource":{"resourceType":"AllergyIntolerance","id":"allergy-1","clinicalStatus":{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical","code":"active"}]},"verificationStatus":{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/allergyintolerance-verification","code":"confirmed"}]},"type":"allergy","category":["food"],"criticality":"high","code":{"coding":[{"system":"http://snomed.info/sct","code":"227493005","display":"Cashew nuts"}],"text":"Allergy to cashews"},"patient":{"reference":"Patient/patient-1"},"reaction":[{"manifestation":[{"coding":[{"system":"http://snomed.info/sct","code":"271807003","display":"Skin rash"}]}],"severity":"moderate"}]},"search":{"mode":"include"}}  ; <DYNAMIC OBJECT>

Index ZipIDX On ZipCode [ Data = (City, State) ];

Here, the index is built on the ZipCode field, and the City and State fields are included in the Data portion of the index structure (i.e., stored as part of the index global). When a query retrieves only City and State based on a ZipCode filter, the SQL engine can perform an index-only scan and avoid accessing the main "Master map". This behavior is similar to a covering index in SQL databases because the requested data is fully available within the index itself.

SELECT City, State FROM Sample.Person WHERE ZipCode = 19904;

In this case, the index global might look like:

^gblI("ZipIDX", ZipCode, ID) = $LB("", City, State)

The query will be satisfied using just the index, avoiding a full table (master map) access.

However, this index does not provide any benefit when the query uses City or State as filter conditions, since those fields are not part of the index key. So, It will search on the "Master map"

Now, consider another index:

Index CityStateIDX On (City, State);

This is a composite index (or multi-column index), where both City and State are stored as part of the index key (subscripts), not as index data. The global would look like:

^gblI("CityStateIDX", City, State, ID) = "

SELECT state FROM SAMPLE.PERSON1 WHERE city ='Newton'

When a query uses City or State in the WHERE clause, the index is used to locate the matching IDs, but the SQL engine must then perform a lookup in the master map to fetch any other columns, even if you're selecting only indexed fields like City or State.

So, composite indexes help filter rows efficiently, but they don't function like covering indexes unless the query involves only index keys and you don't need to retrieve other columns.

Here is the Index types documentation

You can delete the application error logs for all days by executing the below code for specific namespace 

ClassMethod DeleteAppErrorLog(Namespace As %String = {$Namespace}) As %Status
{
    New $Namespace
    Set $Namespace = "%SYS"
    Return ##class(SYS.ApplicationError).DeleteByNamespace(Namespace)
}

Delete by date

ClassMethod DeleteAppErrorLogByDT(pNamespace As %String = {$Namespace},pDate ={$ZD(+$H)}) As %Status
{
    New $Namespace
    Set $Namespace = "%SYS"
    Return ##class(SYS.ApplicationError).DeleteByDate(pNamespace,pDate)
}

Maybe can you try to wrap the HL7 message like below format and set the ContentType As "application/xml"  in additional setting in the Business operation "EnsLib.HL7.Operation.HTTPOperation" and check for the response headers as well if required.

<?xml version="1.0" encoding="UTF-8"?>
<HL7Message>
<![CDATA[
MSH|^~\&|... your message ...
PID|... etc ...
]]>
</HL7Message>

We can use the %IsDefined method  to check the key is defined, and %Size() to determine the number of the elements in an Object or Array. These methods help to prevent from the <INVALID OREF> and <UNDEFINED>

// verify the "items" is present and it has values
If responseData.%IsDefined("items")&&(responseData.items.%Size()) {
    Set item1 = responseData.items.%Get(0)
    If $IsObject(item1) {
        Write item1.portalUrl
    }
    /*another*/
    If $IsObject(item1)&&(item1.%IsDefined("portalUrl")) {
        Write item1.portalUrl
    }
}

The %GetTypeOf method is used to determine the type of a key, and it returns 'unassigned' if the key does not exist

If responseData.%GetTypeOf("items")="array" {
    Set item1 = responseData.items.%Get(0)
    If $IsObject(item1) {
        Write item1.portalUrl
    }
}

Hi @Pravin Barton

The {Contents} has the id of the stream property. So, We can open the the stream object  by using OID and then convert to JSON like below. and the stream write need to use %ToJSON() for JSON serialization stream.Write({"msg":"hello world!"}.%ToJSON())


Trigger ExtractKeys [ Event = INSERT/UPDATE, Foreach = row/object, Time = AFTER ]
{
    new contentsJSON, id, msg
    
    if {Contents*C} {
        set contentsJSON = {}.%FromJSON(##class(%Stream.GlobalCharacter).%Open($lb({Contents},"%Stream.GlobalCharacter","^PAB.DebugStreamS")))
        set id = {ID}
        set msg = contentsJSON.msg
        &sql(update learn_Smp.NewClass13 set msg = :msg where Id = :id)
        $$$ThrowSQLIfError(SQLCODE, %msg)
    }
}

Thanks!

Hi @Julian Matthews

The Ens.StreamContainer class is a %Persistent class and it stores the different types of stream in it. So, If you delete the row/record by id / or by query it will delete the entry as well as the stream contents(it's also part of the row) from the Ens.StreamContainer table. So, be cautious before deleting the container. %OnDelete  callback method is used to do some additional function while deleting the object.

Hello @Nezla,

The %SYS.Task class has the task details which includes the status of the task. The "Suspended" column has value if incase the task is errored out while running ("Suspend Leave" ) or the task is suspended ("Suspend Reschedule"). Based on this column you can find out the suspended /errored task. Use the below query for the TaskName and additional details.

select Name,Status,TaskClass,Suspended from %SYS.Task

Hello  @Michael Wood,

here are several approaches you can take to handle this. One option is to create a file service that reads the file as a stream and sends it to a custom business process. You can then convert that stream into a JSON object and iterate through each DynamicObject entry. Alternatively, you could send the stream to BPL and process the JSON there

Simplified sample of process the JSON. 


Class Samples.Introp.JSONFileService Extends Ens.BusinessService
{

Parameter ADAPTER = "EnsLib.File.InboundAdapter";

Method OnProcessInput(pInput As %Stream.Object, Output pOutput As %RegisteredObject) As %Status
{
	Do ..SendRequestSync("JSONFileProcess",pInput,pOutput)
	Quit $$$OK
}

}

Class Samples.Introp.JSONFileProcess Extends Ens.BusinessProcess [ ClassType = persistent ]
{

Method OnRequest(pRequest As Ens.Request, Output pResponse As Ens.Response) As %Status
{
	Set json = {}.%FromJSON(pRequest)
	
	Set iter = json.%GetIterator()
	
	while iter.%GetNext(.key,.val)
	{
		s ^test($Classname(),$NOW(),key)=val.%ToJSON()
	}

	Quit $$$OK
}
}

Thanks!

Hello @Krishnaveni Kapu 

%SYS.Task is responsible for store, suspend and resume for all the tasks. so, your can execute the below method programmatically to achieve it. It expects the task id as the first argument

You can execute the below query to get the task id, name and additional information

select Suspended,Name,id from %SYS.Task

suspend

Flag

1 - Suspend the task, but leave it in task queue (default)
2 - Suspend the task, remove from task queue, and reschedule for next time

Set taskId = 1001
Set flag = 2
Write ##class(%SYS.Task).Suspend(taskId,flag)

resume

Set taskId=1001
Write ##class(%SYS.Task).Resume(taskId)