Hi Sergio,

I have the following code that will do what you need, but i don't see this as the best approach since it is more complicated than a bunch of If's. 

But it works, and it shows that you do anything in ObjectScript!

Class MyPackage.MyClass
{

ClassMethod MyMethod(p1 = 1, p2 = 2, p3 = 3)
{
Write p1,"-",p2,"-",p3,!
}

ClassMethod Test()
{
Do ..FromJson({})
Do ..FromJson({"P1":"first value""P2":"second value"})
Do ..FromJson({"P1":"first value""P3":"third value"})
Do ..FromJson({"P2":"second value"})
}

ClassMethod FromJson(json)
{
Set call="(json) Do ##class(MyPackage.MyClass).MyMethod("  //we need to pass json as input param to xecute
Set first = 1
For jsonProp = "P1","P2","P3" {
If 'first Set call=call_","
//Set call=call_$Select(json.%IsDefined(jsonProp):"json."_jsonProp,1:"") //same as $Property, but doc mentions to use $Property instead
Set call=call_$Select(json.%IsDefined(jsonProp):"$Property(json,"""_jsonProp_""")",1:"")
Set first = 0
}
Set call=call_")"
Xecute (call,json) //pass json as input parameter
}

}

Hi John,

I tried to create the classes you are describing, and they seem to give the correct results in the two SQL statements.

The two query plans are also giving the same access path.

Can you tell me what the outcome (data/error) of the second SQL statement is giving you ? 

I used following classes :

Class User.immst Extends %Persistent
{
Relationship PhysicalRecord As User.pytrn [ Cardinality = many, Inverse = ItemRecord ];
Property imdesc As %String;
}

Class User.pytrn Extends %Persistent
{
Relationship ReportRecords As User.pyrpt [ Cardinality = many, Inverse = PhysicalRecord ];
Relationship ItemRecord As User.immst [ Cardinality = one, Inverse = PhysicalRecord ];
Property pypqty As %String;
}

Class User.pyrpt Extends %Persistent
{
Relationship PhysicalRecord As User.pytrn [ Cardinality = one, Inverse = ReportRecords ];
Property pypqty As %String;
}

 

To start debugging in Studio, you first have to set your method as a debug-target : right-click on the method header and choose 'Set DoMyWork as debug target'.

Then set a breakpoint  anywhere in the method you want to start debugging (click on F9  to toggle breakpoints)

Then start the debugger in the menu  or Ctrl-F5.

If you want to call your method with some predefined arguments, it is better to create another method that will call ..DoMyWork(.arg1, arg2) and use this method as your debug-target, or  better, in the debug menu, click on debug-target and add proper arguments in the classmethod.

If you wish to debug in terminal, you need to use the command Break with some options :

USER> Break "S+" Do ##class(MyPackage.MyClass).DoMyWork(.arg1)

^
<BREAK>zDoMyWork+1^...
USER 2d1> 
 

Option S or L with + or - depending if you want to debug instruction by instruction (S) or Line by line (L), debug into methods (+) or execute them(-).

Use G (or Goto) to go step by step, Use Break "C" to clear debugging.

More info on Break : https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_debug

Hi Jimmy,

I think the Send* methods have an extra argument where you can specify the REST type (GET, PUT or POST), and the methods with the Get, Put or Post in the names are just shortcuts that internally call the Send method. (This is true in the %Net.HttpRequest class, so i guess it is the same in the adapter)

The SendFormDataArray and SendFormDataUrl have also an extra argument where you can pass  a %HttpRequest instance. So you could create this instance to pre-populate properties that are not possible to set using the adapter, like the ContentType property.

Set objHttpRequest ##class(%Net.HttpRequest).%New()
Set objHttpRequest.ContentType "application/json"
Set tSC=..Adapter.SendFormDataURL(tURL,.tHttpResponse,"POST",objHttpRequest,,pRequest1.%ToJSON()).
 

I haven't tested this code (don't have Ensemble) but looking at the docs it should work.

Hi Jimmy,

I don't use Ensemble , but maybe the 4th parameter is not in the right format : see doc(https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=EHTTP_outbound#EHTTP_C7322547) :

The pData argument is an array. The top node of the array is not used. Each subnode is subscripted by the index of the corresponding form variable in the pFormVarNames list. The value at a given subscript should be specified as follows:

  • For a form variable (varname) with a single value, the value at pData(“varname”) should be the form data value to send. There should be no subnodes.

  • For a form variable (varname) with multiple values, the value pData(“varname”) should be the count of the values. Each of the values for this form variable should appear in a subnode, subscripted by its position in the node.

  • To send a request body instead of form variables, leave pFormVarNames empty and pass the body text as the pData argument.

So, can you try to call the PostURL with pRequest.%ToJSON()

In Caché - using %Net.HttpRequest - it works like this :

Set objHttpRequest = ##class(%Net.HttpRequest).%New()
Set objHttpRequest.ContentType = "application/json"
Set objHttpRequest.Server = "dummy.restapiexample.com"
Set pRequest = {"name":"abc1jim23","salary":"123","age":"23"}
Do objHttpRequest.EntityBody.Write(pRequest.%ToJSON())
If objHttpRequest.Send("POST", "/api/v1/create") {
Set objHttpResponse = objHttpRequest.HttpResponse
If $IsObject(objHttpResponse.Data) {
     Set objStream = objHttpResponse.Data
     Set json =""
     While ('objStream.AtEnd) {
          Set json = json _ objStream.ReadLine()
     }
Else {
     Set json = objHttpResponse.Data
}
Set httpStatus = objHttpResponse.StatusCode
Write "Status : ",httpStatus,!
Write "Response : ",json,!
}

Any of the following is possible, but this will only work if you want to keep the data in the two namespaces for that class exactly the same : 

  • Map the globals that are used by the persistent class to the other namespace.

OR

  • Change the global names in the Class Storage definition (DataLocation, IDLocation, IndexLocation, StreamLocation) and add a namespace reference to it, like this :
Storage Default
{
<Data name="customerDefaultData">
...
<DataLocation>^["USER"]test.customerD</DataLocation>
<DefaultData>customerDefaultData</DefaultData>
<IdLocation>^["USER"]test.customerD</IdLocation>
<IndexLocation>^["USER"]test.customerI</IndexLocation>
<StreamLocation>^["USER"]test.customerS</StreamLocation>
<Type>%Library.CacheStorage</Type>

Be careful if properties are pointing to other persistent classes as well !

You can run the Job command with a timeout parameter, and check if the job has really started with the $TEST variable :

USER> JOB ##class(TestFramework.API.E2E.Service).RunCases()::0

USER> Write $TEST

Should be 1 if the classmethod was started, 0 if the job timed out and did not start

In the second case it can be a license problem, check  https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GSA_license#GSA_license_capacity

Hi Kurt,

Some old terminal emulators cannot work with UTF8.

I used AniTa which had the same problem connecting to a Caché Unicode server.

I tried TeraTerm which is free and can at least work with UTF8 and VT320 emulation, but i haven't tried all our terminal tricks yet to see if it can do the job for 100%.

Once you start TeraTerm, don't forget to change in Setup->General the language to UTF-8,.

Setup -> Save Setup will save all your changes to a Teraterm.ini file so they will be in effect the next time.

Are you unable to POST anything, or are you looking for an easy way to construct JSON in 2012.1.4 ?

The class to POST something is %Net.HttpRequest, you need to send the form as a  stream.

In recent (2016.2 upward) versions, you can create a dynamic object and convert it to a JSON string, but 2012.1.4 is lacking this  JSON support,.

But you should still  be able to send a string in the body part formed (manually) as correct JSON :

    Set httprequest=##class(%Net.HttpRequest).%New()
    Set httprequest.Server="apitest.authorize.net"
    Set httprequest.Https=1
    Set httprequest.SSLConfiguration = "TEST"  ;make sure this SSL is created via mgmt security portal
    Do httprequest.EntityBody.Write("{""createTransactionRequest"":{""merchantAuthentication"":{""name"":""gfufet9QVgT5P"",""transactionKey"":""8pg6FJjxuekeY62m""},""refId"":""123456"",""transactionRequest"":{""transactionType"":""authCaptureTransaction"",""amount"":""5"",""payment"":{""creditCard"":{""cardNumber"":""5424000000000015"",""expirationDate"":""2020-12"",""cardCode"":""999""}}}}})")
    Do httprequest.Post("/xml/v1/request.api")
    Do httprequest.HttpResponse.OutputToDevice()