go to post Jeffrey Drumm · Jul 4, 2023 Do you actually want the logic to check for the specific fields in the service itself? A Business Process with a rule can do this, and would be a bit more "analyst friendly." Here's a very bare-bones method to send email from within a custom Business Service: Class User.Mail Extends %RegisteredObject { Property MailServer As %String [ InitialExpression = "hostname@domainname" ]; Property FromAddress As %String [ InitialExpression = "fromaddress@domainname" ]; Property EmailCreds As %String [ InitialExpression = "SMTPServer" ]; Method Send(pToAddress As %String, pSubject As %String, pBody As %String = "") As %Status { Set tEmail = ##class(%Net.SMTP).%New() If pEmailCreds '= "" { #dim tCred As Ens.Config.Credentials Set tSC = ##class(Ens.Config.Credentials).GetCredentialsObj(.tCred,$CLASSNAME(),"Ens.Config.Credentials",..EmailCreds) Return:$$$ISERR(tSC) tSC Set tAuth = ##class(%Net.Authenticator).%New() Set tAuth.UserName = tCred.Username Set tAuth.Password = tCred.PasswordGet() Set tEmail.authenticator = tAuth } Set tEmail.smtpserver = ..MailServer Set tEmail.timezone="LOCAL" Set tMsg = ##class(%Net.MailMessage).%New() Set tMsg.From = ..FromAddress Do tMsg.To.Insert(pToAddress) Set tMsg.Subject = pSubject Set tMsg.Charset = "utf-8" Do tMsg.TextData.Write(pBody) Return tEmail.Send(tMsg) } } You can set the properties in the class to represent default values for your organization. Otherwise, you would call it like so: Set tMail=##class(User.Mail).%New() Set tMail.MailServer = "smtpserver.mydomain.com" Set tMail.FromAddress = "healthshare@mydomain.com" Set tMail.EmailCreds = "SMTPServer" Set tSC = tMail.Send("user@mydomain.com","This Thing Happened","And Here's what it is") You will need to obtain access to an SMTP relay host; HealthShare does not supply one. There will also be adjustments required for the class if encryption is required, and if you need to supply credentials for authentication to the SMTP server, you will need to create a Credentials entry in the Management Console and supply its name for the EmailCreds property.
go to post Jeffrey Drumm · Jul 3, 2023 Is there more to this than just disabling the web application? That simply causes the "Open" button in the Business Rules List or Business Process to display an authentication page, which does not allow one to log on. Until the new rules editor is sorted, it would be nice not to require extra steps each time a rule needs editing. EDIT: Oops ... disabled the wrong service (/api/interop-editors). Disabling the right service (/ui/interop/rule-editor) does the job.
go to post Jeffrey Drumm · Jul 3, 2023 Do you need a local installation of the database itself on these machines or just the client tools (system tray launcher, Studio, terminal, etc.). If the latter, you can install the latest version of the client kit rather than 2017. The tools are backwards compatible to at least 2015, and likely earlier.
go to post Jeffrey Drumm · Jun 20, 2023 The RecordMap services have options for handling errors: I'm not sure whether they do actual datatype validation on fields in the RecordMap (wouldn't make much sense to let you specify datatypes without supporting validation though). But if your extra field didn't trigger some sort of warning or error in the Event Log 🤷♂️
go to post Jeffrey Drumm · Jun 1, 2023 @Eduard Lebedyuk is correct (yeah, he's always correct 😁), you can't use a variable for the target in a business rule. You can do this in a custom BP (COS or Python) or a BPL-based BP, though. The BPL <call> action specifically supports a context variable as a destination: The variable would be assigned the name of the BH to send to prior to invoking the call.
go to post Jeffrey Drumm · May 31, 2023 It's not clear from your post whether you're using any of the healthcare-related variants of the InterSystems suite. If you're using HealthShare, Health Connect or IRIS for Health, support is included for receiving HL7 messages and storing them via multiple mechanisms. TCP/IP MLLP, HTTP, and file based services are all supported natively. When configuring a Business Service to receive HL7 messages via TCP/IP MLLP, you would select the EnsLib.HL7.Service.TCPService class and configure the Message Schema Category to "2.5" or "2.5.1" depending on your specific HL7 version. You would also need to configure the port on which to receive the messages, the target Business Process or Operation to act on them, and possibly a few other settings. Messages received through that service will then be inserted into the Interoperability message store, regardless of HL7 message type; message headers are created to provide tracking/status information and the messages are databased. If your need is to index and retrieve those messages based on content (patient name, account number, gender, etc), there are additional steps to fetch the specific data elements needed from the messages themselves and populate associated fields in a database structure that addresses those needs. That's something you would need to design; you would populate it using interoperability production components tailored to your filtering requirements and database design.
go to post Jeffrey Drumm · May 26, 2023 In addition to checking the logs, you can configure ^MONMGR and you'll get emailed on a failover (or any other significant Caché/IRIS event). There's also ^%SYSMONMGR for notifications on other Caché/IRIS system-health events.
go to post Jeffrey Drumm · May 23, 2023 I think in some cases questions are simply seeds planted for the growth of stimulating exchanges of ideas. This is a topic I would find interesting, and I'm no newbie, nor am I an ISC employee. If the answers to this question don't interest you, there are other questions that can use your help 😉
go to post Jeffrey Drumm · May 22, 2023 Can you try the code I posted above, substituting appropriate paths/filenames in the calls to the LinkToFile() methods? Any file will do for the in stream, as long as file/directory permissions permit. This at least would tell us whether the issue is with the key file or the JWT you're attempting to encrypt. I've tried this on I4H 2023.1 and Health Connect 2021.1.2 and the RSASHASign() method has not failed to generate a signature unless the key was passphrase-protected or not readable (due to file ownership/permissions) by the process opening it.
go to post Jeffrey Drumm · May 22, 2023 Password-protecting the key won't prevent it from being read. Do you have access to openssl? If yes, try the following: $ openssl rsa -in <keyfile-name> -check -noout You should get "RSA key ok" if it's a good key and has no passphrase.
go to post Jeffrey Drumm · May 22, 2023 Is your key file passphrase-protected? I get the output you describe when the key is passphrase-protected and the passphrase is not supplied.
go to post Jeffrey Drumm · May 22, 2023 I just tried RSASHASign() myself and a signature was returned, using your call: Set in=##class(%Stream.FileCharacter).%New() Do in.LinkToFile("/home/jeff/sample.jwt") Set token=in.Read() Set key=##class(%Stream.FileCharacter).%New() Do key.LinkToFile("/home/jeff/sample.pem") Set secret=key.Read() Set sig=##class(%SYSTEM.Encryption).RSASHASign(512,token,secret) The return value will be the signature only, though, not a signed JWT. If you want the latter, see the ObjectToJWT() method in %OAuth2.JWT - InterSystems IRIS for Health 2021.1.
go to post Jeffrey Drumm · May 22, 2023 I believe your argument list is incorrect. The first argument should be a string containing the data to be signed. The second is the private key, also in the form of a string. If the key is passphrase-protected, the third argument should be a string containing the passphrase. SHA-1 is deprecated, by the way.
go to post Jeffrey Drumm · May 20, 2023 The reason this 2-year-old thread floated to the top is because I found it researching an issue I had encountered with EnsLib.HTTP.GenericService.. I wanted to "pass through" a status code I had set as a property of a response message in a business process. While a solution was buried in the thread, the OP claimed it did not work in his case. I'm not sure why; I used a slight variation of that solution with success and simply felt the variation was worth sharing.
go to post Jeffrey Drumm · May 20, 2023 Just in case someone stumbles into this thread looking for an answer (as I did) ... Assuming the vanilla, un-extended EnsLib.HTTP.GenericService is the service handling the request, any response it receives from a business process needs to be an EnsLib.HTTP.GenericMessage. %Net.HttpResponse is not needed, nor is a CSP layer required. The service requires that a stream is attached to the message; the stream doesn't need to contain anything. The response message is composed in the BP something like this: Set rstream = ##class(%Stream.GlobalCharacter).%New() // Optional body content Do rstream.Write("<HTML><HEAD>Uh oh.</HEAD><BODY><BR><STRONG>Error: Invalid Patient ID</STRONG></BODY></HTML>") // Provide a stream object, empty is fine Set response = ##class(EnsLib.HTTP.GenericMessage).%New(rstream) // This works as expected in I4H 2023.1 Do response.HTTPHeaders.SetAt("HTTP/1.1 400 Bad Request","StatusLine") // if you're providing a payload ... Do response.HTTPHeaders.SetAt("text/html; charset=utf-8","Content-Type") I've verified that it works as coded above, using curl: < HTTP/1.1 400 Bad Request < Content-Type: text/html; charset=utf-8 < Content-Length: 99 < * Connection #0 to host iristest.local left intact <HTML><HEAD>Uh oh.</HEAD><BODY><BR><STRONG>Error: Invalid Patient ID</STRONG></BODY></HTML>
go to post Jeffrey Drumm · May 18, 2023 If the individual segment transformations are common across all ADT DTLs, you could implement your DTLs with subtransforms (these work at the segment level). As long as the gross structure of the messages rarely changes, the maintenance is all done in segment DTLs.
go to post Jeffrey Drumm · May 18, 2023 As you suggested, git is likely the culprit. It has an option for handling line-endings; see Configuring Git to handle line endings - GitHub Docs.
go to post Jeffrey Drumm · May 17, 2023 With #2 (at least for me anyway), the issue seems to be related to running iris session when using the Windows version of ssh.exe (called from VS Code, configured in settings under node terminal.integrated.profiles.windows). Home and End work normally at the Linux shell prompt, but when running iris session the effect is that either key produces the same result as pressing the Enter key. The current command is executed and a new IRIS prompt is generated. It doesn't seem to be a VS Code problem so much as an ISC problem, at least on Windows.
go to post Jeffrey Drumm · May 17, 2023 This should work (no looping required): I'm using the parenthesis syntax with the Matches() function to locate a pattern of any number of punctuation characters (.P) followed by 8 numeric characters (8N) followed by any number of any character (.E). The parenthesis syntax returns the repeating values in the form "<><><20230512191543><>" where <> represents an empty iteration of the repeating field (and fortunately qualifies as a punctuation character).
go to post Jeffrey Drumm · May 17, 2023 And an upgrade, since the foreach action didn't exist in 2017.2 😉