go to post Danny Wijnschenk · Aug 6, 2019 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 xecuteSet first = 1For 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 insteadSet call=call_$Select(json.%IsDefined(jsonProp):"$Property(json,"""_jsonProp_""")",1:"")Set first = 0}Set call=call_")"Xecute (call,json) //pass json as input parameter}}
go to post Danny Wijnschenk · Jul 26, 2019 Hi John,Can you show me your class definitions, because when i execute the second SQL on my classes and some random data, it will show the results i expect :(maybe you need to re-index your tables)
go to post Danny Wijnschenk · Jul 25, 2019 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;}
go to post Danny Wijnschenk · Jul 25, 2019 Hi Vitaliy,This is the same as 'write $SYSTEM.INetInfo.EthernetAddress(0)' in recent versions.As said we prefer to not use $zu anymore, but since availability of the helper classes depend on what version is used, $zu might be the only possibility unless they upgrade.
go to post Danny Wijnschenk · Jul 25, 2019 What version are you using and on what platform (Caché/Ensemble/Iris) ?
go to post Danny Wijnschenk · Jul 23, 2019 write $SYSTEM.INetInfo.EthernetAddress(0)Look at https://irisdocs.intersystems.com/irislatest/csp/documatic/%25CSP.Documatic.cls for more info.
go to post Danny Wijnschenk · Jul 16, 2019 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
go to post Danny Wijnschenk · Jul 16, 2019 Hi Jimmy,According to the comment of following article https://community.intersystems.com/post/how-call-rest-service-basic-authentication, you only need to set the credentials in Ensemble. Hope this will help.
go to post Danny Wijnschenk · Jul 15, 2019 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.
go to post Danny Wijnschenk · Jul 12, 2019 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.HttpResponseIf $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.StatusCodeWrite "Status : ",httpStatus,!Write "Response : ",json,!}
go to post Danny Wijnschenk · Jun 29, 2019 If i need one value, i use GetStored, if i need a few values, i use SQL, if i need a lot of them or need the references to other objects, I open the object instance.To open an instance and using only 1 property of a class with lots of properties is potentially slower than GetStored or SQL.
go to post Danny Wijnschenk · Jun 27, 2019 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.ORChange 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 !
go to post Danny Wijnschenk · Jun 26, 2019 You cannot pass an object (oref) as a parameter using Job.You have to save its properties to a variable/array and pass that, or save the object and pass its id.
go to post Danny Wijnschenk · Jun 25, 2019 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()::0USER> Write $TESTShould be 1 if the classmethod was started, 0 if the job timed out and did not startIn 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
go to post Danny Wijnschenk · Jun 7, 2019 Did you check if you have enough licenses available (e.g. Portal -> View system dashboard -> Highest License Use)You can also look at View Audit Database to see if there are any related messages
go to post Danny Wijnschenk · May 9, 2019 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.
go to post Danny Wijnschenk · Jan 20, 2019 We will finalize the agenda for the Caché User Group @BeneluxSymposium shortly.All questions or suggestions for demos or presentations you want to do are still welcome here or at CUG Benelux Blog
go to post Danny Wijnschenk · Sep 7, 2018 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()
go to post Danny Wijnschenk · Aug 21, 2018 Do you have a user with the %ALL Role to check if the problem is user-based, if that user cannot login either, it could be that some services are disabled.Again, you can know for sure by enabling auditing and look at the login failures.
go to post Danny Wijnschenk · Aug 16, 2018 If Caché Auditing is enabled, you can check the login failure messages to see if the problem is a disabled user or wrong username/password.(Auditing can be enabled in Caché portal -> system admin -> Security -> Auditing -> Enable Auditing.Use 'configure Auditing events' to enable Login Failure messages.