Eduard Lebedyuk · Mar 15, 2021 go to post

OnHandleCorsRequest is called automatically if a browser requests CORS.

To add to original answer a bit:

Do %response.SetHeader("Access-Control-Allow-Origin","*")

This is OK for development but for production use you need to replace * with a hostname of your web site.

Eduard Lebedyuk · Mar 9, 2021 go to post

You probably have a mismatched brackets somewhere.

You can also try

[].%FromJSON

instead of

{}.%FromJSON
Eduard Lebedyuk · Mar 9, 2021 go to post

If you're sure that there's only one object in response array, replace:

Set tSC = pResponse.%JSONImport(tHttpResponse.Data.Read())

with:

Set tSC = pResponse.%JSONImport({}.%FromJSON(tHttpResponse.Data).%Get(0)) 

It would parse your JSON stream into a dynamic JSON array (via {}.%FromJSON(tHttpResponse.Data)), get zeroth element from it (via %Get(0)), and pass it for JSON import (via pResponse.%JSONImport).

Eduard Lebedyuk · Mar 9, 2021 go to post

If you're sure that there's only one object in response, replace:

Set tSC = pResponse.%JSONImport(tHttpResponse.Data.Read())

with:

Set tSC = pResponse.%JSONImport({}.%FromJSON(tHttpResponse.Data).%Get(0)) 

If you want to parse an entire array, you'll need another class:

Class CDSM.ProviderAPI.Responses Extends (%Persistent, %JSON.Adaptor) {

Property Responses As List Of CDSM.ProviderAPI.ProviderInfo;

}

And in this case replace this code:

Set pResponse=##class(CDSM.ProviderAPI.Response).%New()
Set tSC = pResponse.%JSONImport(tHttpResponse.Data.Read())

With:

Set pResponse=##class(CDSM.ProviderAPI.Responses).%New()
Set tSC = pResponse.%JSONImport(tHttpResponse.Data)

and update the method signature too.

Eduard Lebedyuk · Mar 9, 2021 go to post

Why would be better or recommended to use %CSP.REST directly, instead of EnsLib.REST.Service?

To start with using %CSP.REST is the recommended way to use REST with productions.

Are there any improvements if we use %CSP.REST?

It's easier to develop, there are more examples available, you can have a combined production/non-production REST services easily.

Eduard Lebedyuk · Mar 9, 2021 go to post

The first, but not the last one, so still not getting the idea of having this intermediate upgrade point.

Sure, but you can start freezing on 2016.2. There's no point in freezing if you jump to latest version from pre 2016.2

Sorry, on which topic? Everyone knows that Cache/IRIS never runs on an unsupported OS.

Upgrade path between Cache/IRIS versions where OS for old and new Cache/IRIS versions must be different.

Eduard Lebedyuk · Mar 8, 2021 go to post

Yes, check my other reply, I get the zeroth element from the JSON array with %Get(0).

Also both [] and {} are valid JSON.

Eduard Lebedyuk · Mar 8, 2021 go to post

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.

Eduard Lebedyuk · Mar 8, 2021 go to post

Cache 2015 is a very old release. You should update to a latest version at least, preferably to InterSystems IRIS.

Eduard Lebedyuk · Mar 8, 2021 go to post

upgrade to 2016.2

What is the reason of this step?

This is a first version with Frozen Plans. If this feature is not needed then upgrade to 2018.1 directly (provided OS compatibility - you're absolutely right about it).

Cache 2017.2 (our App's supported version) turned to be incompatible with Ubuntu 18, which was chosen as on OS for IRIS.

What's the official way to upgrade in that case? I usually just power down an instance, remove it from autostart, upgrade OS to the version supported by a new release, upgrade instance to a new version.

This way Cache/IRIS never runs on unsupported OS. Do you have a case with WRC on this topic?

Eduard Lebedyuk · Mar 8, 2021 go to post

Yeah I've merged intersystemscommunity org into intersystemsdc recently.

Great to see it used!

Eduard Lebedyuk · Mar 7, 2021 go to post

Another minor thing:

RESTForms2 link links to localhost and /restforms2-ui/index.html#/

Eduard Lebedyuk · Mar 6, 2021 go to post

I would also recommend rewriting this property:

Property "cdsm_Physician_Issue_ID" As %String;

like this:

Property physicianIssueID As %String(%JSONFIELDNAME = "cdsm_Physician_Issue_ID");

This way JSON would still be imported, but you would be able to refer to property name without double quotes.

Eduard Lebedyuk · Mar 6, 2021 go to post

Get 0th array element from your array:

Class test.Provider Extends (%RegisteredObject, %JSON.Adaptor)
{

Property physicianFirstName As %String;

Property physicianLastName As %String;

Property physicianMiddleNameInitial As %String;

Property physicianSpecialty As %String;

Property physicianNPI As %String;

Property physicianMPIN As %String;

Property physicianTaxID As %String;

Property physicianADRId As %String;

Property physicianAddressLine1 As %String;

Property physicianCity As %String;

Property physicianState As %String;

Property physicianZip As %String;

Property physicianZipPlus4 As %String;

Property physicianPhone As %String;

Property facilityNPI As %String;

Property facilityAddressLine1 As %String;

Property facilityCity As %String;

Property facilityState As %String;

Property facilityZip As %String;

Property error As %String(MAXLEN = 200);

Property "cdsm_Physician_Issue_ID" As %String;

ClassMethod GetJSON() [ CodeMode = expression ]
{
[
    {
        "physicianFirstName": "STEVENSON",
        "physicianLastName": "HOWARD",
        "physicianMiddleNameInitial": "W",
        "physicianSpecialty": "null",
        "physicianNPI": "null",
        "physicianMPIN": "null",
        "physicianTaxID": "null",
        "physicianADRId": "null",
        "physicianAddressLine1": "null",
        "physicianCity": "null",
        "physicianState": "null",
        "physicianZip": "null",
        "physicianZipPlus4": "null",
        "physicianPhone": "null",
        "facilityNPI": "null",
        "facilityAddressLine1": "\"\"",
        "facilityCity": "\"\"",
        "facilityState": "\"\"",
        "facilityZip": "\"\"",
        "error": "Invalid NPI. Requested NPI should contain 10 numeric digits",
        "cdsm_Physician_Issue_ID": "null"
    }
]
}

/// do ##class(test.Provider).Test()
ClassMethod Test()
{
    set json = ..GetJSON()
    
    set obj = ..%New()
    set sc = obj.%JSONImport(json.%Get(0))
    
    zw sc,obj
}

}
Eduard Lebedyuk · Mar 6, 2021 go to post

%ZEN.Auxiliary.jsonProvider class and %ConvertJSONToObject method are definitely available in 2018.1. They are available on way older versions - 2014.1 at least and probably older.

That said, in 2018.1 it would be better to use %ZEN.Auxiliary.altJSONProvider - it has the same methods but uses dynamic objects instead of %ZEN.proxyObject which is faster.

Eduard Lebedyuk · Mar 5, 2021 go to post

First of all I would recommend reading these two documents available on WRC (Software Distribution - Docs):

  • InterSystems IRIS Adoption Guide
  • InterSystems IRIS In Place Conversion Guide

First one explains the differences between Cache and InterSystems IRIS and the second one is about automated in-place conversion from Cache to InterSystems IRIS.

I would recommend the following steps:

  • upgrade to 2016.2
    • This is the place to uplift your application - on the one hand it's still Cache so upgrade is simple, on the other the code, even with the new 2016.2 features would probably run fine on InterSystems IRIS
    • if you're using SQL - start using frozen plans
    • if you're using JSON - new JSON features become available here (dynamic objects)
  • upgrade to 2018.1 (latest micro)
  • perform in-place conversion to the latest InterSystems IRIS
Eduard Lebedyuk · Mar 3, 2021 go to post

The comments talk about modifying a setting too.

In general you need to open a corresponding Ens.Config.Item, adjust settings properties and save it. And activate changes in production of course.

Here's an example.