InterSystems products (IRIS, Caché, Ensemble) already include a built-in Apache web server. But the built-in server is designed for the development and administration tasks and thus has certain limitations. Though you may find some useful workarounds for these limitations, the more common approach is to deploy a full-scale web server for your production environment. This article describes how to set up Apache to work with InterSystems products and how to provide HTTPS access. We will be using Ubuntu, but the configuration process is almost the same for all Linux distributions.

7 2
9 2.4K

This article was written as an attempt to share the experience of installing the InterSystems Caché DBMS for production environment.
We all know that the development configuration of a DBMS is very different from real-life conditions.
As a rule, development is carried out in “hothouse conditions” with a bare minimum of security measures, but when we publish our project online, we must ensure its reliable and uninterrupted operation in a very aggressive environment.

7 2
5 1.6K

I bet that not everyone familiar with InterSystems Caché knows about Studio extensions for working with the source code. You can actually use the Studio to create your own type of source code, compile it into interpretable (INT) and object code, and sometimes even add code completion support. That is, theoretically, you can make the Studio support any programming language that will be executed by the DBMS just as well as Caché ObjectScript. In this article, I will give you a simple example of writing programs in Caché Studio using a language that resembles JavaScript. If you are interested, please read along.

12 6
6 1.2K

Everybody has a testing environment.

Some people are lucky enough to have a totally separate environment to run production in.

-- Unknown

.

In this series of articles, I'd like to present and discuss several possible approaches toward software development with InterSystems technologies and GitLab. I will cover such topics as:

  • Git 101
  • Git flow (development process)
  • GitLab installation
  • GitLab WorkFlow
  • GitLab CI/CD
  • CI/CD with containers

This first part deals with the cornerstone of modern software development - Git version control system and various Git flows.

16 1
4 4.3K
Article
· Nov 19, 2018 1m read
Pagination with filters

Working on a proyect with :

Cache Object Script, Jquery and Bootstrap :

I have a big problem to do pagination with parameter, to query filter and registry limitation, but i find a solution using session and global:

1 1
0 423

The data model of your solution based on InterSystems platforms constantly changes over time. But what do you do with the data that was entered before? Back then, the data was valid, but what’s happening to it now after a number of data model changes? The answer to this question can be provided by the IDP DV tool that checks the property data of persistent and serial classes according to the types of these properties. In case any discrepancies are found, the tool generates a detailed error report for the user.

4 2
0 541

(Originally posted on Intersystems CODE by @Eduard Lebedyuk, 10/12/15) The following code snippet outputs all filenames in the file path "dir" in the Cache/IRIS terminal. The class method "test" runs the code:


Class eduardlebedyuk.filenamesInDir Extends %RegisteredObject
{
	classmethod test() {
		// replace dir with file path you want
		set dir = "D:\directory" 
		set dir = ##class(%File).NormalizeDirectory(dir)
		set file=$ZSEARCH(dir_"*")
		while file'="" {
			write !,file
			set file=$ZSEARCH("")
		}
	}
}

1 3
2 1.7K
Article
· Oct 26, 2018 1m read
Send an HTML Email

This code snippet contains the class method "test" which sends an HTML email. Change the literal strings in the method to customize the email's from address, to address, subject, and body:


Class objectscript.sendEmail Extends %RegisteredObject
{
    classmethod test() {
        set m=##class(%Net.MailMessage).%New()
        set m.From="user@company.com"
         
        set m.IsHTML=1
         
        do m.To.Insert("user@company.com")
        set m.Subject="Sent by IRIS mail"
        set m.Charset="iso-8859-1"
        do m.TextData.Write("<HTML><HEAD><TITLE></TITLE>"_$char(13,10))
        do m.TextData.Write("<META http-equiv=Content-Type content=""text/html; charset=iso-8859-2""></HEAD>"_$char(13,10))
        do m.TextData.Write("<BODY><FONT face=Arial size=2>Test <B>Test</B></FONT></BODY></HTML>")
        set s=##class(%Net.SMTP).%New()
        set s.smtpserver="mail.company.com"
        set status=s.Send(m)
    }
}

Here's a link to the code on GitHub

1 0
1 1K

From the first glance, the task of configuring LDAP authentication in Caché is not hard at all – the manual describes this process in just 6 paragraphs. On the other hand, if the LDAP server uses Microsoft Active Directory, there a few non-evident things that need to be configured on the LDAP server side. Those who don’t do anything like that on a regular basis may get lost in Caché settings. In this article, we will describe the step-by-step process of setting up LDAP authentication and cover the diagnostic methods that can be used if something doesn’t work as expected.

4 3
2 2.1K

This code snippet uses %ZEN.Auxiliary.jsonSQLProvider. The namespace and string of SQL can be edited for different situations. The class method "test" runs the code:


Class eduardlebedyuk.passQuestionParams
{
    classmethod test(pValue = 50) {
        s ns = $Namespace
        zn "samples"
        s tSQL = "SELECT ID, Name FROM Sample.Person WHERE Id > ?"
        s tPR = ##class(%ZEN.Auxiliary.jsonSQLProvider).%New()
        s tPR.sql = tSQL
        s tPR.%Format = "tw"
        s tPR.maxRows = 100
     
        s tParam = ##class(%ZEN.Auxiliary.parameter).%New()
        s tParam.value = pValue
        d tPR.parameters.SetAt(tParam,1)
      
        d tPR.%DrawJSON() 
        //d ##class(%ZEN.Auxiliary.jsonSQLProvider).%WriteJSONFromSQL(,,,,,tPR)  //same thing
        zn ns
    }
}

(Originally posted to Intersystems CODE by @Eduard Lebedyuk, 5/13/15)

Here's a link to the code on GitHub

1 0
0 253

This code snippet provides a ZEN page that downloads a stream from its database directly:


/// We assume that you have stored your data within this schema:
/// MyApp.Model.Storage: Filename,FileSize,Content,ContentType
Class zen.downloadStream Extends (%ZEN.Component.page,%CSP.StreamServer)
{
 
    /// Wrapper to get the id of the download, we assume that the id is passed to this zen page
    /// as a URI parameter, i.e.: MyApp.Downloads.cls?OID=1234
    ClassMethod GetId()
    {
        Quit $Get(%request.Data("OID",1))
    }
     
    /// Set the appropriate header for the file.
    ClassMethod OnPreHTTP() As %Boolean
    {
        Set tId = ..GetId()
     
        If ##Class(MyApp.Model.Storage).%ExistsId(tId) {
            Set tStream = ##Class(MyApp.Model.Storage).%OpenId(tId)
            // You could "guess" the content type by its file extension
            // or you can store it (before) in the database separately (like in this example).
            // Set Extension = $Piece(tStream.Filename,".",$Length(tStream.Filename,"."))
            // Set ContentType = ..FileClassify(Extension)
     
            Set %response.ContentType = tStream.ContentType
            Do %response.SetHeader("content-disposition","attachment; filename="_tStream.Filename)
            Do %response.SetHeader("Content-Length",tStream.FileSize)
        }
        Else {
            Set %response.Status="404 File Not Found"
            Quit 0
        }
        Quit $$$OK
    }
     
    ClassMethod OnPage() As %Status
    {
        Set Download = ##Class(MyApp.Model.Storage).%OpenId(..GetId())
        Do Download.Content.OutputToDevice()
        Quit $$$OK
    }
 
}

Link to code on GitHub

2 1
2 566
Article
· Sep 27, 2018 2m read
Method to Create a Class

The following class method "test" contains code that can create a new class, create new properties for classes, or create new methods for classes. "test" runs all three of these processes once, and the code that performs each action is labelled by comments in the method:


ClassMethod test() As %Status
{
    set sc = $$$OK
    
    // Create a class
    set class = ##class(%ClassDefinition).%New("MyClass")
    set class.Description = "This is my test class"_$c(13,10)_"testing %ClassDefinition"
    set class.Super = "%Persistent"

    // Create a property and add it
    set property = ##class(%PropertyDefinition).%New("MyClass.MyProperty")
    set property.Type = "%String"
    set property.Description="This is a property"
    set sc1 = class.Properties.Insert(property)
    do:$$$ISERR(sc1) $system.Status.DisplayError(sc1)
    set sc = $$$ADDSC(sc, sc1)
    
    // Create a method and add it
    set method = ##class(%MethodDefinition).%New("MyClass.MyMethod")
    set method.ReturnType = "%Integer"
    set method.FormalSpec = "x:%Integer,y:%Integer=10"
    set method.Description = "Return product of x and y"
    set method.CodeMode = "code"
    set method.Code = " new result"_$c(13,10)_" set result=x*y"_$c(13,10)_" quit result"
    set sc2 = class.Methods.Insert(method)
    do:$$$ISERR(sc2) $system.Status.DisplayError(sc2)
    set sc = $$$ADDSC(sc, sc2)
    
    // Save the class definition
    set sc3 = class.%Save()
    do:$$$ISERR(sc3) $system.Status.DisplayError(sc3)
    set sc = $$$ADDSC(sc, sc3)
    
    return sc
}

Here's a link to the code on GitHub

1 1
0 565
Article
· Sep 13, 2018 1m read
Find a table given its name

The following code snippet includes a class method "test" that runs code to find a class based on the class's name. "test" takes one argument, which is the name of the table:


Class objectscript.findTable Extends %RegisteredObject
{
    classmethod test(name as %String="mytable")  
    {
            #Dim result as %ResultSet
            #Dim tName as %String
            #Dim contain as %Integer
     
            Set contain=0
            Set result = ##class(%ResultSet).%New("%Dictionary.ClassDefinition:Summary")
            Do result.Execute()

            While(result.Next()) 
            {
                Set tName=$get(result.Data("Name"))
                &sql(select position (:name in :tName) into :contain)
                Write:contain'=0 tName, " ... ", name, " (", contain,")", !
            }
            Return $$$OK
     }
}

Here's a link to the code on GitHub

2 6
0 712
Article
· Sep 20, 2018 2m read
Get Day of the Week from Date

This code snippet determines the day of the week associated with a date. The class method "test" takes a date as a string in "mm/dd/yyyy" format, and returns an integer corresponding to a day of the week:


Class cartertiernan.getDayfromDate Extends %RegisteredObject
{
    classmethod test(date) as %Integer {
        //Set date = $ZDATE(date) //  Looks like: mm/dd/yyyy
     
        Set monthList = $LISTBUILD(0,3,3,6,1,4,6,2,5,0,3,5) // (Jan,Feb,Mar,Apr,...)
        Set centuryList = $LISTBUILD(6,4,2,0) // first two digits divisiable by 4, then subsequent centuries. EX (2000, 2100, 2200, 2300)
        Set dayList = $LISTBUILD("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday") // Index goes from 0-6
         
        Set day = $PIECE(date,"/",2) // get the day 
        Set monthVal = $LIST(monthList,($PIECE( date,"/",1 ))) // get the month value
        Set first2DigsYear = $PIECE( date,"/",3 ) \ 100 // get the last 2 digits of the year
        Set last2DigsYear = $PIECE( date,"/",3 ) # 100 // get the first 2 digits of the year
         
        // Used for DEBUG perpouses
        /*write !,"day: ",day
        write !,"Month: ",monthVal
        write !,"last2: ",last2DigsYear
        write !,"first2: ",first2DigsYear
        write !,"cen Val: ",$LIST(centuryList,(first2DigsYear # 4) + 1),!!*/
         
        // Look here for formula explination (its the "Basic method for mental calculation")
        // http://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week
        Set dayOfWeekVal = ( day + monthVal + last2DigsYear + (last2DigsYear\4) + $LIST(centuryList,(first2DigsYear # 4) + 1 ) ) # 7
     
        Quit dayOfWeekVal
    }
}

Here's a link to the code on GitHub

(originally posted to CODE by Carter Tiernan, 6/18/14)

2 1
1 895

Introduction

Any election is a highly mysterious process, and when you look at its results, the overall picture is not quite clear. I decided to put them, region by region, on the map of Moscow using InterSystems technologies that offer both storage and data analysis functionality. In this particular case, I used InterSystems Ensemble, a platform for application development and integration, but you can also build this solution using the multi-model InterSystems Caché DBMS, as well as InterSystems’ new product called IRIS Data Platform.

3 0
0 708

Generally speaking, InterSystems products supported dynamic objects and JSON for a long while, but version 2016.2 came with a completely new implementation of these features, and the corresponding code was moved from the ObjectScript level to the kernel/C level, which made for a substantial performance boost in these areas. This article is about innovations in the new version and the migration process (including the ways of preserving backward compatibility).

5 0
2 3K

This is a FYI for anyone who has experienced the following error after upgrading an existing instance to any product based on Caché 2017.2.2. In our case, the products are HealthShare HealthConnect for Redhat x64 and for Windows x86-64 but I believe it would be a common problem for any InterSystems product on any platform, if based on Caché 2017.2.2. After upgrading our development instance from 2016.2.2 to 2017.2.2, we experienced the following errors when attempting to start a pre-existing Java Object Gateway that was defined prior to the upgrade:

1 0
1 517
Article
· Sep 6, 2018 1m read
Save a file using %Net.HttpRequest

This code snippet allows for a file on the web to be saved into the file system. Specify the server and GET request, as well as the directory the file should be saved to. The class method "test" runs the code:


Class objectscript.saveFileHTTP Extends %RegisteredObject
{
    classmethod test() {
        Set httprequest = ##class(%Net.HttpRequest).%New()
        Set httprequest.Server = "docs.intersystems.com"
        Do httprequest.Get("documentation/cache/20172/pdfs/GJSON.pdf")
        
        Do $System.OBJ.Dump(httprequest.HttpResponse)
         
        Set stream=##class(%FileBinaryStream).%New()
        Set stream.Filename="c:\test.pdf"

        Write stream.CopyFrom(httprequest.HttpResponse.Data)
        Write stream.%Save()
    }
}

Here's a link to the code on GitHub

3 0
1 920

I already talked about GraphQL and the ways of using it in this article. Now I am going to tell you about the tasks I was facing and the results that I managed to achieve in the process of implementing GraphQL for InterSystems platforms.

What this article is about

  • Generation of an AST for a GraphQL request and its validation
  • Generation of documentation
  • Generation of a response in the JSON format
6 2
2 1K