My guess (I may be wrong!) is that you did not configure IIS existingResponse PassThrough option.

In IIS, if you don't configure that options, application errors (like IRIS REST errors) are not sent back to the client, instead a "standard IIS error" (my definition) is sent back to the client (i.e. browser).

Check this IRIS documentation on Configuring IIS to Return SOAP Fault Details, although it refers to soap, the same apply to REST.
You may want to google "IIS existingResponse PassThrough" for more info.

Again, I may be wrong...but I bet on this being the issue here.

First I'd suggest not to use a persistent class "linked" to a message (Ens.Response in this case), Supplier  is linked by your message class in this case.
If you do it, you will definitely create "orphaned" persistent objects when you purge, unless you add some logic (like triggers and callbacks) to delete the "linked" persistent objects when a message is purged.

To avoid this (when possible) a serial class is preferred.

So, the Supplier class would be:

Class Community.App.Msg.Supplier Extends (%SerialObject, %XML.Adaptor)
{
Property row As %Integer;
}

As for the message class:

Class Community.App.Msg.Suppliers Extends Ens.Response
{

Property Supplier As list Of Community.App.Msg.Supplier(XMLPROJECTION = "ELEMENT");
ClassMethod test() As %Status
{
    set XmlString="<Suppliers><Supplier><row>1</row></Supplier><Supplier><row>2</row></Supplier></Suppliers>"
    set reader = ##class(%XML.Reader).%New()
    $$$ThrowOnError(reader.OpenString(XmlString))
    do reader.CorrelateRoot("Community.App.Msg.Suppliers")
    do reader.Next(.Suppliers, .tSC)
    do Suppliers.XMLExport(,",indent")
    quit tSC
}
}

For simplicity I modified the sample to be a classmethod.
When the test() method is run the output is:

EPTEST>d ##class(Community.App.Msg.Suppliers).test()
<Suppliers>
  <Supplier>
    <row>1</row>
  </Supplier>
  <Supplier>
    <row>2</row>
  </Supplier>
</Suppliers>

The relevant documentation is "Controlling the Form of the Projection for Collection Properties" here.

Let me add a few notes.

If a class extend Ens.Response or Ens.Request  is not necessary to extend %Persistent because is already inherited by Ens.Request/Ens.Response.
Edit: please see Antoine commnet below

If the desired XML tag correspond to the class name (without package), it is not necessary to add the XMLNAME parameter, like you did in App.Objects.Suppliers class.

Same goes for XMLNAME property parameter XMLNAME = "row" is not necessary because the property name correspond to the desired XML tag name.

OK, I think I understand the question! 😊

Suppose you want to put the "source" HL7 Message SourceConfigName in MSH:Security:

<assign value='##class(Ens.MessageHeader).%OpenId($$$JobCurrentHeaderId).SourceConfigName' property='target.{MSH:Security}' action='set' />

In case you what to get the first message source config name:

<assign value='##class(Ens.MessageHeader).%OpenId($$$JobSessionId).SourceConfigName' property='target.{MSH:Security}' action='set' />

To "capture" output I'd use a pipe instead of $ZF(-100), here a code sample:

Class Community.ExecOS [ Abstract ]
{

/// run an operating system command
ClassMethod ExecOS(cmd As %String, Output LinesOut As %String)
{
    set oldzeof=$SYSTEM.Process.SetZEOF(0)
    set io=$IO,LinesOut=0
    try {
        if cmd="" Quit
        open cmd:"Q" use cmd
        for LinesOut=1:1 {
            read LinesOut(LinesOut)
        }
    } catch CatchError {
        If CatchError.Name'="<ENDOFFILE>" {
            set LinesOut=CatchError.Name
        }
    }
    close cmd
    Do $SYSTEM.Process.SetZEOF(oldzeof)
    Use io
    quit
}

}
EPTEST>d ##class(Community.ExecOS).ExecOS("dir",.out)
 
EPTEST>zw
out=13
out(1)=" Volume in drive C has no label."
out(2)=" Volume Serial Number is 3E11-87B5"
out(3)=""
out(4)=" Directory of c:\intersystems\irishealth\mgr\eptest"
out(5)=""
out(6)="02.01.2024  12:14    <DIR>          ."
out(7)="02.01.2024  12:14    <DIR>          .."
out(8)="11.01.2024  19:04       429'916'160 IRIS.DAT"
out(9)="05.01.2024  14:26                42 iris.lck"
out(10)="24.11.2023  00:34    <DIR>          stream"
out(11)="               2 File(s)    429'916'202 bytes"
out(12)="               3 Dir(s)  63'936'786'432 bytes free"
EPTEST>

I found the problem.

The issue does not happen if the service user is changed using:

IRISinstall.exe setserviceusername <instance-name> <username> <password>

When that command is issued two groups are created:

IRISServices
IRIS_Instance_<InstanceNme>

and the service user is added as member of there two groups.

The reason that it works using this way is that to the IRISServices group, in Local Security Policy is assigned the "Replace a process level token" user right.

In other words, the user that stars IRIS need the "Replace a process level token" right assigned via Local Security Policy (or GPO in an AD Domain).

Lesson learned:
- Use IRISinstall.exe to change the user for the IRIS service
or
- Assign "Replace a process level token" right to the user of IRIS service

Set sc=##class(%File).GetDirectorySpace("D:",.FreeSpace)

Write FreeSpace

Classreference:

classmethod GetDirectorySpace(Name As %String, ByRef FreeSpace As %String, ByRef TotalSpace As %String, Flag As %Integer = 1) as %Status
Return the amount of total space and free space in either Bytes,MB,GB on a drive or directory
Name = Valid Drive or directory specification
Flag = 0 - Return bytes
Flag = 1 - Return MB (Default)
Flag = 2 - Return GB

MB and GB returned are rounded to 2 decimal places.
Any error status returned is O/S level error. Note that on Windows only drives have a measurement for free space and directories can not so the FreeSpace is only returned for drives.

Please note that "%PosixTime values have a 1 microsecond resolution", see %Library.PosixTime class reference documentation.

Then:
USER>set ts="2023-12-12 19:46:19.000"
 
USER>set Posix=##class(%Library.PosixTime).TimeStampToLogical(ts)
 
USER>write ##class(%Library.PosixTime).LogicalToTimeStamp(Posix-18000000000)
2023-12-12 14:46:19

Enrico

Using correct length of 16 characters for IV and 32 characters key.

This Javascript:

var iv CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
var stringyouWantToEncrypt "HelloWorld";
var base64Key "RXJjb2xpbm9zZW1wcmVpbnBpZWRpMDEyMzQ1Nzg5MDE=";
var encrypted CryptoJS.AES.encrypt(
    stringyouWantToEncrypt,
    CryptoJS.enc.Base64.parse(base64Key),
    {
        iv: iv,
    }
)

And this ObjectScript:

Set text="HelloWorld"
Set IV=$c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Set KEY = "RXJjb2xpbm9zZW1wcmVpbnBpZWRpMDEyMzQ1Nzg5MDE="
Set KEY=$SYSTEM.Encryption.Base64Decode(KEY)
Set text=$ZCONVERT(text,"O","UTF8")
Set sCrypt=$SYSTEM.Encryption.AESCBCEncrypt(text,KEY,IV)
Set sToken=$SYSTEM.Encryption.Base64Encode(sCrypt)
Write !,!, "Encoded -> "_sToken

Both return the same:

Encoded -> 2s4qbUJC6romvsp7TP2L4A==

Enrico