Eduard Lebedyuk · Apr 19, 2017 go to post

If you're running your SOAP service with a custom listener, specify SSLConfig setting for the ensemble business host (Should be in Connection category).

If you're running your SOAP service on the main web server, you should enable SSL for a web server. It's usually done by installing external web server and configuring SSL there.

Eduard Lebedyuk · Apr 19, 2017 go to post

After you receive base64 string decode it:

set text="Hello @"
set text = $zcvt(text, "O", "UTF8")
set base64text = $system.Encryption.Base64Encode(text)
wrile base64text
>SGVsbG8gQA==
set decoded = $system.Encryption.Base64Encode(base64text)
set decoded = $zcvt(text, "I", "UTF8")
write decoded
>Hello @
Eduard Lebedyuk · Apr 19, 2017 go to post

Great article, Fabio!

The problem can be that when data changes, then the whole record is copied, i.e. also data which does not change.

That can be solved by checking m%<property> value. It has false positives sometimes (when you change value back, i.e.: a-b-a) and calling log code only if property value has changed.

Forgot that it's only about object access. Still, you have old and new value, so:

Do %code.WriteLine($Char(9,9,9)_"Set tOldValue = {"_tProperty.SqlFieldName_"*O}")
Do %code.WriteLine($Char(9,9,9)_"Set tNewValue = {"_tProperty.SqlFieldName_"*N}")
Do %code.WriteLine($Char(9,9,9)_"if {" _ tProperty.SqlFieldName _ "*C},tOldValue'=tNewValue {")

 

All data changes are logged in a common table.

Why not generate a separate log table for each class, inheriting from logged class, so 1 change == 1 record in log table. It also gives you the possibility of writing "easy" diff tool, so audit results can be displayed conveniently.

If table person has a column "photo" with binary data (stream) containing the photography then each and every time yhe user changes the picture  the role stream is recorded (consuming disk space). 

That problem can be solved by creating immutable stream-containing class.

/// Immutable wrapper for stream
Class User.Document Extends %Persistent
{

/// Global identifier to give to user (prevent id traversal)
Property guid As %String [ InitialExpression = {$system.Util.CreateGUID()}, Required ];

/// Creation date time
Property createDateTime As %TimeStamp [ InitialExpression = {$ZDATETIME($ZTIMESTAMP, 3, 1, 3)};

/// File name as supplied by user (only for display purposes)
Property fileName As %String(MAXLEN =1000) [ Required ];

/// File stream
Property content As %FileBinaryStream;

/// User who uploaded the file
Property user As %String [ InitialExpression = {$username} ];

/// Add new stream
/// realName - real name of a stored file
/// suppliedName - name supplied by user, used only for display purposes
/// stream - stream with data
Method %OnNew(realName As %String = "", suppliedName As %String = "", stream As %Stream.Object = {##class(%FileBinaryStream).%New()}) As %Status [ Private, ServerOnly = 1 ]
{
    #dim sc As %Status = $$$OK
    set ..fileName = ##class(%File).GetFilename(suppliedName)
    set ..content.Filename = realName
    set sc = ..content.CopyFromAndSave(stream)
    quit sc
}

/// Serve file on web
Method serve() As %Status
{
    #dim sc As %Status = $$$OK
    #dim %response As %CSP.Response
    kill %request.Data
    set %request.Data("STREAMOID",1)= ##class(%CSP.StreamServer).Encrypt(..content.%Oid())
    if ##class(%CSP.StreamServer).OnPreHTTP() {
        set %response.Headers("Content-Disposition")="attachment; filename*=UTF-8''"_##class(%CSP.Page).EscapeURL(..fileName,"UTF8")
        set st = ##class(%CSP.StreamServer).OnPage()
    }

    quit sc
}

That way your audit log table would contain only id references.

Eduard Lebedyuk · Apr 19, 2017 go to post

Fixed the link to a correct article and I hadn't wrote about 7z problem even there. So here it is:

Document files (docx, xlsx, pptx) zipped with 7z on linux cannot be opened by Microsoft Office on Windows.

Eduard Lebedyuk · Apr 18, 2017 go to post

You can combine triggers and method generators into trigger generators like this:

Class User.Class1 Extends %Persistent
{

Property prop1 As %String;

Property prop2 As %String;

Trigger NewTrigger [ CodeMode = objectgenerator, Event = INSERT, Time = AFTER ]
{
    #dim class As %Dictionary.CompiledClass = %compiledclass
    set proplist = ""
    for i=1:1:class.Properties.Count() {
        #dim prop As %Dictionary.CompiledProperty = class.Properties.GetAt(i)
        if prop.Internal || prop.Calculated || prop.ReadOnly || prop.Private || prop.Identity || prop.MultiDimensional continue
        set proplist = proplist _ $lb(prop.Name)
    }
    
    do %code.WriteLine($$$TAB _ "set ^dbg($i(^dbg)) = $lb({" _$lts(proplist, "},{") _ "})")
    quit $$$OK
}

/// do ##class(User.Class1).Test()
ClassMethod Test()
{
    do ..%KillExtent()
    kill ^dbg
    
    &sql(INSERT INTO Class1 (prop1, prop2) Values ('Alice', 1))
    &sql(INSERT INTO Class1 (prop1, prop2) Values ('Bob'  , 2))
    zw ^dbg
}

Test:

do ##class(User.Class1).Test()
^dbg=2
^dbg(1)=$lb("Alice",1)
^dbg(2)=$lb("Bob",2)

Here's whats going on during compilation.

  1. Build list of all relevant properties and write them into proplist variable. 
  2. Generate trigger code:  set ^dbg($i(^dbg)) = $lb({prop1}, {prop2})

And at runtime only set ^dbg gets hit

That said I'd have automatically generated some log class and called method log there, passing all properties.

Some docs:

Eduard Lebedyuk · Apr 17, 2017 go to post

Just redefine the trigger with the same name in a child class:

Class FormsDev.NewClass1 Extends %Persistent
{

Property Name As %String;

Trigger Insert [ Event = INSERT ]
{
    Set ^dbg = {Name}
}

/// do ##class(FormsDev.NewClass1).Test()
ClassMethod Test()
{
    Kill ^FormsDev.NewClass1D, ^dbg, ^dbg2
    
    &sql(INSERT INTO FormsDev.NewClass1 (Name) Values ('Alice'))
    &sql(INSERT INTO FormsDev.NewClass2 (Name) Values ('Bob'))
    zw ^dbg, ^dbg2
}

}

and child class:

Class FormsDev.NewClass2 Extends FormsDev.NewClass1
{

Trigger Insert [ Event = INSERT ]
{
    Set ^dbg2 = {Name}
}

}

Test:

>do ##class(FormsDev.NewClass1).Test()
^dbg="Alice"
^dbg2="Bob"

 

Also, if you change trigger name, both would be executed. For example Insert in NewClass1:

Trigger Insert [ Event = INSERT ]
{
    Set ^dbg($i(^dbg)) = {Name}
}

And Insert2 in NewClass2:

Trigger Insert2 [ Event = INSERT ]
{
    Set ^dbg2($i(^dbg2)) = {Name}
}

Would result in:

>do ##class(FormsDev.NewClass1).Test()
^dbg=2
^dbg(1)="Alice"
^dbg(2)="Bob"
^dbg2=1
^dbg2(1)="Bob"
Eduard Lebedyuk · Apr 11, 2017 go to post

You set tSC variable equal to a string:

"/ensemble/data/transfer/AncillaryPDF/TMSAUDIO/Apr-11-1/980512729TMSAUDIO1046784936436537800.pdf"

However, this variable was (probably) intended to be used as a %Status. Somewhere there is probably a check:

$$$ISERR(tSC)
$$$ISOK(tSC)

Or status variable is set from tSC.

Eduard Lebedyuk · Apr 11, 2017 go to post

Possible reasons

  • Class doesn't have a %Open method. Check class value, and try to execute in a terminal: zw ##class(<class>).%Open(oid)
  • Passing id instead of oid. Try to use %OpenId method instead.
Eduard Lebedyuk · Apr 11, 2017 go to post

1. Do you send Authorization Basic header? What's the status code?

2. Include session cookie with the request. It should be done automatically.

Eduard Lebedyuk · Apr 10, 2017 go to post

1. Go to: SMP -> Menu -> Web Apps -> Your web app.

2. Click on DeepSee checkbox.

3. Press Save.

Eduard Lebedyuk · Apr 10, 2017 go to post

1. Export cube registry class from source server

2. Import cube registry class into target server

3. Execute in a terminal on a target server:

set ^DeepSee.CubeManager("activeRegistry") = "Cube.Registry.Class"
Eduard Lebedyuk · Apr 10, 2017 go to post

Unit tests should be on a server. Copy your files to "/usr/cachesys/mgr/unittests/" and point ^UnitTestRoot  global to it.

Eduard Lebedyuk · Apr 7, 2017 go to post

To check new prompt $system.Process method can be used:

do $system.Process.TerminalPrompt(8,2,4)

Here's a description of all possible values. For me 4 (Current time) is very useful as it allows for a quick performance tracking.

Eduard Lebedyuk · Apr 6, 2017 go to post

You're trying to connect to cache from the same cache process. I think the error arises from that.

Eduard Lebedyuk · Apr 3, 2017 go to post

Well, that's actually exactly what this plugin is.

<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
  <ShortName>InterSystems</ShortName>
  <Description>Latest InterSystems documentation search</Description>
  <InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16">data:image/png;base64,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
</Image>
<Url type="text/html" method="GET" template="http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.SearchPageZen.cls" rel="searchform">
  <Param name="KeyWord" value="{searchTerms}"/>
</Url>
</OpenSearchDescription>