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.

  1. Use a Utility Method: Develop a utility method within a class that inherits from Ens.Util.FunctionSet. This method would read the source config name from the first message header in the session. You can then use this method in your router logic as it will be automagically included.  

Custom utility functions used in DTL and Rules are defined in a class extending/inherits from Ens.Rule.FunctionSet, not Ens.Util.FunctionSet.

As documented here.

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' />

I had the same issue in in one system and opened a WRC case.

This is a spurious message (benign, simply should not be there)  and can be ignored, nevertheless make messages.log analysis...complicated.

You may want to contact WRC and mention MAK5798  and DP-412382.

Please note that this was "First fixed in IRIS 2022.2.0", so upgrading can be another option.

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>

Instantiated classes can be compiled with no error since....long time, I think at least Cachè 2017 but I might be wrong.

This is also documented here:

Compiling When There Are Existing Instances of a Class in Memory

If the compiler is called while an instance of the class being compiled is open, there is no error. The already open instance continues to use its existing code. If another instance is opened after compilation, it uses the newly compiled code.

However, the code to scan all processes variables is good to know/useful!