@Armin Gayl   The answer depends a lot on background.  If you are a team experienced with Cache then you are probably already comfortable with Studio.  Studio is stable and works well with InterSystems products.  If you are primarily a Windows environment, working primarily with Cache/IRIS classes and objectscript,  staying with this IDE is fine.

On the other hand if you:

  1. work across platforms (windows, linux, mac) OR
  2. want to easily integrate source control OR
  3. need to program in multiple languages and/or different components (docker, angular cli, ...) OR
  4. need to attract new talent OR

If any of the above is true I would recommend VSCode with the Objectscript plug-in.  Why?

  • mutli-platform (I work with a Linux desktop so this we important to me)
  • easy source control integrations
  • much more resource friendly than Eclipse which I found to be a resource hog
  • plug-ins just seem to work better.  Example the docker plugin(s) on Eclipse were a disaster.  The one I have on VSCode is great
  • Well accepted in the market

Let my delve into point 4 above and the previous last bullet point as I think this gets overlooked or considered unimportant to the IDE question because "they have to learn a new language (objectscript) anyway".   My opinion is that the issue of learning a new language is really overstated.   Any programmer today can't even get out of bed without knowing several development languages.   The real problem is HOW you work with those languages.  In other words the IDE.    If you can bring in someone that is already familiar with how to work with the IDE and the general workflow, which is similar regardless of language, then you remove one barrier to entry.  Now it becomes learning just another scripting language with is a process that new developers are used to.

VSCode is quite popular and is trending up.  I participated in a Hackathon with InterSystems several months ago.  In the end there were 70 teams that submitted projects.  Figure an average of 3 people on a team as a rough estimate.  Every single developer that we interacted with was using VSCode.    This, along with some great templates from @Evgeny Shvarov , made it easy for them to get working with IRIS.  In fact something like 12 teams used IRIS including the second place team (the first place team's solution was related to a process where they were forbidden by law from storing any data).

So that's my $0.02.  I would stay with Studio if that is your comfort zone and work primarily within InterSystems technology.  If not go with Visual Studio Code.  I would not consider Eclipse for many of the reasons others have stated and because it is really resource heavy.

Robert,

The cause is that fact that Desktop Docker (Docker for Windows) is a bit of a miss-leading.  This is not really using Windows containers at all by default, though it can.  From what I understand, while it is getting better, true Windows containers are still a bit problematic.  Also all our images are Ubuntu based anyway.  What is really happening is that there is a small Linux (Moby) vm running under Desktop Docker.  So when you share volumes from the windows file system to the container you are going through two transitions.  One from the Container to the Host Linux then from the Host Linux out to windows.   While this works for just Docker volumes, there are issues when trying to do Durable %SYS around permissions as you surmised.   I have heard of people getting into the Moby Linux environment and messing with the permissions, but this seems too much trouble and too fragile for my tastes.

You do have some options though.

  1. A better option might be to use WSL2 (Windows Sub-system for Linux).  This will enable you to run an Ubuntu environment within Windows.  You do need to be on WSL2 and not the first version which as too limited.  Here are a couple of links: https://code.visualstudio.com/blogs/2020/03/02/docker-in-wsl2https://www.hanselman.com/blog/HowToSetUpDockerWithinWindowsSystemForLinuxWSL2OnWindows10.aspx  
  2. you could just run a Linux VM  
  3. You could go with the nuclear option and just switch to Linux as a Desktop.  I took this route over a year ago, before WSL2 came out, and have not looked back.

Hope this helps.

Kevin,

The  best option is to work with  IRIS for Health Community Edition which is free for development and education.  You can get this from either Docker as a container you can use on your system or on AWS, Azure, or GCP if you want to work in the cloud.  AWS, at least, has a free tier that is good for 750 hours a month up to a year.  This is more than adequate for education and simple development.  I have used this for demos for a time.

https://hub.docker.com/_/intersystems-iris-for-health
https://aws.amazon.com/marketplace/pp/B07N87JLMW?qid=1587469562959&sr=0-3&ref_=srh_res_product_title
https://azuremarketplace.microsoft.com/en-us/marketplace/apps/intersystems.intersystems-iris-health-community?tab=Overview
https://console.cloud.google.com/marketplace/details/intersystems-launcher/intersystems-iris-health-community-edition?filter=category:database&filter=price:free&id=31edacf5-553a-4762-9efc-6a4272c5a13c&pli=1
 

if you follow the link in the top bar for 'Learning'  you will find many education resources including some quick start topics on IRIS.  And, of course, you can ask questions here.

Damiano,

Keep in mind that Studio is VERY namespace centric.  A single running instance of CStudio can only talk to a single namespace at a time. Even running multiple copies of CStudio can run into issues related to this and how projects track the information.

As Dmitriy Maslennikov has indicated you can look at Visual Studio code with the VSCode-ObjectScript plug-in as long as you are on Cache 2016.2+ or IRIS.  You can also use the Atelier plugin for Eclipse (Photon version only) which has much the same capabilities.

One last thought is why you have two namespaces?  If this is just to separate the code from the application data then you really don't need two namespaces.  You need to configure a single namespace to reference the two databases, one for data and one for code.  I would review the documentation for Namespace to be sure you are on the right track.

https://cedocs.intersystems.com/ens201813/csp/docbook/DocBook.UI.Page.cls?KEY=GSA_config#GSA_config_namespace
 

I would also encourage you to engage with your sales engineer to review your architecture and development direction.

If you used package mapping you may have forgotten to map the global too.  Examine the class definition to find the global name to map.  If you map the class, but not the global you are getting the code of the class, but the storage would be local.  This allows the sharing of definitions across namespaces without sharing the data.  Add the global mapping to share the data too.

Dmitry,

The method of logging to a global was primarily to match the original use case.  Having a full class for logging including indexes would be a better option.

However, my personal belief is that suspending transactions, or even worse stopping and starting  journaling,  is not really a good option.  Even if the actually coding does not appear to be complex there is the potential for reach beyond the current transaction if you don't cover all bases.  Holding the logs in a temporary global that then gets written out after the transaction insures that the application logic is intact.  You could even encapsulate this functionality in classmethods.  If there is any failure the impact would be on the logging and not the actual logic of the transaction.

Not if we could perform an update/insert/save that could be intentionally and deliberately excluded from the transaction OR if the suspend was only for the current transaction so no lasting impact was even possible then I would feel more comfortable with that approach.

I will add that this is a matter of design and the programmer's approach.  Either method works the decision is where you wish to have any risk, no matter how small that risk is.  My preference is to be absolutely sure the integrity of the transaction  is maintained over the logging.

First let me state for clarity that the life of a transaction should be short.  That is a single logical transaction to the application.  I have seen cases where an entire batch update was treated as a single transaction.  This can create many problems that are not easy to diagnose.

I also agree with Fabian that suspending transactions is a path that can lead to complexity in the code that it best to avoiding.  The nature of a transaction is to track EVERYTHING that happens in the transaction.  Messing with that will lead to issues with maintainability and debugging later in the life of the application.

My suggestion is to do your logging to an in-memory global while in the transaction.  Then you can permanently write this after the transction commits or rolls back.   Two things to be sure of in this method: 

  1. always explicitly commit or rollback the transaction.   Don't rely on implied rollback that would occur from a process end
  2. enclose your transaction in a try/catch block.  This will insure that you have the opportunity to commit your logs in the case of a system fault.  This could be an existing try/catch in the program.  However for control and clarity I recommend a separate try/catch for the transaction.

How you commit your log updates will depend on your error handling.  I this example the logs are committed in two places, after a tcommit and in the catch block since the catch block will throw the exception up the stack.  If this did not occur then a simpler approach would be to write the logs out after the catch block.  

Example (just typed it here for example.  Not a running program) with exception passed up the stack

Try {
    set ^LOG($Increment(^LOG)) = "starting a transaction"
    TSTART
    // do some program logic
    // do some logging
    set tLog($Increment(^LOG)) = "some application trace" // note using the still using he ^LOG increment
    
    // if application error
    throw ##class(%Exception.StatusException).CreateFromStatus(tSC)

    TCOMMIT
    Merge ^LOG = tLog
} catch except {
    TROLLBACK
    Merge ^LOG = tLog
    Throw except
}
 

Example with internal error handling only

Try {
    set ^LOG($Increment(^LOG)) = "starting a transaction"
    TSTART
    // do some program logic
    // do some logging
    set tLog($Increment(^LOG)) = "some application trace" // note using the still using he ^LOG increment
    
    // if application error
    throw ##class(%Exception.StatusException).CreateFromStatus(tSC)

    TCOMMIT
} catch except {
    TROLLBACK
}
Merge ^LOG = tLog
 

Murray,

This looks great.  However I am having a problem getting this to work with a recent pButtons report I received.  The error is a follows.  Any thoughts?

docker container run --rm -v "$(pwd)":/data yape/yape --mgstat --vmstat -c /data/dbmirror2-c_CACHE_20190131_161057_24hours.html
INFO:root:Profile run "24hours" started at 16:10:57 on Jan 31 19.
Traceback (most recent call last):
  File "/usr/local/bin/yape", line 11, in <module>
    load_entry_point('yape', 'console_scripts', 'yape')()
  File "/src/yape/yape/command_line.py", line 6, in main
    yape.yape2()
  File "/src/yape/yape/main.py", line 248, in yape2
    parsepbuttons(args.pButtons_file_name, db)
  File "/src/yape/yape/parsepbuttons.py", line 382, in parsepbuttons
    StartDateStr = datetime.strptime(StartDateStr, "%b %d %Y").strftime(
  File "/usr/local/lib/python3.7/_strptime.py", line 577, in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
  File "/usr/local/lib/python3.7/_strptime.py", line 359, in _strptime
    (data_string, format))
ValueError: time data 'Jan 31 19' does not match format '%b %d %Y'
 

If that is the case you can use BPL to create a business process with greater control over the orchestration.  You would set it up so that it  sends to each end point synchronously so that the first send has to happen before the second.  Of course if this were the case then the receiving side, with separate end points, would have to be sure that the messages stayed in order.  That is out of your control however.

Well one thing is to be sure that the external database implements a FHIR server and that you have the necessary access information and credentials.   They have to be able to accept the REST call per the FHIR standard.  If this is not in place all is not lost.  You can still use other methods access the external database, the method depends on what options are provided.  You just could not use FHIR.

BTW, if I understand you correctly Health Connect would be acting as a FHIR client in this usage, not a server.

Edrian,

You state that Request.JSON is a simple string.  The %ToJSON() method only exists as part of the DynamicObject and DynamicArray classes.  Actually I am surprised that this is not failing completely before you even send the request because of this.  If your variable already has well formed JSON as the value then you can just write that into the EntityBody.

BTW, When you deal with JSON in the future you may find an advantage in using the Dynamic object handling for JSON.  For example take the following JSON {"NAME":"RICH","STATE":"MA"}

If this is in a variable, say jsonStr, I can load this into a Dynamic Object using the following command:

set obj = {}.%FromJSON(jsonStr)

Now you can use object references to work with the JSON

Write obj.NAME   -> displays RICH

I can add new properties dynamically

set obj.ZIPCODE = "99999"

Finally convert this back to a json string with:

write obj.%ToJSON()

which would display  {"NAME":"RICH","STATE":"MA","ZIPCODE":"99999"}

See the documentation at https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GJSON_preface

I find the easiest way is to log into the CSP Gateway for the web server you are using.  If this is a development machine and you are using the stripped down web server internal to Cache you can access this from the management portal.  The path is System Adminstration -> Configuration -> CSP Gateway Management.  If you looking to do this against the traffic on an external web server then you need to the path to the Module.xxx.  On my Windows VM this is http://192.168.x.xxx/csp/bin/Systems/Module.cxw.

You will need the Web Gateway Management username and password.  The user is typically CSPSystem.  Once logged in look for the View HTTP Trace on the left hand menu.

Click on that and you will see a screen with 'Trace OFF' and 'Trace ON' at the top of the left hand menu.  You will also see options to refresh and clear.  Below that will appear any requests that have been traced. This is probably blank at this time.  Click Trace ON (it should change to RED.  Now go make a request that you want to trace.  Once your request is complete go back and turn off the trace so you don't get a bunch of requests that have nothing to do with what you want to examine.  I did this and made a request for the System Management Portal.  Here is the list I get.

Note that I see two requests.  Only one is what I want to look at which, in my case is the first.  When you select a trace you will see the request a the top followed by the response.  Note if the body of the response is not readable you likely have gzip compression on.  Go to the Application settings in the web gateway and turn this off to actually be able to see the body.  Remember to turn it back on later though.

Here is my results (truncated).  Hope this helps you