Enrico Parisi 路 Dec 18, 2023 go to post

Yeah, it has happened to me too, it seems WRC is not interested in fixing/reporting bugs when any sort of workaround is possible/available, like using a different class in this case.

The community is frequented by InterSystems product managers, developers, sales engineers and many other InterSystems people, maybe out of compassion will report it and will get it fixed, so maybe in IRIS 2026 we will see it fixed! 馃槀

Fixing this does not seems to be difficult, it's just  matter of filtering/checking the XData block  before (blindly) using it as JSON map.

I'm not holding my breath....

Enrico Parisi 路 Dec 18, 2023 go to post

It seems you cannot use ax XData block of "MimeType = application/json" within a class that extends %JSON.Adaptor.

Put your XData block in a different class that does not extends %JSON.Adaptor.

This may be a bug, (it looks so to me), you may want to report it to WRC.

Enrico

Enrico Parisi 路 Dec 17, 2023 go to post

Set sc=##class(%File).GetDirectorySpace("D:",.FreeSpace)

Write FreeSpace

Classreference:

classmethod GetDirectorySpace(Name As %String, ByRef FreeSpace As %String, ByRef TotalSpace As %String, Flag As %Integer = 1) as %Status
Return the amount of total space and free space in either Bytes,MB,GB on a drive or directory
Name = Valid Drive or directory specification
Flag = 0 - Return bytes
Flag = 1 - Return MB (Default)
Flag = 2 - Return GB

MB and GB returned are rounded to 2 decimal places.
Any error status returned is O/S level error. Note that on Windows only drives have a measurement for free space and directories can not so the FreeSpace is only returned for drives.

Enrico Parisi 路 Dec 16, 2023 go to post

@Julius Kavay , nice code.

But the point was "more efficiently than using a serialization/deserialization", with this code it takes more than 4 times as serialization/deserialization.

I think that using serialization/deserialization IS very efficient.

@Rodrigo Werneck , are you having performance issues? What makes you think serialization/deserialization is inefficient? Did you measure the performance in your use case?

Enrico

Enrico Parisi 路 Dec 15, 2023 go to post

Do you know the function name?

Do you need the *exact* function body (including comments, formatting etc.) or just the function code?

Enrico Parisi 路 Dec 14, 2023 go to post
set status = instance.OnProcessInput(classToPostHandler, .response)

You are not supposed to call the OnProcessInput() callback method directly, instead the ProcessInput() method should be called.

Sometime calling OnProcessInput() works, sometimes create problems.

Enrico

Enrico Parisi 路 Dec 14, 2023 go to post

Please note that "%PosixTime values have a 1 microsecond resolution", see %Library.PosixTime class reference documentation.

Then:
USER>set ts="2023-12-12 19:46:19.000"
 
USER>set Posix=##class(%Library.PosixTime).TimeStampToLogical(ts)
 
USER>write ##class(%Library.PosixTime).LogicalToTimeStamp(Posix-18000000000)
2023-12-12 14:46:19

Enrico

Enrico Parisi 路 Dec 14, 2023 go to post

Personally I usually prefer to assign permissions to Web Applications and assign to the users only the role necessary to use the application.

Often I don't need/want the user itself to have direct access to resources (i.e. database, tables//classes etc.), what I want is the ability for the user to access/use the Web Application (the FHIR server in this case), then the application itself has the required privilege.

In short, I don't what the user to be authorized to mess with the "internal" stuff...just use the application.

Of course this is a matter of preferences and use case scenario.

Enrico

Enrico Parisi 路 Dec 13, 2023 go to post

My guess is that the user does not have enough privilege (role/resource permissions) to access your FHIR server, maybe the database resource?

If so, you have two options:

1) add to the user the required role(s) with proper access to the required resource(s)
2) add to the Web Application the required role(s) with proper access to the required resource(s)

Personally I would prefer option 2.
Just for testing, try to temporary %All role to the Web Application and see if it works.

Enrico

Enrico Parisi 路 Dec 12, 2023 go to post

Using correct length of 16 characters for IV and 32 characters key.

This Javascript:

var iv CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
var stringyouWantToEncrypt "HelloWorld";
var base64Key "RXJjb2xpbm9zZW1wcmVpbnBpZWRpMDEyMzQ1Nzg5MDE=";
var encrypted CryptoJS.AES.encrypt(
    stringyouWantToEncrypt,
    CryptoJS.enc.Base64.parse(base64Key),
    {
        iv: iv,
    }
)

And this ObjectScript:

Set text="HelloWorld"
Set IV=$c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
Set KEY = "RXJjb2xpbm9zZW1wcmVpbnBpZWRpMDEyMzQ1Nzg5MDE="
Set KEY=$SYSTEM.Encryption.Base64Decode(KEY)
Set text=$ZCONVERT(text,"O","UTF8")
Set sCrypt=$SYSTEM.Encryption.AESCBCEncrypt(text,KEY,IV)
Set sToken=$SYSTEM.Encryption.Base64Encode(sCrypt)
Write !,!, "Encoded -> "_sToken

Both return the same:

Encoded -> 2s4qbUJC6romvsp7TP2L4A==

Enrico

Enrico Parisi 路 Dec 12, 2023 go to post

Ciao Barbara,

In your JS code:

var iv = CryptoJS.enc.Hex.parse("0000000000000000");

Convert the HEX sequence to a string, the resulting string made of 8 characters, all with ascii value of zero.
In AES, IV *must" be 16 characters long, I have no idea how your JS library handle this invalid value, IRIS correctly returns an error if IV is not 16 characters long.
The sample in the page you linked uses an IV made of 16 characters, converted from an HEX sequence.

In addition, you are passing to $SYSTEM.Encryption.AESCBCEncrypt() the KEY encoded in base64, in JS th base 64 KEY is decoded before use, so it should be:
Set sCrypt=$SYSTEM.Encryption.AESCBCEncrypt(text,$SYSTEM.Encryption.Base64Decode(KEY),IV)

Moreover, as Ralf pointed out, make sure the key is 16, 24, or 32 characters long

Ciao,
Enrico

Enrico Parisi 路 Dec 10, 2023 go to post

Excellent job Dan!
I believe this is going to be very helpful for the community.

This week I will be out for training a course, so I have limited time to try the sample.

Enrico

Enrico Parisi 路 Dec 10, 2023 go to post

Keep in mind that production CONFIG is stored in the database when the production class is compiled.

Enrico

Enrico Parisi 路 Dec 8, 2023 go to post

Use foreach action to loop DRGgrp() and inside the loop insert an if action to the check if = "PMP", use break action when found.

If you need more detail, provide a sample HL7 message and specify what you need to do after finding it.

Enrico

Enrico Parisi 路 Dec 8, 2023 go to post

Outstanding article, congratulations Kurro! 馃憦

Just one note on base64 conversion.
In fact you don't need to worry about the base64 conversion, all you need is to set ContentTransferEncoding to "base64" and then %Net.MIME* will take care of it, including adding the header "Content-Transfer-Encoding: base64" in the mime part header.

So, all you need is:

set content.ContentTransferEncoding = "base64"
set content.Body = pImage ; pImage is binary stream

Enrico

Enrico Parisi 路 Dec 8, 2023 go to post

Use foreach action to loop DRGgrp() and inside the loop insert the check.

Enrico

Enrico Parisi 路 Dec 7, 2023 go to post

I don't think you can implement it in a messaging routing rule.

Personally I would implement it using code, writing a Business Process class.

Another option is using a BPL business process, but I'm not a fan of BPL. But probably that's just me. 馃槉

Enrico

Enrico Parisi 路 Dec 7, 2023 go to post

I think to remember (I might be wrong) that Service Unavailable error can be caused by a license limit and using csp pages/application can consume license slots quickly due to the sessions not being cleared and license grace period.

Maybe you are using IRIS Community Edition (limited number of connections/license), if so, try to restart and see if it works right after restart.

You may also check in Management Portal in System Operation -> License usage

Again, I'm guessing! I might be wrong.

Enrico

Enrico Parisi 路 Dec 6, 2023 go to post

If you type in "Document.Orders.GetAt(1).ResultStatus", does it work?

If not, what error do you get?

Enrico

P.S.: what type of rule are you using?

Enrico Parisi 路 Dec 6, 2023 go to post

Is Document an instance of CDM.OrderResultMsg?

If so, then Document.Orders.GetAt(1).ResultStatus should work, if not, what error you get? What is assigned to Document?

Enrico

Enrico Parisi 路 Dec 6, 2023 go to post

I would create my "custom" datatype extending %Library.DateTime:

Class Community.dt.CustomDateTime Extends %Library.DateTime
{

ClassMethod LogicalToXSD(%val As %TimeStamp) As %String [ ServerOnly = 1 ]
{
    Set %val=##class(%Library.TimeStamp).LogicalToXSD(%val)
    Quit $translate(%val,"TZ"," ")
}

ClassMethod XSDToLogical(%val As %String) As %TimeStamp [ ServerOnly = 1 ]
{
    Set $e(%val,11)="T"
    Quit ##class(%Library.TimeStamp).XSDToLogical(%val)
}

}

Then in your class define your property as:

Property OPDT As Community.dt.CustomDateTime;

Are you sure you really need %Library.DateTime and not %Library.TimeStamp?
The difference is the JDBC/ODBC format. From the documetation:

%DateTime is the same as %TimeStamp (is a sub-class or %TimeStamp) with extra logic in the DisplayToLogical and OdbcToLogical methods to handle imprecise datetime input T-SQL applications are accustomed to.

If you prefer using %Library.TimeStamp, then change the superclass in my sample code.

After that:

USER>Set reader = ##class(%XML.Reader).%New()
 
USER>Set sc=reader.OpenString("<NewClass2><OPDT>2023-11-30 11:07:02</OPDT></NewClass2>")
 
USER>Do reader.CorrelateRoot("Samples.NewClass2")
 
USER>Do reader.Next(.ReturnObject,.sc)
 
USER>Do ReturnObject.XMLExport(,",indent")
<NewClass2>
  <OPDT>2023-11-30 11:07:02</OPDT>
</NewClass2>
 
USER>Write ReturnObject.OPDT
2023-11-30 11:07:02
USER>

Enrico

Enrico Parisi 路 Dec 5, 2023 go to post

You have setup your REST Web application "Allowed Authentication Method" as "Unauthenticated", therefore your REST code/application runs under the "UnknownUser" account/user.

My guess is that the UnknownUser user does not have enough privilege (Role(s)) to run your code.
If this is just a private, isolated test system, try adding %All role to the UnknownUser user account.

Enrico

Enrico Parisi 路 Dec 5, 2023 go to post

"CALL returns an empty result"

How did you determine that? After that 3 lines, run this:

For  {Set rset=sqlResult.%NextResult() q:rset=""  do rset.%Display() Write !}

I get:

1 Row Affected
1 Row Affected
1 Row Affected
1 Row Affected
name    age     home_city
Jorge   32      Tampa
Enrico  29      Turin
Dan     25      Miami
Alexy   21      London
 
4 Rows(s) Affected

You may want to check the documentation:

Returning Multiple Result Sets

Enrico

Enrico Parisi 路 Dec 5, 2023 go to post

I didn't realized you are still using Cach茅 2018! 馃槷

Add this to the, possibly long, list of good reasons to migrate to IRIS! 馃槈馃槉

Enrico

Enrico Parisi 路 Dec 5, 2023 go to post

What does sqlStatus contains?

Write $system.Status.GetErrorText(sqlStatus)

Enrico

Enrico Parisi 路 Dec 5, 2023 go to post

I don't have details of your project but when you say  "I want to use %SYSTEM.Event to process queues" and ask "Is there a way to store the queue with their messages in a Global?" I think that what you describe is exactly what an IRIS interoperability production does.

In fact, an IRIS interoperability production internally use %SYSTEM.Event to process queues and messages are indeed queued and persisted (in globals).
Within an IRIS interoperability production queued messages are preserved across system restart (and crash!), in addition messages are traced, can be resent etc etc.

So my question is, given your requirements, why not using an interoperability production instead of reinventing (or reimplementing) the wheel?

Enrico

Enrico Parisi 路 Dec 5, 2023 go to post

Hi Luis,

how can you possibly get a <MAXSTRING> error extracting a stream from a base64 encoded property that is imported from a JSON string that is limited itself by the MAXSTRING value?

In the line:

set bodyJson = %request.Content.Read()

You get the whole JSON into a string limited to string max size.

To avoid this, you can import directly the content stream into a dynamic object:

set dynamicBody = {}.%FromJSON(%request.Content)

Enrico