Class Servicios.REST.miSCS.Pruebas Extends EnsLib.REST.Service
{
Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter"
Parameter EnsServicePrefix = "/aplicaciones/scs/test/miscs"
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/:personType/:keyfield/:keyval/:getfield" Method="GET" Call="retrievePerson"/>
<Route Url="/consultarImagen" Method="GET" Call="consultarImagen"/>
</Routes>
}
Method retrievePerson(pInput As %Library.AbstractStream, Output pOutput As %Stream.Object, pPersonType As %String, pKeyField As %String, pKeyVal As %String, pGetField As %String = "") As %Status
{
Set tType=$ZConvert(pPersonType,"L") Quit:$Case(tType,"employee":0, "person":0, :1) $$$ERROR($$$EnsErrGeneral,"Directory type "_..#EnsServicePrefix_"/"_tType_"/ not supported.")
Set $E(tType)=$ZConvert($E(tType),"U")
Set tKeyIn=pKeyField, tKey=$ZConvert(tKeyIn,"L") Quit:$Case(tKey,"name":0, "ssn":0, :1) $$$ERROR($$$EnsErrGeneral,"Directory key "_..#EnsServicePrefix_"/"_tType_"/"_tKey_" not supported.")
Set tKeyVal=$Replace($ZConvert(pKeyVal,"I","URL"),"'","''")
Set tField=pGetField Set:""=tField tField="*" Quit:tField["," $$$ERROR($$$EnsErrGeneral,"Commas not allowed in selection field; found: .../"_tField)
Set tNS=$Namespace
Set tKeyWild=$Translate(pKeyVal,"*?","%_")
Do:tKeyWild'=pKeyVal pOutput.Write("[")
ZNSpace "SAMPLES"
try {
Set tSel=$S("*"=tField:"ID",1:tField)
Set tSQL="SELECT "_tSel_$S("*"=tField||(tKey=tSel):"", 1:","_tKey)_$Case("ID",tKey:"",tSel:"",:",ID")_" FROM Sample."_tType_" WHERE "_tKey_" LIKE '"_tKeyWild_"'"
Set tRS=##class(%ResultSet).%New()
Set tSC=tRS.Prepare(tSQL) Quit:$$$ISERR(tSC)
Set tSC=tRS.Execute() Quit:$$$ISERR(tSC)
Set tFirst=1
Set tOut=##class(%IO.StringStream).%New()
While tRS.Next(.tSC) && $$$ISOK(tSC) {
#
If tFirst {
Set k="" For { Set k=$O(tRS.Data(k)) Quit:""=k
If $ZConvert(k,"L")=$Zconvert(tSel,"L") Set tSelN=k
If $ZConvert(k,"L")=$Zconvert(tKey,"L") Set tKeyN=k
}
}
If $Case(tSelN, "Company":1, "Notes":1, "Home":1, "Office":1, :0) {
Set tVal=tRS.Data("ID")
Set tObj=$classmethod("Sample."_tType,"%OpenId",tVal,,.tSC) Quit:$$$ISERR(tSC)
Set tVal=$property(tObj,tSelN)
Set tSelX = $Case(tSelN, "Home":"Addr", "Office":"Addr", :tSelN)
Set tVal=$Case(tSelX, "Company":tVal.Name, "Notes":tVal.Read(), "Addr":tVal.Street_", "_tVal.City_" "_tVal.State_" "_tVal.Zip, :tVal)
} Else {
Set tVal=tRS.Data(tSelN)
}
If "*"=tField {
Set tObj=$classmethod("Sample."_tType,"%OpenId",tVal,,.tSC) Quit:$$$ISERR(tSC)
Set tProxyObj=..buildProxyObj(tObj)
Do tOut.Write($S(tFirst:"",1:","))
Set tSC=..ObjectToJSONStream(tProxyObj,.tOut)
} Else {
Set:tKeyN'=tSelN tKeyFound=tRS.Data(tKeyN)
Do tOut.Write($S(tFirst:"",1:",")_"{"_$S(tKeyN=tSelN:"",1:""""_tKeyIn_""":"""_tKeyFound_""", ")_""""_tSel_""":"""_tVal_"""}"_$C(13,10))
}
Set tFirst=0
ZNSpace tNS
Do tOut.Rewind() Set tSC1=pOutput.Write(tOut.Read()) Do tOut.Clear() Set:$$$ISOK(tSC) tSC=tSC1 Quit:$$$ISERR(tSC)
ZNSpace "SAMPLES"
} Quit:$$$ISERR(tSC)
Do:tKeyWild'=tKeyVal pOutput.Write("]"_$C(13,10))
} catch {
Kill tRS
ZNSpace tNS
Set tSC=$$$SystemError
}
Kill tRS
ZNSpace tNS
$$$LOGINFO("tSQL: "_tSQL)
Do:$$$ISOK(tSC) pOutput.SetAttribute("Content-Type","application/json")
while (pOutput.AtEnd = 0){
set respuestaFinal = pOutput.Read()
}
do pOutput.Rewind()
$$$LOGINFO("respuestaFinal: "_respuestaFinal)
Quit tSC
}
ClassMethod buildProxyObj(pObj As %Persistent) [ Internal ]
{
Set tProxy = ##class(%ZEN.proxyObject).%New()
Set tProxy.ID=pObj.%Id()
Set tProxy.Name=pObj.Name
Set tProxy.Age=pObj.Age
Set tProxy.DOB=$ZDateTime(pObj.DOB,3)
Set tProxy.SSN=pObj.SSN
Set tProxy.FavoriteColors=pObj.FavoriteColors
Set tProxy.Spouse=pObj.Spouse.Name
Set tProxy.Home=..buildProxyAddr(pObj.Home)
Set tProxy.Office=..buildProxyAddr(pObj.Office)
If pObj.%IsA("Sample.Employee") {
Set tProxy.Company=pObj.Company.Name
Set tProxy.Notes=$S($IsObject(pObj.Notes):pObj.Notes.Read(),1:"")
}
Quit tProxy
}
ClassMethod buildProxyAddr(pObj As %SerialObject) [ Internal ]
{
Set tProxy = ##class(%ZEN.proxyObject).%New()
Set tProxy.Street=pObj.Street
Set tProxy.City=pObj.City
Set tProxy.State=pObj.State
Set tProxy.Zip=pObj.Zip
Quit tProxy
}
ClassMethod OnErrorStream(pStatus As %Status)
{
Set tStream = ##class(%GlobalBinaryStream).%New() $$$ASSERT($IsObject(tStream))
Do tStream.Write($ZConvert($$$StatusDisplayString(pStatus)_$C(13,10),"O","UTF8"))
Set tStream.Attributes("Content-Type")=" text/plain; charset=""UTF-8"""
Set tStream.Attributes("ResponseCode")="500 Internal Server Error"
Quit tStream
}
Method consultarImagen(pInput As %Library.AbstractStream, Output pOutput As %Stream.Object) As %Status
{
Set pOutput=##class(%GlobalBinaryStream).%New()
set claseAux = ##class(%ZEN.Auxiliary.jsonProvider).%New()
set body = pInput.Read()
$$$LOGINFO("miSCS: body: "_body)
do pInput.Rewind()
set tSC= claseAux.%ConvertJSONToObject(.body,"Mensajes.Request.miSCS.ConsultarImagen",.objetoEntrada,1)
set tSC = ..SendRequestSync("miSCS",objetoEntrada,.objetoSalida)
set tSC = claseAux.%WriteJSONStreamFromObject(.pOutput,.objetoSalida,,,,"aloqtuw")
while (pOutput.AtEnd = 0){
set respuesta = pOutput.Read()
}
do pOutput.Rewind()
$$$LOGINFO("respuesta: "_respuesta)
$$$LOGINFO("tSC: "_tSC)
$$$LOGINFO("$$$ISOK(tSC): "_$$$ISOK(tSC))
Do:$$$ISOK(tSC) pOutput.SetAttribute("Content-Type","application/json")
while (pOutput.AtEnd = 0){
set respuestaFinal = pOutput.Read()
}
do pOutput.Rewind()
$$$LOGINFO("respuestaFinal: "_respuestaFinal)
Quit tSC
}
}
If you are sending a body in your request to the REST service then it needs to be a POST, not a GET.
<Route Url="/consultarImagen" Method="GET" Call="consultarImagen"/>
Thanks Marc Mundt for your reply
Yes you are right, we should use POST
We have changed it:
<Route Url="/consultarImagen" Method="POST" Call="consultarImagen"/>
However we do not see the response in POSTMAN:
And the headers are:
Content-Type: text/html
Content-Length: 0
CACHE-CONTROL: no-cache
PRAGAM: no-cache
We send the POST to the following URL:
http://localhost:19622/aplicaciones/scs/test/miscs/consultarImagen
Besides we observe the response message being converted from Ensemble object to JSON in the service:
We do see the Response Message from the Operation to the Service
Why we do not see the JSON being replied from the Service in POSTMAN?
How could we debug this behaviour?
Thanks for your replies
Thanks Marc Mundt for your attention, and your helpful reply
When we dig deeper using Whireshark:
First, we find that the method in the example that uses GET, the retrievePerson, does answers with a JSON to POSTMAN, so it works:
GET request:
GET response:
In POSTMAN:
However,
Our custom method: consultarImagen which is a POST
Shows nothing in POSTMAN
Why?
POST request:
POST response:
In POSTMAN:
Could you help us?
Thanks for your replies
Yone, try removing this line and test if it works:
Set pOutput=##class(%GlobalBinaryStream).%New()
Thanks Marc Mundt for your help
You are right
When we removed that line, the response is shown in POSTMAN:
Thanks four your help Marc
How did you know we should remove that line?
I noticed that retrievePerson doesn't instantiate pOutput.
We are grateful Marc for your help,
Thanks for explaining how did you find the cause which was preventing to get the response in POSTMAN
I would recommend using plain
%CSP.REST
and calling BP/BO from it. Here's how. You'll need to replace async call with a sync one to get response back, but the rest of the logic would be the same.Thanks Eduard for sharing this interesting piece of advice
Why would be better or recommended to use %CSP.REST directly, instead of EnsLib.REST.Service?
Are there any improvements if we use %CSP.REST?
Thanks for your reply
To start with using
%CSP.REST
is the recommended way to use REST with productions.It's easier to develop, there are more examples available, you can have a combined production/non-production REST services easily.
Hi Eduard,
I am looking for some examples of REST API served through production. Would you be able to point me to some, please?
I am trying to implement a business service, process and operation that serves bundle of apis related to a domain and resource e.g Patient , Patient alerts, patient status . These will be 3 api urls served by single business service, process and operation.
I am also looking for best practice to handle various http responses in BP and BO.
Would greatly appreciate if you can direct me to relevant examples.
Thank you,
Utsavi
Check this article.