the key difference is that you can pass the classname by a variable.
So you are prepared to get the classname passed by some other method.

In your example with a constant string"circle"you miss the key advantage and It's of o added value.

BTW. Correct is   $classmethod("circle.radius","%New")

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

For testing with Terminal I typically use PuTTY.  http://www.putty.org/

There I can have multiple terminals with separated  Sessions/$JOB in parallel without problem.
(pls. don't ask how )
Terminal driver changes to a free set of ports ( 51133|10088) as you see by $IO
so it's no problem to have multiple terminal sessions connected 

USER>w $io
|TNT|127.0.0.1:51133|10088

I have no idea if Atelier allows multiple Terminals . And if how to launch them.
In Atelier just click again to the Terminal Open Icon:

is  Enable %Service_Telnet set ?
in  the Management Portal (http:///csp/sys/sec/%25CSP.UI.Portal.Services.zen)
 

My Caché runs on Win .(I'm not sure if this works also for Caché on Unix )

It does NOT work for Unix:

%Service_TelnetYesYesUnauthenticatedUnrestrictedControls Telnet sessions on a Windows server

 

So on UNIX you go to bash and have to start via csession....

Right: if you don't establish TELNET connection it's just bash or MS-DOS depending on your local OS.
Also for local localhost access !
so from Help:

Using the Terminal Plug-in
Telnet Connection
If your Caché instance is on a remote Windows server, you will need to connect using Telnet.
  1. Enable %Service_Telnet from the Management Portal (http:///csp/sys/sec/%25CSP.UI.Portal.Services.zen)
  2. In the main menu, select Show View > Other > Terminal > Terminal, or click this link to open the Opens the new Class file wizard Terminal View.
  3. Select the Open a Terminal button on the Terminal view toolbar.
  4. Select Telnet Terminal from the Choose terminal drop down menu.
  5. Complete the Telnet session configuration and click "OK"
  6. If csession isn't in your PATH, navigate to your instance's bin directory. For example, cd C:\InterSystems\Cache\bin.
  7. Launch a Caché terminal session. For example, csession Cache.

Setup Connection

And you get your Caché Terminal

 

HTH

It is. I have used it some time ago.
You need a  suitable plug in and connect to port 23 of your server 
(provided it is not blocked by Win* firewall.

plugin from the following update repository: http://download.eclipse.org/tm/terminal/marketplace/.

  1. From your Eclipse/Atelier workspace, navigate to command link Help > Install New Software from the main menu.
  2. Enter the URL for the Terminal plugin update site in the Work with field. Ensure that the Group items by category check box is selected.
  3. Once the groups are displayed, select the check box by the newest version.
  4. Click Next to open the Install Details page. Review your installation choices.
  5. Click Next to open the Review Licenses page. Accept the license terms and click Finish.
  6. To open the Terminal view, select Window > Show View > Other on the main menu and type "terminal" in the filter box. Select Terminal and OK.

Because it's so easy I've added a solution for those readers that don't refuse to work with Caché Objects & Classes .

Class Definition

Class DC.productListing Extends (%RegisteredObject, %XML.Adaptor)                            
{                                                                                                                                                                          
Property product As %String(CONTENT = "MIXED", XMLPROJECTION = "CONTENT");
}                                                                                                                                                                          

Simple display method

ClassMethod Show(xml As %String(MAXLEN=""))
{
 set rd=##class(%XML.Reader).%New()
    ,sc=rd.OpenString(xml)
 do rd.Correlate("product","DC.productListing")
 while rd.Next(.obj) {
    write !,"######"_$i(cnt)_"#########",$replace(obj.product,$c(10),$C(13,10))
 }
}

Extended test data

USER>write xml
<productListing title="ABC Products">
 <product>
   <name>Product One</name>
   <description>Product One is an exciting new widget that will simplify your life.</description>
   <cost>$19.95</cost>
   <shipping>$2.95</shipping>
 </product>
 <product>
   <name>Product 2</name>
   <description>Product 2 is an exciti</description>
   <cost>$19.95</cost>
   <shipping>$2.95</shipping>
 </product>
 <product>
   <name>Product 3</name>
   <description>Product 3 is simplify your life.</description>
   <cost>$19.95</cost>
   <shipping>$2.95</shipping>
 </product>
</productListing>
USER>

Result

USER>do ##class(DC.productListing).Show(xml)
 
######1#########
  <name>Product One</name>
  <description>Product One is an exciting new widget that will simplify your life.</description>
  <cost>$19.95</cost>
  <shipping>$2.95</shipping>
 
######2#########
  <name>Product 2</name>
  <description>Product 2 is an exciti</description>
  <cost>$19.95</cost>
  <shipping>$2.95</shipping>
 
######3#########
  <name>Product 3</name>
  <description>Product 3 is simplify your life.</description>
  <cost>$19.95</cost>
  <shipping>$2.95</shipping>
 
USER>

Kevin,

if you call a ClassMethod() it will return whatever the type of return value is like.
some variants:

- your Classmethod generates the CSV file as you do and the return value is the filename

ClassMethod Kevin1() as %String [SqlProc]
{                                        
....... generate CVS File                
 quit Filename                           
}                                        

 

- instead of a file you generate a 2 dimensional $Piece String (, as field separator and ^ as record separator)

ClassMethod Kevin2() as %String(MAXLEN="") [SqlProc]
{                                                   
....... setup ResultSet                             
    set output=""                                   
    while rs.Next() {                               
        for col=1:1:rcws.GetColumnCount() { set output=output_rs.GetData(col)_"," }
        set output=output_"^"                       
        }                                           
    quit output                                     
}                                                   

 

- a similar thing could be rows as a list of JSON sets

ClassMethod Kevin3() as %String(MAXLEN="") [SqlProc]
{                                                   
    set output=""
    &SQL( SELECT LIST(line) into :output FROM (
             Select top 3 JSON_OBJECT('Name':Name
                                      ,'ZIP':Home_ZIP
                                      ,'State':Home_State) as line
                      from sample.Person where name [ 'A' )
             )
         )                                      
    quit output                                     

///  {"Name":"Xiang,Agnes O.","ZIP":56604,"State":"MT"},{"Name":"Zubik,Bill A.","ZIP":78872,"State":"NV"},"Name":"Schaefer,Alvin X.","ZIP":63607,"State":"ME"}                                                 

in all cases you have to disassemble the result on the EXCEL end.

BUT as this is MS-EXCEL

my personal preference would be anyhow  to connect to Cache over ODBC with a local DSN
and just call your data via SQL and get back a full working XLS table that feeds the rest in your XLS.
This is standard in EXCEL and except for the DSN the same for ACCESS  or real DBs.
(as I don't own and use EXCEL any more  I can't offer an example)

- your initial question didn't mention CSV nor MS-EXCEL
so my Article on Light weight EXCEL Download may apply
https://community.intersystems.com/post/light-weight-excel-download

or  Tips & Tricks - SQL to Excel
https://community.intersystems.com/post/tips-tricks-sql-excel

HTH,
Robert

An alternate approach to SOAP:

a) you run your query over  JDBC on your DataServer
     so you can query what ever you like

b) slightly more sophisticated
    you create a ClassMethod with [SqlProc] parameter and also call it over JDBC
    like this.  SELECT Pkg.Class_ClassMethod()  
    It's totally up to you what the content of your return value is.   

I personally prefer JDBC as it's platform independent

in fact b) is pretty much the same as SOAP just with a different transport that avoids %CSP and its side effects.......

Proposal:

Store your JSON String as %String(MAXLEN="")  like a log file

for the typical components  type, age, firstname, lastname, ...
create calculated properties that find its content by $piece,  $find or some JSON specific stuff.
setup an  index on those calculated properties to find your record.

With this approach you keep the origin as you get it and get te indices you may require.
It's pretty similar to what I did to mimic an XML DB with Caché

so 1) =NO  2) =see above 3) =YES 4) = it's just another challenge