Here's my code, of course I could shrink this down a lot, but figured people might want to read it.

Personally, I think looking at different ways of doing the same thing are a great learning lesson.  Judging based on the length of the code, simply encourages bad programming.

ClassMethod toPhone(i As %String)
{
    set k="----abc-def-ghi-jkl-mno-pqrstuv-wxyz ---"
    set i=$zconvert(i,"L"),o=""
    f p=1:1:$l(i) s c=$e(i,p),d=$f(k,c)\4+1,r=3-(d*4-($f(k,c))) s:r<1 r=4+r,d=d-1 s:d>9 d=0 s z="",$p(z,d,r+1)="",o=o_$s($e(o,$l(o))=d:" ",1:"")_z
    q o
}

Your $zv looks very suspect Paul.   On one hand you have a 2016.2 beta of Ensemble, but you have HealthShare libraries also which aren't distributed with Ensemble.

Was this a HealthShare instance of 2016.1 that you overlayed with a 2016.2 install of Ensemble?

I'm not sure that can ever be expected to work right.

Maybe try your service on a fresh install of 2016.2 beta and see if it works then, although you won't have access to the HS libraries 

The only strangeness I see here is that in your code you set pOutput to the result of HS.Test.Service.SendSync which returns a %Status.

In your method, the pOutput variable is used in the method declaration and is supposed to be a stream object because that is how the adapter responds back as the response to the http request.

I wonder if this could possibly be the problem.  I have to admit that the behavior is very strange, if indeed that is the problem.

Interesting,  I took your code and just added some code to the OnProcessInput method so that it would just take a string int he body of the http request and then echo that string back as the response.  here is the code, which when tested with my http test tool seems to work fine which would indicate that there might be a problem elsewhere.

What settings are you using when adding your service to the production, and what version of Ensemble are you using?

Here's a copy of the working code I tested in 2016.1

Class Community.Services.MyService Extends Ens.BusinessService
{

/// Set Adapter
Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter";

/// Set this to 0 to prevent normalizing of HTTP header variable names to lowercase
Parameter TOLOWERHEADERVARS = 1;

/// Set this to make page parse form variables from the form body in case of a form POST
Parameter PARSEBODYFORMVARS = 0;

/// Copied from EnsLib.HTTP.Service
Method OnInit() As %Status
{
    If $IsObject(..Adapter) {
        Set ..Adapter.%ToLowerHeaderVars=..#TOLOWERHEADERVARS
        Set ..Adapter.ParseBodyFormVars=..#PARSEBODYFORMVARS
    }
    Quit ##super()
}

/// Same method signature as EnsLib.REST.Service
Method OnProcessInput(pInput As %Library.AbstractStream, Output pOutput As %Stream.Object = {$$$NULLOREF}) As %Status
{
    set pOutput=##class(%GlobalCharacterStream).%New()
    set string=pInput.Read()
    do pOutput.Write(string)
    quit $$$OK
}

}
 

Here's an example of a business service that receives input in the form of a delimited string, passes the input off to a business process (in your case it would be a business operation), gets the response and returns the response as the return document.

Class AC.Services.HTTPService Extends Ens.BusinessService
{

Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter";

Method OnProcessInput(pInput As %GlobalCharacterStream, Output pOutput As %Stream.Object) As %Status
{
    // Instanciate the output stream
    set pOutput=##class(%GlobalCharacterStream).%New()
    
    // Read the delimited string passed in the content stream
    set iStr=pInput.Read(,.tSC)

    // Build the request message
    set request=##class(AC.Messages.RouteMessagePreProcessRequest).%New()
    set request.DOB=$p(iStr,"^",1)
    set request.Facility=$p(iStr,"^",2)
    set request.RXNumber=$p(iStr,"^",3)
    set request.SSN4=$p(iStr,"^",4)
    set request.CMOPFlag=$p(iStr,"^",5)
    
    // Send request message to RouterPrePRocess
    do ..SendRequestSync("RouteMessagePreProcess",.request,.response)
    
    // Return response to caller
    do pOutput.Write(response.RESP)

    Quit $$$OK
}

}
 

You should use an Ensemble REST web service which is a sub-class of EnsLib.REST.Service

I would recommend starting with reviewing the documentation on CSP REST services which can be found at the link below.  This will give you a basic understanding of how Ensemble implements RESTful web services.

http://docs.intersystems.com/ens201513/csp/docbook/DocBook.UI.Page.cls?K...

There is also an extension of the HTTP adapter that provides an interface for providing RESTful web services as part of your production.  The documentation on how to implement this can be found here:

https://community.intersystems.com/product-documentation/creating-rest-s...

Jeff- Thanks

What I am really looking for here is a generic way to represent any global structure as JSON.

In my example, the top node contains both data as well as sub-nodes.  

I'm not really looking for a way to represent a person in JSON, just a way to represent generic global structures taking into account the fact that a global node can have both data stored at that particular level as well as sub-nodes below it.

I have to say that I never thought of using Google to search our documentation until a colleague pointed it out to me a while back.

Need the function to determine your process id.

Open Google, enter "intersystems determine process id"

First returned document is the documentation for the $JOB symbol variable which contains your process id.

I have to say that as an Intersystems employee I was disappointed when I heard that the feature maps were going away.  I cant say how many times I used to use those maps for jumping to a key feature that I wanted to know about.

However, since I started using Google to search the docs the docs have become much more friendly and easy to locate what I'm looking for.

Change is hard....