Eduard Lebedyuk · Jun 12, 2017 go to post

To get user/pass? Sure:

set sc = #class(Ens.Config.Credentials).GetCredentialsObj(.cred, "caller.class", "Ens.Config.Credentials", "CredentialsId")
write cred.Username
write cred.PasswordGet()
Eduard Lebedyuk · Jun 9, 2017 go to post

I'd start without base64 decode just to check how ftp works.

I think this would be enough to work (1st argument in Store is a full filename and second is a stream you want to put there):

ClassMethod DecodeBase64HL7ToFileFaxing(base64 As %Stream.GlobalBinary, Ancillary As %String, FileName As %String) As %String
{
    set ftp=##class(%Net.FtpSession).%New()
    if 'ftp.Connect("xxxxx","xxxxx","xxxxxx") $$$LOGINFO("Unable to connect to inteng11")
    if 'ftp.Store(FileName, base64) $$$LOGINFO("Unable to write file")
    if 'ftp.Logout() $$$LOGINFO("Failed to logout")
    quit $$$OK
}
Eduard Lebedyuk · Jun 7, 2017 go to post

Cool!

Currently all the classes are in one folder (and as there's 6 classes currently, that's ok), but is there any reason not to separate them further into folders by package?

Eduard Lebedyuk · Jun 2, 2017 go to post

Here's how you can define your own errors.

Create messages.xml with your error messages:

<?xml version="1.0" encoding="UTF-8"?>
<MsgFile Language="en">
    <MsgDomain Domain="asd">
        <Message Id="-1" Name="ErrorName1">Your error 1</Message>
        <Message Id="-2" Name="ErrorName2">Some other error 2 %1 %2</Message>
    </MsgDomain>
</MsgFile>

Import it into Cache:

do ##class(%MessageDictionary).Import("messages.xml")

It will result in two globals being populated:

  • ^CacheMsg
USER>zw ^CacheMsg 
^CacheMsg("asd","ru",-2)="Some other error 2" 
^CacheMsg("asd","ru",-1)="Your error 1"
  •   ^CacheMsgNames
USER>zw ^CacheMsgNames 
^CacheMsgNames("asd",-2)="ErrorName2" 
^CacheMsgNames("asd",-1)="ErrorName1"

Next we generate CustomErrors include file (docs):

USER>Do ##class(%MessageDictionary).GenerateInclude("CustomErrors",,"asd",1) 
Generating CustomErrors.INC ...

Here's what CustomErrors.inc looks like:

#define asdErrorName2 "<asd>-2"
#define asdErrorName1 "<asd>-1"

Now we can use new custom errors:

Include CustomErrors

Class demo.test [ Abstract ]
{

ClassMethod test(A As %Integer) As %Status
{
  if A=1 Quit $$$ERROR($$$asdErrorName1)
  if A=2 Quit $$$ERROR($$$asdErrorName2,"f","6")
  Quit $$$OK
}

}

Results in:

USER>d $system.OBJ.DisplayError(##class(demo.test).test(1))

ERROR <asd>-1: Your error 1

USER>d $system.OBJ.DisplayError(##class(demo.test).test(2))

ERROR <asd>-2: Some other error 2 f 6

Text is not mine, translated from here.

Eduard Lebedyuk · Jun 1, 2017 go to post

Here's a very simple Ensemble REST service. That said, I recommend usual %CSP.REST broker  with calls to Ensemble via Ens.Director:CreateBusinessService. Check Demo.ZenService.Zen.WeatherReportForm class, GetWeatherReport method in ENSDEMO namespace for an example.

Eduard Lebedyuk · Jun 1, 2017 go to post

Check %ZEN.Auxiliary.altJSONProvider class, %UnpackObjectToCOSObjectmethod, it converts dynamic object to the specified class.

Set dynamicObject = {}.%FromJSON(%request.Content)
Set object = ##class(%ZEN.Auxiliary.altJSONProvider).%UnpackObjectToCOSObject(dynamicObject, "class")
Eduard Lebedyuk · May 31, 2017 go to post

Compare "Enabled ciphersuites" property in your SSL/TLS configuration.

But you'll probably need a longer key.

Eduard Lebedyuk · May 30, 2017 go to post

They are stored as objects of Ens.Config.DefaultSettings class.

You can:

  • Export the ^Ens.Config.DefaultSettingsD global
  • Export Ens_Config.DefaultSettings table contents to CSV, etc.
  • Export settings as objects to XML
Eduard Lebedyuk · May 29, 2017 go to post

If you store data in globals, you can run parallel jobs on your data.

On a single job however, locals are faster because there's no journaling and disk writes.

Eduard Lebedyuk · May 26, 2017 go to post

%OnAddToSaveSet() can get called many times during modification or saving of our target object and all objects related to it. Therefore it's better to move code we need to execute once to triggers or initialexpression or sqlcomputed.

Eduard Lebedyuk · May 26, 2017 go to post

Please note that It's not recommended to use %OnAddToSaveSet(), especially performing heavy operations there.

Eduard Lebedyuk · May 24, 2017 go to post

Like this:

set p = ##class(%SYS.ProcessQuery).%OpenId($job)
set p.UserInfo = "My Text"
kill p