Clear filter
Question
Rob Rubinson · Nov 28, 2021
Is InterSystems ODBC driver backwards compatible? If I use cache version 2018, can I upgrade the ODBC drivers to the 2021 version or it is better to upgrade to the 2018? Rob, the ODBC drivers for IRIS are not compatible with Caché and Ensemble.
Erik what about the ODBC drivers not for IRIS? Earlier ODBC driver versions should be compatible with Caché 2018.1, but we recommend updating clients to the latest driver for your Caché version. There aren't any 2021.x ODBC drivers for Caché on the WRC download page. If you have one and you want to be sure you have a good driver, reach out to the WRC so we can understand your specific situation.
Erik
Article
Yuri Marx · Aug 2, 2021
This article suggests to you some patterns to create REST API applications using IRIS.
Note: source code in https://github.com/yurimarx/movie
Class Pattern to the REST Application
To begin, see my suggestion for classes needed to create IRIS API applications:
IRISRESTApplication: CSP.REST class that will be the central controller for all REST requests and responses processed by the business services.
BusinessService: class with a business topic implementation. It can use one or more Persistent Domain Classes to persist and query data required by the business topic requirements.
Persistent Domain: persistent class to manage a SQL table.
Prereqs
VSCode;
Docker Desktop;
InterSystems ObjectScript Extension Pack.
Class Diagram to the Sample Application
I will create a Movie Catalog application to demonstrate the patterns suggested in the article:
Note: thanks to the https://openexchange.intersystems.com/package/iris-rest-api-template application. It was the base to this tutorial.
Setup the Sample Application
1. Create a folder movie in your file system. Open this folder in a new VSCode window.
2. Create the Dockerfile file inside movie folder to run IRIS Community edition into a Docker container instance. Content:
Docker file content
ARG IMAGE=intersystemsdc/iris-community:2020.3.0.221.0-zpm
ARG IMAGE=intersystemsdc/iris-community:2020.4.0.524.0-zpm
ARG IMAGE=intersystemsdc/iris-community
FROM $IMAGE
USER root
WORKDIR /opt/irisapp
RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp
USER ${ISC_PACKAGE_MGRUSER}
COPY src src
COPY module.xml module.xml
COPY iris.script /tmp/iris.script
RUN iris start IRIS \
&& iris session IRIS < /tmp/iris.script \
&& iris stop IRIS quietly
3. Create the docker-compose.yml file inside movie folder to allows you run your docker instance and other instances together (not in this sample, but it is a good practice run from docker-compose instead dockerfile. Content:
Docker composer content
version: '3.6'
services:
iris:
build:
context: .
dockerfile: Dockerfile
restart: always
ports:
- 51773
- 1972:1972
- 52773:52773
- 53773
volumes:
- ./:/irisdev/app
4. Create the iris.script file inside movie folder to do some actions before run IRIS. This file is important to do custom terminal actions necessary for the application, like disable password expiration. Content:
iris.script content
;do $System.OBJ.LoadDir("/opt/irisapp/src","ck",,1)
zn "%SYS"
Do ##class(Security.Users).UnExpireUserPasswords("*")
zn "USER"
zpm "load /opt/irisapp/ -v":1:1
halt
5. Create the module.xml file inside movie folder to install and run your application using ZPM. This file is important to do the application endpoint configuration and install swagger-ui (web app used to run and test your API using swagger file). Content:
Module.xml content
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
<Document name="movie.ZPM">
<Module>
<Name>movie</Name>
<Version>1.0.0</Version>
<Packaging>module</Packaging>
<SourcesRoot>src</SourcesRoot>
<Resource Name="dc.movie.PKG"/>
<Dependencies>
<ModuleReference>
<Name>swagger-ui</Name>
<Version>1.*.*</Version>
</ModuleReference>
</Dependencies>
<CSPApplication
Url="/movie-api"
DispatchClass="dc.movie.MovieRESTApp"
MatchRoles=":{$dbrole}"
PasswordAuthEnabled="1"
UnauthenticatedEnabled="0"
Recurse="1"
UseCookies="2"
CookiePath="/movie-api"
/>
</Module>
</Document>
</Export>
You can see CSPApplication tag, used to run the application API in the /movie-api URI and enable or disable password to consume the API.
6. Create the LICENSE file inside movie folder to setting the license of your application. Content:
LICENSE content
MIT License
Copyright (c) 2019 InterSystems Developer Community Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7. Create the README.md file inside movie folder to document your application to the users using markdown language. Content:
## movie-rest-application
This is a sample of a REST API application built with ObjectScript in InterSystems IRIS.
8. Create .vscode folder inside movie folder. Create settings.json file inside .vscode folder to configure server connection between VSCode and your IRIS instance. Content:
Settings content
{
"files.associations": {
"Dockerfile*": "dockerfile",
"iris.script": "objectscript"
},
"objectscript.conn" :{
"ns": "USER",
"username": "_SYSTEM",
"password": "SYS",
"docker-compose": {
"service": "iris",
"internalPort": 52773
},
"active": true
},
"sqltools.connections": [
{
"namespace": "USER",
"connectionMethod": "Server and Port",
"showSystem": false,
"previewLimit": 50,
"server": "localhost",
"port": 32770,
"askForPassword": false,
"driver": "InterSystems IRIS",
"name": "objectscript-docker",
"username": "_SYSTEM",
"password": "SYS"
}
]
}
9. Create the folder src inside movie folder to put your source code folders and files.
10. Create dc folder inside src folder. This is a convention when your build projects to the InterSystems Developer Community, otherwise is not necessary.
11. Create movie folder inside dc folder. This folder will be the folder to your objectscript classes.
12. Create our first class, MovieRESTApp.cls file, inside src\dc\movie folder. This file will be the IRISRESTApplication class. Content:
MovieRESTApp content
Class dc.movie.MovieRESTApp Extends %CSP.REST
{
Parameter CHARSET = "utf-8";
Parameter CONVERTINPUTSTREAM = 1;
Parameter CONTENTTYPE = "application/json";
Parameter Version = "1.0.0";
Parameter HandleCorsRequest = 1;
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<!-- Server Info -->
<Route Url="/" Method="GET" Call="GetInfo" Cors="true"/>
<!-- Swagger specs -->
<Route Url="/_spec" Method="GET" Call="SwaggerSpec" />
</Routes>
}
ClassMethod %ProcessResult(pStatus As %Status = {$$$OK}, pResult As %DynamicObject = "") As %Status [ Internal ]
{
#dim %response As %CSP.Response
SET tSC = $$$OK
IF $$$ISERR(pStatus) {
SET %response.Status = 500
SET tSC = ..StatusToJSON(pStatus, .tJSON)
IF $isobject(tJSON) {
SET pResult = tJSON
} ELSE {
SET pResult = { "errors": [ { "error": "Unknown error parsing status code" } ] }
}
}
ELSEIF pStatus=1 {
IF '$isobject(pResult){
SET pResult = {
}
}
}
ELSE {
SET %response.Status = pStatus
SET error = $PIECE(pStatus, " ", 2, *)
SET pResult = {
"error": (error)
}
}
IF pResult.%Extends("%Library.DynamicAbstractObject") {
WRITE pResult.%ToJSON()
}
ELSEIF pResult.%Extends("%JSON.Adaptor") {
DO pResult.%JSONExport()
}
ELSEIF pResult.%Extends("%Stream.Object") {
DO pResult.OutputToDevice()
}
QUIT tSC
}
ClassMethod SwaggerSpec() As %Status
{
Set tSC = ##class(%REST.API).GetWebRESTApplication($NAMESPACE, %request.Application, .swagger)
Do swagger.info.%Remove("x-ISC_Namespace")
Set swagger.basePath = "/movie-api"
Set swagger.info.title = "Movie API"
Set swagger.info.version = "1.0"
Set swagger.host = "localhost:52773"
Return ..%ProcessResult($$$OK, swagger)
}
}
Note 1: The class extends CSP.REST to be used as the REST Endpoint.
Note 2: the parameter chaset is used to encode requests and responses with UTF-8.
Note 3: the CONVERTINPUTSTREAM is used to force the request content in the UTF-8, without this you can have problems with special latin chars.
Note 4: CONTENTTYPE is used to declare the content using JSON, not XML.
Note 5: HandleCorsRequest = 1 is necessary to allows you consume the API from other servers different from the IRIS server.
Note 6: Routes are used to declare API URI to each class method.
Note 7: SwaggerSpec from CSP.REST class allows you generate the API swagger (API web documentation) content.
Now you have the following folders and files:
13. Open VSCode Terminal (menu Terminal > New Terminal) and type:
docker-compose up -d --build
This will build the docker instance and run it.
14. Test your API with Swagger-UI. In the browser and type: http://localhost:52773/swagger-ui/index.html. Pay attention to the address bar (fix the url, if necessary to correct address)
Connection beetween VSCode and IRIS
1. Click in the ObjectScript bar (in the VSCode footer)
2. Select Toogle Connection in the Top:
3. Check the connection status into ObjectScript Explorer (you will be able to see folders and classes created):
Persistent Classes to the Movie Catalog Application
In this section we will create the persistent domain classes to store and query the business data. See the DBeaver Diagram:
1. Create the folder model inside src\dc\movie folder.
2. Create the Actor.cls file inside model folder. Write the content:
Class dc.movie.model.Actor Extends (%Persistent, %JSON.Adaptor)
{
Parameter %JSONREFERENCE = "ID";
Property actorId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ];
Property name As %VarString(MAXLEN = 120);
Property dob As %Date;
Property genre As %Integer(VALUELIST = ",1,2");
}
3. Create the Movie.cls file inside model folder. Write the content:
Class dc.movie.model.Movie Extends (%Persistent, %JSON.Adaptor)
{
Parameter %JSONREFERENCE = "ID";
Property movieId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ];
Property name As %VarString(MAXLEN = 120);
Property releaseDate As %Date;
Property duration As %Integer;
Property imdb As %String(MAXLEN = 300);
Property movieCategory As dc.movie.model.MovieCategory;
ForeignKey MovieCategoryFK(movieCategory) References dc.movie.model.MovieCategory();
}
4. Create the MovieCategory.cls file inside model folder. Write the content:
Class dc.movie.model.MovieCategory Extends (%Persistent, %JSON.Adaptor)
{
Parameter %JSONREFERENCE = "ID";
Property movieCategoryId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ];
Property name As %VarString(MAXLEN = 120);
}
5. Create the Casting.cls file inside model folder. Write the content:
Class dc.movie.model.Casting Extends (%Persistent, %JSON.Adaptor)
{
Parameter %JSONREFERENCE = "ID";
Property castingId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ];
Property movie As dc.movie.model.Movie;
ForeignKey MovieFK(movie) References dc.movie.model.Movie();
Property actor As dc.movie.model.Actor;
ForeignKey ActorFK(actor) References dc.movie.model.Actor();
Property characterName As %String(MAXLEN = 100);
Index CastingIndex On (movie, actor) [ Unique ];
}
See the created files:
Note 1: Parameter %JSONREFERENCE = "ID" allows return ID value inside JSON response.
Note 2: Property actorId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ] and the other similar properties are used to return class+id into JSON response.
Note 3: (VALUELIST = "1,2") set possible values to 1 or 2 only.
Note 4: ForeignKey MovieFK(movie) References dc.movie.model.Movie() and similar are used to create a SQL foreign key reference.
Note 5: Index CastingIndex On (movie, actor) [ Unique ] and similar are used to not allows duplicate values combining properties in the On (movie and actor).
Note 6: I'm using Camel Case to property names because a best practice for JSON attribute names.
Business Service Classes to the Movie Catalog Application
In this section we will create the classes with business logic (methods to do persistence, query and calculations).
1. Create the service folder inside src\dc\movie.
2. Create CrudUtilService.cls file inside service folder. Write the content:
CrudUtilService content
Class dc.movie.service.CrudUtilService Extends %CSP.REST
{
Parameter CHARSET = "utf-8";
Parameter CONVERTINPUTSTREAM = 1;
Parameter CONTENTTYPE = "application/json";
Parameter Version = "1.0.0";
Parameter HandleCorsRequest = 1;
/// Return all the records
ClassMethod GetAll(DomainClass As %Persistent) As %Status
{
#dim tSC As %Status = $$$OK
Set rset = DomainClass.ExtentFunc()
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Write "["
if rset.%Next() {
Set actor = DomainClass.%OpenId(rset.ID)
Do actor.%JSONExport()
}
While rset.%Next() {
Write ","
Set actor = DomainClass.%OpenId(rset.ID)
Do actor.%JSONExport()
}
Write "]"
Quit tSC
}
/// Return one record
ClassMethod GetOne(DomainClass As %Persistent, id As %Integer) As %Status
{
#dim tSC As %Status = $$$OK
#dim e As %Exception.AbstractException
#; Set the response header to plain text
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Set domain = DomainClass.%OpenId(id)
If '$IsObject(domain) Quit ..Http404()
Do domain.%JSONExport()
Quit tSC
}
/// Creates a new record
ClassMethod Create(DomainClass As %Persistent) As %Status
{
#dim tSC As %Status = $$$OK
#dim e As %Exception.AbstractException
Set domain = DomainClass.%New()
Set data = {}.%FromJSON(%request.Content)
$$$TOE(tSC, domain.%JSONImport(data))
$$$TOE(tSC, domain.%Save())
Write domain.%JSONExport()
Set %response.Status = 204
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Quit tSC
}
/// Update a record with id
ClassMethod Update(DomainClass As %Persistent, id As %Integer) As %Status
{
#dim tSC As %Status = $$$OK
#dim e As %Exception.AbstractException
Set domain = DomainClass.%OpenId(id)
If '$IsObject(domain) Return ..Http404()
Set data = {}.%FromJSON(%request.Content)
$$$TOE(tSC, domain.%JSONImport(data))
$$$TOE(tSC, domain.%Save())
Write domain.%JSONExport()
Set %response.Status = 200
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Quit tSC
}
/// Delete a record with id
ClassMethod Delete(DomainClass As %Persistent, id As %Integer) As %Status
{
#dim tSC As %Status = $$$OK
#dim e As %Exception.AbstractException
Set domain = DomainClass.%OpenId(id)
If '$IsObject(domain) Return ..Http404()
$$$TOE(tSC, domain.%DeleteId(id))
Set %response.Status = 200
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Quit tSC
}
}
3. Create MovieService.cls file inside service folder. Write the content:
MovieService content
Class dc.movie.service.MovieService Extends %CSP.REST
{
ClassMethod GetAll() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.Movie).%New())
}
ClassMethod GetOne(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.Movie).%New(), id)
}
ClassMethod Create() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.Movie).%New())
}
ClassMethod Update(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.Movie).%New(), id)
}
ClassMethod Delete(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.Movie).%New(), id)
}
/// Return casting from the movie
ClassMethod GetMovieCasting(id As %Integer) As %Status
{
#dim tSC As %Status = $$$OK
Set qry = "SELECT actor->name AS actorName, characterName, movie->name AS movieName FROM dc_movie_model.Casting WHERE movie = ?"
Set tStatement = ##class(%SQL.Statement).%New()
Set qStatus = tStatement.%Prepare(qry)
If tSC'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
Set rset = tStatement.%Execute(id)
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Set result = []
While rset.%Next() {
Set item = {}
Set item.actorName = rset.actorName
Set item.movieName = rset.movieName
Set item.characterName = rset.characterName
Do result.%Push(item)
}
Write result.%ToJSON()
Quit tSC
}
}
4. Create MovieCategoryService.cls file inside service folder. Write the content:
MovieCategoryService content
Class dc.movie.service.MovieCategoryService
{
ClassMethod GetAll() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.MovieCategory).%New())
}
ClassMethod GetOne(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.MovieCategory).%New(), id)
}
ClassMethod Create() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.MovieCategory).%New())
}
ClassMethod Update(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.MovieCategory).%New(), id)
}
ClassMethod Delete(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.MovieCategory).%New(), id)
}
}
5. Create ActorService.cls file inside service folder. Write the content:
ActorService content
Class dc.movie.service.ActorService
{
ClassMethod GetAll() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.Actor).%New())
}
ClassMethod GetOne(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.Actor).%New(), id)
}
ClassMethod Create() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.Actor).%New())
}
ClassMethod Update(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.Actor).%New(), id)
}
ClassMethod Delete(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.Actor).%New(), id)
}
}
6. Create CastingService.cls file inside service folder. Write the content:
CastingService content
Class dc.movie.service.CastingService
{
ClassMethod GetAll() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.Casting).%New())
}
ClassMethod GetOne(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.Casting).%New(), id)
}
ClassMethod Create() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.Casting).%New())
}
ClassMethod Update(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.Casting).%New(), id)
}
ClassMethod Delete(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.Casting).%New(), id)
}
}
7. Update the file MovieRESTApp.cls to create paths to all new service class methods. Write the content:
MovieRESTApp updated content
Class dc.movie.MovieRESTApp Extends %CSP.REST
{
Parameter CHARSET = "utf-8";
Parameter CONVERTINPUTSTREAM = 1;
Parameter CONTENTTYPE = "application/json";
Parameter Version = "1.0.0";
Parameter HandleCorsRequest = 1;
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<!-- Server Info -->
<Route Url="/" Method="GET" Call="GetInfo" Cors="true"/>
<!-- Swagger specs -->
<Route Url="/_spec" Method="GET" Call="SwaggerSpec" />
<!-- List all movies -->
<Route Url="/movies" Method="GET" Call="GetAllMovies" />
<!-- Get a movie -->
<Route Url="/movies/:id" Method="GET" Call="GetMovie" />
<!-- Get the movie casting -->
<Route Url="/movies/casting/:id" Method="GET" Call="GetMovieCasting" />
<!-- Create new movie -->
<Route Url="/movies" Method="POST" Call="CreateMovie" />
<!-- Update a movie -->
<Route Url="/movies/:id" Method="PUT" Call="UpdateMovie" />
<!-- Delete a movie -->
<Route Url="/movies/:id" Method="DELETE" Call="DeleteMovie" />
<!-- List all movie categories -->
<Route Url="/categories" Method="GET" Call="GetAllMovieCategories" />
<!-- Get a movie category -->
<Route Url="/categories/:id" Method="GET" Call="GetMovieCategory" />
<!-- Create new movie category -->
<Route Url="/categories" Method="POST" Call="CreateMovieCategory" />
<!-- Update a movie category -->
<Route Url="/categories/:id" Method="PUT" Call="UpdateMovieCategory" />
<!-- Delete a movie category -->
<Route Url="/categories/:id" Method="DELETE" Call="DeleteMovieCategory" />
<!-- List all actors -->
<Route Url="/actors" Method="GET" Call="GetAllActors" />
<!-- Get a actor -->
<Route Url="/actors/:id" Method="GET" Call="GetActor" />
<!-- Create new actor -->
<Route Url="/actors" Method="POST" Call="CreateActor" />
<!-- Update a actor -->
<Route Url="/actors/:id" Method="PUT" Call="UpdateActor" />
<!-- Delete a actor -->
<Route Url="/actors/:id" Method="DELETE" Call="DeleteActor" />
<!-- List all castings -->
<Route Url="/castings" Method="GET" Call="GetAllCastings" />
<!-- Get a actor -->
<Route Url="/castings/:id" Method="GET" Call="GetCasting" />
<!-- Create new actor -->
<Route Url="/castings" Method="POST" Call="CreateCasting" />
<!-- Update a actor -->
<Route Url="/castings/:id" Method="PUT" Call="UpdateCasting" />
<!-- Delete a actor -->
<Route Url="/castings/:id" Method="DELETE" Call="DeleteCasting" />
</Routes>
}
/// List movies
ClassMethod GetAllMovies() As %Status
{
Return ##class(dc.movie.service.MovieService).GetAll()
}
/// Get movie casting
ClassMethod GetMovieCasting(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieService).GetMovieCasting(id)
}
/// Get a movie
ClassMethod GetMovie(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieService).GetOne(id)
}
// Create a new movie
ClassMethod CreateMovie() As %Status
{
Return ##class(dc.movie.service.MovieService).Create()
}
// Update a movie
ClassMethod UpdateMovie(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieService).Update(id)
}
// Delete a movie
ClassMethod DeleteMovie(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieService).Delete(id)
}
/// List movies categories
ClassMethod GetAllMovieCategories() As %Status
{
Return ##class(dc.movie.service.MovieCategoryService).GetAll()
}
/// Get a movie category
ClassMethod GetMovieCategory(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieCategoryService).GetOne(id)
}
// Create a new movie category
ClassMethod CreateMovieCategory() As %Status
{
Return ##class(dc.movie.service.MovieCategoryService).Create()
}
// Update a movie category
ClassMethod UpdateMovieCategory(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieCategoryService).Update(id)
}
// Delete a movie category
ClassMethod DeleteMovieCategory(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieCategoryService).Delete(id)
}
/// List actors
ClassMethod GetAllActors() As %Status
{
Return ##class(dc.movie.service.TestActorService).GetAll()
}
/// Get an actor
ClassMethod GetActor(id As %Integer) As %Status
{
Return ##class(dc.movie.service.ActorService).GetOne(id)
}
// Create a new actor
ClassMethod CreateActor() As %Status
{
Return ##class(dc.movie.service.ActorService).Create()
}
// Update an actor
ClassMethod UpdateActor(id As %Integer) As %Status
{
Return ##class(dc.movie.service.ActorService).Update(id)
}
// Delete an actor
ClassMethod DeleteActor(id As %Integer) As %Status
{
Return ##class(dc.movie.service.ActorService).Delete(id)
}
/// List castings
ClassMethod GetAllCastings() As %Status
{
Return ##class(dc.movie.service.CastingService).GetAll()
}
/// Get a casting
ClassMethod GetCasting(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CastingService).GetOne(id)
}
// Create a new casting item
ClassMethod CreateCasting() As %Status
{
Return ##class(dc.movie.service.CastingService).Create()
}
// Update a casting
ClassMethod UpdateCasting(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CastingService).Update(id)
}
// Delete a casting
ClassMethod DeleteCasting(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CastingService).Delete(id)
}
/// General information
ClassMethod GetInfo() As %Status
{
SET version = ..#Version
SET fmt=##class(%SYS.NLS.Format).%New("ptbw")
SET info = {
"Service": "Movie API",
"version": (version),
"Developer": "Yuri Gomes",
"Status": "Ok",
"Date": ($ZDATETIME($HOROLOG))
}
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Write info.%ToJSON()
Quit $$$OK
}
ClassMethod %ProcessResult(pStatus As %Status = {$$$OK}, pResult As %DynamicObject = "") As %Status [ Internal ]
{
#dim %response As %CSP.Response
SET tSC = $$$OK
IF $$$ISERR(pStatus) {
SET %response.Status = 500
SET tSC = ..StatusToJSON(pStatus, .tJSON)
IF $isobject(tJSON) {
SET pResult = tJSON
} ELSE {
SET pResult = { "errors": [ { "error": "Unknown error parsing status code" } ] }
}
}
ELSEIF pStatus=1 {
IF '$isobject(pResult){
SET pResult = {
}
}
}
ELSE {
SET %response.Status = pStatus
SET error = $PIECE(pStatus, " ", 2, *)
SET pResult = {
"error": (error)
}
}
IF pResult.%Extends("%Library.DynamicAbstractObject") {
WRITE pResult.%ToJSON()
}
ELSEIF pResult.%Extends("%JSON.Adaptor") {
DO pResult.%JSONExport()
}
ELSEIF pResult.%Extends("%Stream.Object") {
DO pResult.OutputToDevice()
}
QUIT tSC
}
ClassMethod SwaggerSpec() As %Status
{
Set tSC = ##class(%REST.API).GetWebRESTApplication($NAMESPACE, %request.Application, .swagger)
Do swagger.info.%Remove("x-ISC_Namespace")
Set swagger.basePath = "/movie-api"
Set swagger.info.title = "Movie API"
Set swagger.info.version = "1.0"
Set swagger.host = "localhost:52773"
Return ..%ProcessResult($$$OK, swagger)
}
}
8. The files and folders to the final project are:
9. Test your new methods acessing http://localhost:52773/swagger-ui/index.html.
Note 1: REST paths are following business topic in plural with /id when we need pass id to the entity and camel case to paths to.
Note 2: We use verb GET to queries, POST to new records, PUT to update record and DELETE to delete a record.
Note 3: In <Route Url="/movies/casting/:id" Method="GET" Call="GetMovieCasting" /> I used /casting indicating a second purpose (get the movie and it casting). This method runs ToJSON(), because is a DynamicArray ([]) with Dynamic items ({}).
Note 4: I created the CrudUtilService class utility to do generic CRUD methods, following the Dont Repeat Yourself principle.
Enjoy this tutorial!
Hi Yuri
You didn't use GoJS by any chance for the UML etc... If you look in the General Section of Discord I have written a chunk of stuff about GoJS and how a developer could build the necessary data collectors into their classes and then having but the data sets render the diagrams through GoJS Thanks for the tip! I did use StarUML, but in the next time I will consider GoJS Great article.
Some comments on formatting:
Move large code blocks under spoiler to improve readability using button.
There are a lot of empty lines in code blocks, they can be safely removed.
On the article itself my only issue is you create 5 methods per class:
GET /class
POST /class
GET /class/object
PUT /class/object
DELETE /class/object
That's a lot of code even for 4 classes, but what about a case where there are 10 classes? 50? 100? Generally I would recommend writing 5 methods which would process objects of any allowed class (see RESTForms2). Fixed and improved, thanks!!! Hi Yuri
I forgot to mention that I agree with Eduard that your article is excellent.
Nigel Thanks!!! Excellent work @Yuri.Gomes, lots of useful details for the reader! I like DRY too :-) Thanks @Luca.Ravazzolo
Question
Muhammad Waseem · Sep 3, 2021
Hi,
Under the social tab of my profile I found "InterSystems SSO" account along with my other social accounts.
What is InterSystems SSO account and to utilize it?
Thanks Just curious - where are you seeing this? Could you please include a URL?
The InterSystems SSO account is what controls your access to open as well as restricted applications provided by InterSystems to help customers and prospects get stuff done. If you go to Login.InterSystems.com you can see the various apps available to you (after you sign in). This would include things like D.C., OEX, Learning, Download, etc for Prospects, and supported customers would also get access to WRC, iService, HS Docs, CCR, etc (depending on what products they have).
Hope that helps - let me know if any additional clarification is needed. SSO is part of Social Tab in Edit Profile in Global Masters.it allows sign in using WRC SSO
https://globalmasters.intersystems.com/ It is along with other social accounts Thanks Robert Cemper, What is the difference between Normal and SSO Account ? SSO account can be shared for WRC (if enabled), DC, OEX, Learnig, ..Global Masters is an external application that can make use of SSObut has its own independent accounts as well.
Article
Yuri Marx · Oct 19, 2021
In the last years the data architecture and platforms focused into Big Data repositories and how toprocess it to deliver business value. From this effort many technologies were created to process tera and petabytes of data, see:
The fundamental piece to the Big Data technologies is HDFS (Hadoop Distributed File System). It is a distributed file system to store tera or petabytes of data into arrays of storages, memory and CPU working together. In addition of the Hadoop we have other components, see:
In a Big Data project the first step is create the data ingestion, integration, transformation/enrichment, with data quality as a requirement. In this area we have:
Apache Kafka: data event flow, in real time asyncronous events, were each event deliver data items to be ingested by the Big Data using Kafka clients. It is possible process milions of data event per second, creating real time data streams.
Apache NiFi: it is an ETL capable to create integration maps that connect with multiples formats, technologies and type of data sources to deliver data to HDFS, Databases or HBase repositories. Acts also as a CDC tool.
Apache Sqoop: it is an Data Ingestion tool for SQL Databases.
Apache Flume: collect data from the log of the datasources to push to the HDFS or HBase.
ESB: it is a service bus used to connect internal and external datasources into a corporate data backbone to send, receive and process data between enterprise data resources, including Big Data repositories. The ESB has connectors/adapters to the main data resources, like Kafka, SQL Databases, NoSQL databases, E-mail, Files, FTP, JMS messages and other. The InterSystems IRIS has an ESB. The ESB can automate data process, delivering complex integrations to the Big Data repositories.
HDFS: it is the most used resource to store big data volumes, with performance, realiabity and availability. The data storage is distributed into data nodes working in an active-active HA and using common machines. So, it is cheaper than store into RDMS products.
HBase: it is like HDFS, but it is used to store NoSQL data, like objects or documents.
Sharding DB: are data stores that use distributed data nodes to allow process Big Data SQL or NoSQL repositories into proprietary formats. The main example is MongoDB, but InterSystems IRIS it is a Shard DB too, including options to store SQL, NoSQL (JSON) or OLAP datastores.
YARN and ZooKeeper: are tools to centralize and allows the Big Data tools share configuration, resources, resource names and metadata.
Apache Spark: Apache Spark is a distributed processing system used for big data workloads. It utilizes in-memory caching, and optimized query execution for fast analytic queries against data of any size. It provides development APIs in Java, Scala, Python and R, and supports code reuse across multiple workloads—batch processing, interactive queries, real-time analytics, machine learning, and graph processing (AWS definition). The InterSystems IRIS has a Spark adapter that can be used to read and write HDFS data.
Apache Hive: it is a distributed, fault-tolerant data warehouse system that enables analytics at a massive scale. A data warehouse provides a central store of information that can easily be analyzed to make informed, data driven decisions. Hive allows users to read, write, and manage petabytes of data using SQL. Hive is built on top of Apache Hadoop, which is an open-source framework used to efficiently store and process large datasets. As a result, Hive is closely integrated with Hadoop, and is designed to work quickly on petabytes of data. What makes Hive unique is the ability to query large datasets, leveraging Apache Tez or MapReduce, with a SQL-like interface (AWS definition). The InterSystems IRIS don't have native adapter for Hive, but I created it (see: https://community.intersystems.com/post/using-sql-apache-hive-hadoop-big-data-repositories).
Apache Pig: it is a library that runs on top of Hadoop, providing a scripting language that you can use to transform large data sets without having to write complex code in a lower level computer language like Java. The library takes SQL-like commands written in a language called Pig Latin and converts those commands into Tez jobs based on directed acyclic graphs (DAGs) or MapReduce programs. Pig works with structured and unstructured data in a variety of formats. (AWS definition).
Apache Drill: it is a tool to do queries for the main Big Data products using SQL sintax. Drill supports a variety of NoSQL databases and file systems, including HBase, MongoDB, MapR-DB, HDFS, MapR-FS, Amazon S3, Azure Blob Storage, Google Cloud Storage, Swift, NAS and local files. A single query can join data from multiple datastores. For example, you can join a user profile collection in MongoDB with a directory of event logs in Hadoop (Apache Drill definition). I will build an adapter to Apache Drill in the near future.
ESB Adapters: it is an interoperability platform, with ready connectors to query and process data from multiple formats and protocols. The InterSystems IRIS has adapter to HTTP, FTP, File, SQL, MQTT (IoT) and many other datasources. These adapters can compose data flows (productions) to deliver the data for multiple targets, including hadoop repositories.
InterSystems IRIS it is a good Big Data architecture option with:
1. An excellent integration/ETL layer, as an ESB platform.2. A fantastic distributed data store when using IRIS Database Sharding.3. An important tool to query and process Big Data information, using its adapters. The InterSystems IRIS can also deliver reports, BI Dashboards and data microservices.4. A good tool to work with Kafka, Spark, Hadoop and Hive, to deliver Big Data with additional resources, like ESB, Analytics, Machine Learning, Data workflows (BPL productions) and native support to the main languages (Python, R, Java, .Net, Node.js).
See a sample of this into my new app: https://openexchange.intersystems.com/package/IRIS-Big-Data-SQL-Adapter. Thanks! And enjoy!
Announcement
Anastasia Dyubaylo · Oct 26, 2021
Hey Community,
We're pleased to invite you to the French stream on InterSystems Technologies #6!
This event hosted by @Guillaume.Rongier7183 for French-speaking InterSystems developers will be live stream November 4th at 12:00 Paris time.
👉 Direct link to join: https://youtu.be/Gn6A1MnsxFY
On the agenda this month:
🗞 News
https://code.visualstudio.com/blogs/2021/09/29/bracket-pair-colorization
https://openexchange.intersystems.com/contest/18
Virtual Summit overview https://www.intersystems.com/VS21Reg
💡 Did you know?
Projections in ObjectScript, how to execute code during compilation
🗂 Focus on
AtScale
Don’t miss the French Stream #6 👉 https://youtu.be/Gn6A1MnsxFY!
Enjoy watching the prev streams on YouTube:
Stream #1
Stream #2
Stream #3
Stream #4
Stream #5
Stay tuned!
Article
Jose-Tomas Salvador · Nov 9, 2021
For some years I missed being able to offer, to everybody interested in ObjectScript, a tutorial more or less complete, to start with ObjectScript. Something that could help more and make things easier to those new developers that come to our technology... something intermediate, halfway between the common "Hello World!", that doesn't really get you further, and the "Advanced Training", that is unaffordable because of lack of time,etc.
If there were something truly helpful not only as an introduction to the ecosystem, but as a starting point, as a boost, to really start to walk into ObjectScript and move forward by yourself... wouldn't that be awesome?
In short... as I say, the idea that something like that should exist, it's going around me for a while... and then, the pandemic... and we had to stay at home, almost no holidays, and loooonnggg weekends,... what a better situation to do what we always say we would do if we had time?
So..no sooner said than done... I started to work on it several months ago and spend some free time here and there to develop this idea... you will tell me how it is (be kind), because:
Today I can announce officially the birth of ¡¡¡1st Video Tutorial in Spanish of ObjectScript 101++ !!!
Ok, ok,... plus, plus, .... I didn't date to call it 102... or intermediate or so....... It's composed of 6 videos plus one with a short introduction...
Wait... yes... I know... I said Spanish... and this is community in english...I know... It's uploaded in the ES community since September...but last week I published the last video there and I thought that it could also be useful to english native speakers that understand (or are learning) spanish... that's why I decided to post it also here. Also, I'm dealing with subtitles in YouTube... so to include the english translation. I'll link the videos for which I consider the english translation is fine as soon as they're ready. Right now, only the first 3 are reviewed (I will need some more weekends ).
Code samples and exercises used in different parts of the tutorial are in GitHub. To see the videos better, my advice is to do it in full size screen... they are also available in YouTube.
IMPORTANT: It's not an InterSystems official training and doesn't intend to (it can't in any way) replace the formal classroom training, which are more extense, rigurous and complete. My intention is for this tutorial to be an additional resource to introduce you into the ObjectScript world as a starting point and a spur, something that helps you to move forward by yourself, together with other resources from eLearning, formal training, documentation or this community!
¡¡Enjoy!!
Chapter 0 - Introduction
Chapter 1 - Settling down
Chapter 2 - Iterating
Chapter 3 - My Execution Context
Chapter 4 - Indirection and Globals
Chapter 5 - Objects in ObjectScript
Chapter 6 - What about SQL?
@Jose-Tomas.Salvador - thank you for the effort you put into creating this and making it available to the Community :) Ok, I've just reviewed the translation of Chapter 4 to english. Here I talk briefly about Indirection in ObjectScript and, mostly, about Globals... Enjoy! Well, this took some more time.... but arrived on time before end of year. Chapter 5 captions reviewed!! In this chapter I talk about OO.OO in ObjectScript, a bit of JSON native support, Macros, Error handling,... with guided hands-on.
Just one left. Enjoy! It was funny really... and served me to realize how hard is to create this kind of material. Now I appreciate it much more. :-) Well, it has been a long trip... but Chapter 6, "What's about SQL?" is finally published with reviewed English CC...
In this last chapter I'll show you what's about the Multi-Model architecture of InterSystems IRIS, and how ObjectScript is able to work also with SQL paradigm in a very easy way to also cover that feature of the platform.We'll do hands-on exercises of embedded and dynamic SQL using the small class model we defined in the previous chapter... which now we'll see as an E/R model.
And... That's all folks!
Happy Coding! worth watching content, thanks! Hi again, I've just added to the article the slides that I used during the video tutorial. Feel free to use all of some of them. If you do, the only thing I would kindly ask you is to include a link as a reference to this article within our community.
For the ones that contacted me, you were right, the repository in GitHub was set as private. It's set to public now: GitHub Repository - Examples
Announcement
Anastasia Dyubaylo · Nov 13, 2021
Hey Community,
The new video is worth watching on InterSystems Developers YouTube:
⏯ Data Warehousing with InterSystems
Get a quick tour of classic and emerging terms used to describe logical and physical data stores that go beyond exclusive application use. With these concepts in mind, see how InterSystems® technology helps streamline your data landscape.
🗣 Presenter: @Benjamin.DeBoe, InterSystems Product Manager
Subscribe to InterSystems Developers YouTube and stay tuned!
Announcement
Anastasia Dyubaylo · Jan 25, 2022
Hey Community,
Learn about the changes we've made to InterSystems IRIS Containers, including security updates and the new web gateway container:
⏯ InterSystems IRIS Container Updates
🗣 Presenter: @Eve.Phelps, Senior Systems Developer, InterSystems
Enjoy watching on InterSystems Developers YouTube channel and stay tuned!
Announcement
Anastasia Dyubaylo · Apr 24, 2022
Hey Developers,
What is the best way to containerize your InterSystems IRIS application? Discover your options:
⏯ Containerizing InterSystems IRIS Applications
🗣 Presenter: @Evgeny.Shvarov, Developer Ecosystem manager, InterSystems
Enjoy watching the new video on InterSystems Developers YouTube!
Announcement
Anastasia Dyubaylo · Jun 29, 2022
Hey Community,
We're thrilled to invite you to the next InterSystems in-person event! Join us for a true community event, once again bringing together InterSystems customers and partners – to learn, inspire, and share innovation challenges with each other:
➡️ InterSystems UK & Ireland Summit 2022
🗓 Date: October 18-19, 2022
📍 Location: Birmingham, United Kingdom – The Vox Conference Centre
A wide range of prominent speakers will provide a wealth of knowledge and expertise, with the event entirely focused on making sure you have the information required to not only help you within your own role but to positively impact on the growth and success of your organisation.
Hear the latest product roadmaps from InterSystems specialists
Network with like-minded peers and be inspired by their levels of innovation
Get face-to-face once again with peers and InterSystems experts in interactive breakouts, experience labs, and workshops
We can’t wait to see you all again in October!
➡️ Register today at www.intersystems.com/uk/uki-summit
Announcement
Derek Robinson · Jun 29, 2022
Hi All! We have recently updated the Exploring Healthcare Analytics with InterSystems exercise to a new version. Originally from a 2021 Virtual Summit experience lab, this exercise now focuses more specifically on using InterSystems IRIS Adaptive Analytics with InterSystems IRIS for Health. It features a new and improved data model and exercise to explore. Feel free to give it a try!
Article
Yuri Marx · Aug 8, 2022
In this article you will have access to the curated base of articles from the InterSystems Developer Community of the most relevant topics to learning InterSystems IRIS. Find top published articles ranked by Machine Learning, Embedded Python, JSON, API and REST Applications, Manage and Configure InterSystems Environments, Docker and Cloud, VSCode, SQL, Analytics/BI, Globals, Security, DevOps, Interoperability, Native API. Learn and Enjoy!
Machine Learning
Machine Learning is a mandatory technology to build advanced data analysis and automate manual activities with excellent efficiency. It creates cognitive models that learn from the existing data, and perform predictions, probability calculations, classifications, identifications, and automation of "non-creative" human activities based on its self-adjusted algorithms.
In all scenarios, InterSystems IRIS acts as a data platform and environment for creating, executing, making available, and using these machine learning models. IRIS enables the use of ML from SQL commands (IntegratedML), execution of ML using Embedded Python and PMML(Predictive Model Markup Language). You can check how it functions in the following articles:
Title
Description
URL
IntegratedML hands-on lab
Practical Overview to IntegratedML
https://community.intersystems.com/post/integratedml-hands-lab
AI Robotization with InterSystems IRIS Data Platform
AI on IRIS productions
https://community.intersystems.com/post/ai-robotization-intersystems-iris-data-platform
Web App to Predict Diabetes using IRIS IntegratedML
IntegratedML sample
https://community.intersystems.com/post/web-app-predict-diabetes-using-iris-integratedml
Predict Maternal Health Risks
IntegratedML sample
https://community.intersystems.com/post/predict-maternal-health-risks
Using Machine Learning to Organize the Community – 1
Using Python ML libraries
https://community.intersystems.com/post/using-machine-learning-organize-community-1
ObjectScript language
ObjectScript is InterSystems' official programming language. It is easy, flexible, and very powerful in creating backend, integration, and analytics applications. Consult the following articles for more information:
Title
Description
URL
InterSystems ObjectScript 101++ (EN)
Video series to learn ObjectScript
https://community.intersystems.com/post/intersystems-objectscript-101-en
On $Sequence function
Create sequences of numbers
https://community.intersystems.com/post/sequence-function
Writing better-performing loops in Caché ObjectScript
Do loops
https://community.intersystems.com/post/writing-better-performing-loops-cach%C3%A9-objectscript
Data anonymization, introducing iris-Disguise
Learn how to do customizations on ObjectScript persistent classes and properties
https://community.intersystems.com/post/data-anonymization-introducing-iris-disguise
ObjectScript error handling snippets
Exception handling
https://community.intersystems.com/post/objectscript-error-handling-snippets
Traditional Debugging in ObjectScript
Debug techniques
https://community.intersystems.com/post/traditional-debugging-objectscript
Using Regular Expressions in Caché
Work with Regular Expressions
https://community.intersystems.com/post/using-regular-expressions-cach%C3%A9
Robust Error Handling and Cleanup in ObjectScript
Write code with quality
https://community.intersystems.com/post/robust-error-handling-and-cleanup-objectscript
SPOOL - the forgotten device
Using Spool
https://community.intersystems.com/post/spool-forgotten-device
How we learned to stop worrying and love InterSystems Ensemble
Processing JSON on Productions
https://community.intersystems.com/post/how-we-learned-stop-worrying-and-love-intersystems-ensemble
A more useFull Object Dump
Dumping objects
https://community.intersystems.com/post/more-usefull-object-dump
Logging using macros in InterSystems IRIS
Logging using macros
https://community.intersystems.com/post/logging-using-macros-intersystems-iris
SYSLOG - what it really is and what it means
Debug information on Syslog
https://community.intersystems.com/post/syslog-what-it-really-and-what-it-means
Tips for debugging with %Status
Debug using %Status
https://community.intersystems.com/post/tips-debugging-status
Making the most of $Query
Looking for data using $Query
https://community.intersystems.com/post/making-most-query
Multidimensional Property Persistence - Part 1 (Classic)
Multidimensional persistent properties
https://community.intersystems.com/post/multidimensional-property-persistence-part-1-classic
The adopted Bitmap
Bitmap indexes
https://community.intersystems.com/post/adopted-bitmap
How to become a time lord - The birth
Date and Time API
https://community.intersystems.com/post/how-become-time-lord-birth
Importance and Collection of Exact Version Information ($zv / $zversion)
Get IRIS version
https://community.intersystems.com/post/importance-and-collection-exact-version-information-zv-zversion
Date before Dec.1840 ? Negative $H(orolog) ?
Negative Dates
https://community.intersystems.com/post/date-dec1840-negative-horolog
Creating a Custom Index Type in Caché
Creating custom indexes
https://community.intersystems.com/post/creating-custom-index-type-cach%C3%A9
$LIST string format and %DynamicArray and %DynamicObject classes
Using $LIST, Dynamic Object, and Dynamic Arrays
https://community.intersystems.com/post/list-string-format-and-dynamicarray-and-dynamicobject-classes
SQL for ^ERROR Global
Use SQL to see Error content
https://community.intersystems.com/post/sql-error-global
Add a default setting value by code
Setting default values
https://community.intersystems.com/post/add-default-setting-value-code
Iterate over dynamic object
Use Iterate
https://community.intersystems.com/post/iterate-over-dynamic-object
Listing all of the properties in a class (and why I love ObjectScript)
ObjectScript properties iteration
https://community.intersystems.com/post/listing-all-properties-class-and-why-i-love-objectscript
Try catch block I usually use in InterSystems ObjectScript
Try Catch handling
https://community.intersystems.com/post/try-catch-block-i-usually-use-intersystems-objectscript
Running shell commands in ObjectScript
Run shell commands
https://community.intersystems.com/post/running-shell-commands-objectscript
Embedded Python
Python is one of the most popular and commonly used programming languages in the world (https://www.tiobe.com/tiobe-index/). InterSystems IRIS is a data platform open to all main programming languages. However, speaking about Python, this amazing language and its libraries are available for use everywhere in IRIS: in classes, SQL, and integrations/productions. For those who do not know or do not want to know ObjectScript (InterSystems programming language), it's a great option. See the following articles on how to do this:
Title
Description
URL
Let's fight against the machines
Build a tic tac toe game using Embedded Python
https://community.intersystems.com/post/lets-fight-against-machines
InterSystems IRIS 2021.2+ Python Examples (Embedded, Native APIs and Notebooks)
See Python and IRIS on some Python notebooks
https://community.intersystems.com/post/intersystems-iris-20212-python-examples-embedded-native-apis-and-notebooks
WebSocket Client with embedded Python
Custom Socket sample
https://community.intersystems.com/post/websocket-client-embedded-python
IRIS Python Native API in AWS Lambda
Python on AWS
https://community.intersystems.com/post/iris-python-native-api-aws-lambda
How I added ObjectScript to Jupyter Notebooks
IRIS on notebooks
https://community.intersystems.com/post/how-i-added-objectscript-jupyter-notebooks
Welcome Django
Create Python Django apps with IRIS as a database
https://community.intersystems.com/post/welcome-django
Geocoding with IRIS and Google Maps API
Using Geocoding python library
https://community.intersystems.com/post/geocoding-iris-and-google-maps-api
REST Service for Convert text to audio using IRIS and Python gTTS
Python sample using gTTS
https://community.intersystems.com/post/rest-service-convert-text-audio-using-iris-and-python-gtts
Building IRIS Responsive dashboard with Python Flask Web Framework
Flesk web app with IRIS
https://community.intersystems.com/post/building-iris-responsive-dashboard-python-flask-web-framework
JSON
JSON is one of the most widely used interoperability formats for sending and receiving data on the market. InterSystems IRIS supports this format in several ways. It is possible to have your native database in JSON (DocDB), serialize and deserialize objects, and process requests and responses in JSON, especially from REST services. Review the following articles:
Title
Description
URL
Introducing new JSON capabilities in Caché 2016.1
Presenting ObjectScript JSON API
https://community.intersystems.com/post/introducing-new-json-capabilities-cach%C3%A9-20161
JSON Enhancements
JSON Adaptor API
https://community.intersystems.com/post/json-enhancements
API and REST Applications
Backend applications are currently developed in the REST (Representational State Transfer) paradigm and are exposed as Web APIs. The following articles will help you see how it works:
Title
Description
URL
GraphQL for InterSystems Data Platforms
Create REST API with GraphQL style
https://community.intersystems.com/post/graphql-intersystems-data-platforms
Introducing InterSystems API Manager
API Management overview
https://community.intersystems.com/post/introducing-intersystems-api-manager
Advanced URL mapping for REST
Mapping routes to your APIs
https://community.intersystems.com/post/advanced-url-mapping-rest
AppS.REST - a new REST framework for InterSystems IRIS
Create REST apps easily
https://community.intersystems.com/post/appsrest-new-rest-framework-intersystems-iris
RESTForms - REST API for your classes
Create REST API for CRUD applications
https://community.intersystems.com/post/restforms-rest-api-your-classes
Developing REST API with a spec-first approach
Contract First Approach to develop APIs
https://community.intersystems.com/post/developing-rest-api-spec-first-approach
ObjectScript REST API Cookbook
REST API development tips
https://community.intersystems.com/post/objectscript-rest-api-cookbook
Generate Swagger spec from persistent and serial classes
Contract First Approach to develop APIs
https://community.intersystems.com/post/generate-swagger-spec-persistent-and-serial-classes
InterSystems IRIS REST Application Patterns
Create API REST using IRIS
https://community.intersystems.com/post/intersystems-iris-rest-application-patterns
Let's create an FHIR profile using SUSHI Part 1
Create custom FHIR profiles
https://community.intersystems.com/post/lets-create-fhir-profile-using-sushi-part-1
IAM (InterSystems API Manager), Zero to Hero
Manage your APIs with IAM
https://community.intersystems.com/post/iam-intersystems-api-manager-zero-hero
Using InterSystems API Management to Load Balance an API
Use APIM to do API load balance
https://community.intersystems.com/post/using-intersystems-api-management-load-balance-api
Securing your APIs with OAuth 2.0 in InterSystems API Management – Part 1
Secure your API using APIM
https://community.intersystems.com/post/securing-your-apis-oauth-20-intersystems-api-management-%E2%80%93-part-1
Getting an Angular UI for your InterSystems IRIS application in 5 minutes
Full Stack app with IRIS and Angular
https://community.intersystems.com/post/getting-angular-ui-your-intersystems-iris-application-5-minutes
Upload into an InterSystems IRIS REST API
Save files using REST API
https://community.intersystems.com/post/upload-intersystems-iris-rest-api
Manage and Configure InterSystems Environments
The good management and configuration of IRIS environments are essential for the performance, security, availability, and reliability of the applications used by users. These articles can give you excellent tips on how to do this.
Title
Description
URL
InterSystems Data Platforms Capacity Planning and Performance Series Index
Capacity and Performance improvement
https://community.intersystems.com/post/intersystems-data-platforms-capacity-planning-and-performance-series-index
Deploying Applications in InterSystems Cache with %Installer
Using %Installer to create namespaces, databases, and applications configuration
https://community.intersystems.com/post/deploying-applications-intersystems-cache-installer
Horizontal Scalability with InterSystems IRIS
Set IRIS instances for horizontal scalability
https://community.intersystems.com/post/horizontal-scalability-intersystems-iris
The InterSystems Iris Fhirserver running on a Raspberry Pi Raspberry running as a FHIRserver
Run IRIS inside Raspberry PI
https://community.intersystems.com/post/intersystems-iris-fhirserver-running-raspberry-pi-raspberry-running-fhirserver
Database Mirroring without a Virtual IP Address
Set mirrors using VIP
https://community.intersystems.com/post/database-mirroring-without-virtual-ip-address
Apache Web Gateway with Docker
Configure SSL and Web Gateway for web applications
https://community.intersystems.com/post/apache-web-gateway-docker
Work with SAML in IRIS
SAML to Web services
https://community.intersystems.com/post/work-saml-iris
Mastering the %SYSTEM.Encryption class
Encrypt and decrypt using IRIS
https://community.intersystems.com/post/mastering-systemencryption-class
Docker and Cloud
The new application architectures work in container Docker and in the cloud, aiming to achieve elastic scalability, shorter installation, configuration, and provisioning times, and reduced infrastructure complexity and cost. Study these articles to learn how to bring IRIS to the cloud:
Title
Description
URL
Highly available IRIS deployment on Kubernetes without mirroring
IRIS on cloud clusters with Kubernetes
https://community.intersystems.com/post/highly-available-iris-deployment-kubernetes-without-mirroring
InterSystems IRIS Example Reference Architectures for Amazon Web Services (AWS)
IRIS on AWS
https://community.intersystems.com/post/intersystems-iris-example-reference-architectures-amazon-web-services-aws
InterSystems Example Reference Architecture for Microsoft Azure Resource Manager (ARM)
IRIS on Azure with cheap machines (ARM machines)
https://community.intersystems.com/post/intersystems-example-reference-architecture-microsoft-azure-resource-manager-arm
Dockerfile and Friends or How to Run and Collaborate to ObjectScript Projects on InterSystems IRIS
Learn about important files on Docker projects
https://community.intersystems.com/post/dockerfile-and-friends-or-how-run-and-collaborate-objectscript-projects-intersystems-iris
InterSystems IRIS Deployment Guide for AWS using CloudFormation template
IRIS on AWS using CloudFormation
https://community.intersystems.com/post/intersystems-iris-deployment%C2%A0guide-aws%C2%A0using-cloudformation-template
InterSystems IRIS Example Reference Architectures for Google Cloud Platform (GCP)
IRIS on Google Cloud
https://community.intersystems.com/post/intersystems-iris-example-reference-architectures-google-cloud-platform-gcp
Using AWS Glue with InterSystems IRIS
Using IRIS and AWS Glue (AWS ETL tool)
https://community.intersystems.com/post/using-aws-glue-intersystems-iris
Amazon EKS and IRIS. High Availability and Backup
IRIS on HA with AWS
https://community.intersystems.com/post/amazon-eks-and-iris-high-availability-and-backup
Running InterSystems Reports in containers
IRIS reports on Docker
https://community.intersystems.com/post/running-intersystems-reports-containers
Running InterSystems IRIS in a FaaS mode with Kubeless
IRIS on Kubernetes
https://community.intersystems.com/post/running-intersystems-iris-faas-mode-kubeless
InterSystems Kubernetes Operator Deep Dive: Introduction to Kubernetes Operators
IRIS on Kubernetes
https://community.intersystems.com/post/intersystems-kubernetes-operator-deep-dive-introduction-kubernetes-operators
Scaling Cloud Hosts and Reconfiguring InterSystems IRIS
Scaling IRIS on AWS, Azure, or GCP
https://community.intersystems.com/post/scaling-cloud-hosts-and-reconfiguring-intersystems-iris
Deploying a Simple IRIS-Based Web Application Using Amazon EKS
IRIS on AWS
https://community.intersystems.com/post/deploying-simple-iris-based-web-application-using-amazon-eks
VSCode
VSCode is one of the most used development IDE in the world. IRIS fully supports this IDE. See the following articles:
Title
Description
URL
VSCode-ObjectScript on GitHub
Develop IRIS apps into Web Github VSCode
https://community.intersystems.com/post/vscode-objectscript-github
GitHub Codespaces with IRIS
Develop IRIS apps into Web Github
https://community.intersystems.com/post/github-codespaces-iris
VSCode Tips & Tricks - SOAP Wizard
Create shortcut option on VSCode
https://community.intersystems.com/post/vscode-tips-tricks-soap-wizard
Adding your own snippets to VS Code
Create snippets
https://community.intersystems.com/post/adding-your-own-snippets-vs-code
SQL
SQL is one of the most used language for dealing with relational databases. These articles demonstrate how to perform queries and data persistence:
Title
Description
URL
Free Text Search: The Way To Search Your Text Fields That SQL Developers Are Hiding From You!*
Using Indexes to promote advanced search
https://community.intersystems.com/post/free-text-search-way-search-your-text-fields-sql-developers-are-hiding-you
Improve SQL Performance for Date Range Queries
Do SQL Queries using dates
https://community.intersystems.com/post/improve-sql-performance-date-range-queries
Static WHERE Conditions
Where on Persistent Classes
https://community.intersystems.com/post/static-where-conditions
2021.2 SQL Feature Spotlight - Run Time Plan Choice
Select Runtime SQL Execution Plan
https://community.intersystems.com/post/20212-sql-feature-spotlight-run-time-plan-choice
New in 2020.1: the Universal Query Cache
SQL Cache
https://community.intersystems.com/post/new-20201-universal-query-cache
Materialized Views
Create views inside persistent classes
https://community.intersystems.com/post/materialized-views
Debugging Trick with SQL
Debug SQL commands
https://community.intersystems.com/post/debugging-trick-sql
Using ClassQueries() as Tables
Creating views
https://community.intersystems.com/post/using-classqueries-tables
M:N Relationship
Mapping N to N relationships
https://community.intersystems.com/post/mn-relationship
Reading AWS S3 data on COVID as SQL table in IRIS
Get CSV data from AWS S3 to IRIS table
https://community.intersystems.com/post/reading-aws-s3-data-covid-sql-table-iris
The One Query Performance Trick You NEED to Know? Tune Table!
SQL tunning
https://community.intersystems.com/post/one-query-performance-trick-you-need-know-tune-table
Data Storage - Information You Must Know to Make Good Decisions When Developing
Configure the data storage section on a persistent class to get more performance
https://community.intersystems.com/post/data-storage-information-you-must-know-make-good-decisions-when-developing
Improve SQL Performance for Date Queries, AGAIN!
Tunning SQL queries for dates
https://community.intersystems.com/post/improve-sql-performance-date-queries-again
Scrollable ResultSet Pagination Sample
Paginate SQL results (see comments too)
https://community.intersystems.com/post/scrollable-resultset-pagination-sample
Day 1: Developing with InterSystems Objects and SQL
Concepts about SQL into InterSystems IRIS
https://community.intersystems.com/post/day-1-developing-intersystems-objects-and-sql
DB Migration using SQLgateway
Migrate from PostgreSQL, MySQL, and other databases to IRIS
https://community.intersystems.com/post/db-migration-using-sqlgateway
Importing CSV into the Existing Table in InterSystems IRIS
Import CSV to SQL Table
https://community.intersystems.com/post/importing-csv-existing-table-intersystems-iris
Four Database APIs
SQL APIs
https://community.intersystems.com/post/four-database-apis
Indexing of non-atomic attributes
Create advanced index options
https://community.intersystems.com/post/indexing-non-atomic-attributes
Know Your Indices
Index creation fundamentals
https://community.intersystems.com/post/know-your-indices
Dynamic SQL to Dynamic Object
Use DynamicSQL
https://community.intersystems.com/post/dynamic-sql-dynamic-object
Data migration tool - Part I: from Postgres to IRIS
Series of articles on how to migrate from popular databases to IRIS database
https://community.intersystems.com/post/data-migration-tool-part-i-postgres-iris
Analytics/BI
BI/Analytics allows making decisions based on data analysis in graphs, dashboards, summaries, and detailed tables and based on navigation and data exploration by the analyst user. Here's how to build analytic applications using IRIS:
Title
Description
URL
COVID-19 Analytics on InterSystems IRIS
Create Analytics dashboards to analyze COVID in the world
https://community.intersystems.com/post/covid-19-analytics-intersystems-iris
DeepSee Troubleshooting Guide
Fix problems
https://community.intersystems.com/post/deepsee-troubleshooting-guide
AnalyzeThis – Quick start into InterSystems BI
Quick start into IRIS BI
https://community.intersystems.com/post/analyzethis-%E2%80%93-quick-start-intersystems-bi
Power BI Connector for InterSystems IRIS. Part I
Using IRIS data inside Power BI
https://community.intersystems.com/post/power-bi-connector-intersystems-iris-part-i
Creating Portlets in DeepSee
Analytics Portlets with IRIS BI
https://community.intersystems.com/post/creating-portlets-deepsee
Game Of Throne Analytics or How long is Arya's Stark List
Analytics sample
https://community.intersystems.com/post/game-throne-analytics-or-how-long-aryas-stark-list
DeepSee Web: InterSystems Analytics Visualization with AngularJS. Part 1
Web dashboards using Angular
https://community.intersystems.com/post/deepsee-web-intersystems-analytics-visualization-angularjs-part-1
Building Analytics Solution with IRIS
Present main options to do analytics with IRIS
https://community.intersystems.com/post/building-analytics-solution-iris
Globals
Globals are the key mechanism in IRIS for flexibly storing and retrieving data, whether in SQL, in classes, in JSON documents, in BI cubes, or other custom formats. Take a glimpse at how to do this in the following articles:
Title
Description
URL
The Art of Mapping Globals to Classes 1 of 3
Mapping globals to SQL tables and Objects
https://community.intersystems.com/post/art-mapping-globals-classes-1-3
Globals Are Magic Swords For Managing Data. Part 1
Fundamentals about globals
https://community.intersystems.com/post/globals-are-magic-swords-managing-data-part-1
GlobalToJSON-embeddedPython-pure
Export globals to JSON
https://community.intersystems.com/post/globaltojson-embeddedpython-pure
Transactions in Global InterSystems IRIS
Manage transactions on Globals persistence
https://community.intersystems.com/post/transactions-global-intersystems-iris
Store Mindmaps using Globals
Using globals to persist mindmap data
https://community.intersystems.com/post/store-mindmaps-using-globals
Security
It is critical to ensure security for any application. Security is related to access and authorization management, tracking and auditing transactions, encryption of the stored and transported content, and setting correct configuration parameters to ensure the protection of sensible resources. Read these articles to understand more about how to establish security:
Title
Description
URL
InterSystems IRIS Open Authorization Framework (OAuth 2.0) implementation - part 1
Using OAuth
https://community.intersystems.com/post/intersystems-iris-open-authorization-framework-oauth-20-implementation-part-1
Debugging Web
Debugging CSP and REST apps
https://community.intersystems.com/post/debugging-web
Class Queries in InterSystems IRIS
Defining SQL Queries inside Persistent classes
https://community.intersystems.com/post/class-queries-intersystems-iris
Using the OS certificate store with TLS/SSL
Using OS certificate to do SSL
https://community.intersystems.com/post/using-os-certificate-store-tlsssl
Integrity Check: Speeding it Up or Slowing it Down
Ensure integrity
https://community.intersystems.com/post/integrity-check-speeding-it-or-slowing-it-down
Tracking Data Changes - Audit Log - 1 of 2
Store audit data
https://community.intersystems.com/post/tracking-data-changes-audit-log-1-2
Running the Management Portal (Private Web Server) Over TLS/SSL/HTTPS
Configure SSL to IRIS Web Server
https://community.intersystems.com/post/running-management-portal-private-web-server-over-tlssslhttps
OAuth Authorization and InterSystems IRIS: Taming Trust Protocols
Using OAuth
https://community.intersystems.com/post/oauth-authorization-and-intersystems-iris-taming-trust-protocols
Using Oauth2 with SOAP (Web)Services
Oauth setting for SOAP services
https://community.intersystems.com/post/using-oauth2-soap-webservices
DeepSee: Setting up security - Part 1 of 5
Security on IRIS BI
https://community.intersystems.com/post/deepsee-setting-security-part-1-5
Changes to the security level of the system
Security by default
https://community.intersystems.com/post/changes-security-level-system
DevOps
DevOps is a way to adopt practices and tools that make it possible to automate the fast and quality transition from source code from development (Dev) to production operation (Ops). See how to do this in IRIS.
Title
Description
URL
Continuous Delivery of your InterSystems solution using GitLab - Part I: Git
Continuous delivery with GitLab
https://community.intersystems.com/post/continuous-delivery-your-intersystems-solution-using-gitlab-part-i-git
Introducing InterSystems ObjectScript Package Manager
Use ZPM to configure and install third-party packages inside your application
https://community.intersystems.com/post/introducing-intersystems-objectscript-package-manager
ZPMshow - a helper for tired fingers
How to use ZPM – IRIS Package Manager
https://community.intersystems.com/post/zpmshow-helper-tired-fingers
How to set up a mirror programmatically
Automate the create new mirrors
https://community.intersystems.com/post/how-set-mirror-programmatically
Unit Tests and Test Coverage in the ObjectScript Package Manager
Create Unit Tests for ObjectScript code quality
https://community.intersystems.com/post/unit-tests-and-test-coverage-objectscript-package-manager
Deploying a sharded cluster with Docker and MergeCPF
Automate config using cpf files
https://community.intersystems.com/post/deploying-sharded-cluster-docker-and-mergecpf
Caché ObjectScript Quick Reference
ObjectScript reference pdf document
https://community.intersystems.com/post/cach%C3%A9-objectscript-quick-reference
The Anatomy of ZPM Module: Packaging Your InterSystems Solution
Use ZPM to automate deployment
https://community.intersystems.com/post/anatomy-zpm-module-packaging-your-intersystems-solution
Adding VSCode into your IRIS Container
Embed VSCode inside your docker instance
https://community.intersystems.com/post/adding-vscode-your-iris-container
How to Create New Database, Namespace and Web Application for InterSystems IRIS programmatically
Automate database and namespace creation
https://community.intersystems.com/post/how-create-new-database-namespace-and-web-application-intersystems-iris-programmatically
Unit Tests: Quality of your ObjectScript Code
Quality Assurance with Unit Tests
https://community.intersystems.com/post/unit-tests-quality-your-objectscript-code
Some InterSystems Developer Community Docker Images
Docker community images
https://community.intersystems.com/post/some-intersystems-developer-community-docker-images
Interoperability
IRIS has a powerful data and application interoperability bus. See how to use it with the following articles.
Title
Description
URL
Sending Alerts from Ensemble via Telegram
Production to send data to telegram
https://community.intersystems.com/post/sending-alerts-ensemble-telegram
[InterSystems IRIS for the First Time] Let’s use Interoperability
Create business services, operations, processes, and productions
https://community.intersystems.com/post/intersystems-iris-first-time-let%E2%80%99s-use-interoperability
InterSystems IRIS Interoperability with Embedded Python
Create business services, operations, processes, and productions using Python
https://community.intersystems.com/post/intersystems-iris-interoperability-embedded-python
Ensemble / Interoperability Training Course
Great sample to learn how to create productions
https://community.intersystems.com/post/ensemble-interoperability-training-course
Some Programmatic Interoperability Examples
Programmatic productions using Python or ObjectScript
https://community.intersystems.com/post/some-programmatic-interoperability-examples
Listing files in folder
List files in a folder
https://community.intersystems.com/post/listing-files-folder
Containerising .Net/Java Gateways (or Kafka Integration Demo)
Kafka support using Java or .Net Native API
https://community.intersystems.com/post/containerising-netjava-gateways-or-kafka-integration-demo
Implementing IRIS Integrations with .NET or Java using PEX
Using PEX to create productions using Java or .Net
https://community.intersystems.com/post/implementing-iris-integrations-net-or-java-using-pex
Migrate from Java Business Host to PEX
Using PEX
https://community.intersystems.com/post/migrate-java-business-host-pex
Using Tesseract OCR and Java Gateway
Using Java PEX
https://community.intersystems.com/post/using-tesseract-ocr-and-java-gateway
Creating a PEX Business Operation
Create Java PEX Business Operation
https://community.intersystems.com/post/creating-pex-business-operation
OCR and NLP together into InterSystems IRIS
Java PEX Sample
https://community.intersystems.com/post/ocr-and-nlp-together-intersystems-iris
Creating a custom interoperability business service using an HTTP Adapter
Creating Business Services
https://community.intersystems.com/post/creating-custom-interoperability-business-service-using-http-adapter
Native API
IRIS is open to working with some of the most used programming languages in the market (Java, Javascript/NodeJS, .Net, C++, and Python). To do it we use Native API for each of these languages. Check out these articles:
Title
Description
URL
WebSocket Client JS with IRIS Native API as Docker Micro Server
Using IRIS and NodeJS to do a WebSocket
https://community.intersystems.com/post/websocket-client-js-iris-native-api-docker-micro-server
IRIS Native API for ObjectScript
Using Native APIs
https://community.intersystems.com/post/iris-native-api-objectscript
Using ZPM for Node.js
Using ZPM on Node.js projects
https://community.intersystems.com/post/using-zpm-nodejs
Creating a PDF from a Text file
Java Native API for generating PDF
https://community.intersystems.com/post/creating-pdf-text-file
How to Start Development with InterSystems IRIS in Less Than a Minute
Start to develop using IRIS
https://community.intersystems.com/post/how-start-development-intersystems-iris-less-minute
Making a blog using Python + IRIS Globals
A blog on using Python native API
https://community.intersystems.com/post/making-blog-using-python-iris-globals
wow. Well done, @Yuri.Gomes ! In bookmarks! Thanks! All the Major Learning points in one shot....Great...
Thanks a lot @Yuri.Gomes so IMPRESSIVE - you made the DC knowledge base! We will create a dedicated challenge in GM Academy on Global Masters so people wouldn't miss. Thanks! Thanks Olga! thanks
Question
Erol Gurcinar · Jul 24, 2022
Hi team,
I'll start with an apology as I am trying to wrap my head around the architecture of how InterSystems IRIS database management works. I am attempting to connect to the platform remotely through say a JDBC or ODBC connection in order to run queries, searches (through SQL statements) on my laptop and was trying to understand whether this would be possible? It is possible to setup an inbound client connection and wanted to better understand the architecture of how the database association works for IRIS database management. Does it use it's own internal SQL database or are we able to connect to our own database and which databases are certified to run against the platform?
Regards,
Eddie Hi Eddie.
>Does it use it's own internal SQL database or are we able to connect to our own database and which databases are certified to run against the platform?
Both.
Supported 3rd party databases are listed here:
https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=ISP_technologies#ISP_relgatewaydbs
Generally, please see "First looks" guides in our doc, particularly for JDBC and ODBC:
https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=AFINDEX Hello,
The IRIS management portal is a web application.It connects to the IRIS database with a component called: "CSP Gateway" (can be installed on various web servers: IIS, Apache, Nginx). This "CSP gateway" is enabling you to develop web applications that will interact with the DB directly though this component. You may run "ajax like" code on the server-side, and have all your web pages fully dynamic (generated on the server in run-time).TO work with the management portal from remote, you may take advantage of it's security mechanism (define users, roles, services) the ability to authenticate with external to IRIS entities (e.g. doing LDAP to ADDS) and also have a two-factor authentication, for better security.
Any external data database or other tool that can do ODBC & JDBC can communicate with IRIS and get data out of it. Those are also.
Announcement
Anastasia Dyubaylo · Sep 21, 2022
Hello Community!
We're thrilled to announce yet another type of contest - the contest for the brightest idea! Please welcome:
💡 InterSystems Idea-A-Thon 💡
Suggest an idea related to InterSystems Products and Services between September 26 and October 16 and receive a guaranteed prize.
Moreover, both InterSystems employees and Community Members can participate!
>> Submit your ideas here <<
Rules
InterSystems Idea-A-Thon is organized via the InterSystems Ideas feedback portal where you can submit product enhancement requests and ideas related to our services (Documentation, Dev Community, Global Masters, etc.) and vote for the ones you like.
In this contest, we invite everyone to share their ideas on this portal and vote for others.
To join the contest, you just need to submit an idea on the InterSystems Ideas portal.
Accepted ideas should:
be created during the Idea-A-Thon period by a user registered on the InterSystems Ideas portal (you can log in via InterSystems SSO);
not be part of other already existing ideas - only new ideas are allowed;
not describe the existing functionality of InterSystems Products or Services;
contain, in addition to a title, a detailed and clear explanation of the ideas' essence;
be posted in English;
be accepted as meaningful by experts.
All eligible ideas will have a special “Idea-A-Thon” status on the InterSystems Ideas portal and can be easily found at Idea-A-Thon Ideas.
Who can participate?
We invite EVERYONE to join our Idea-A-Thon. Both InterSystems employees and Community Members are welcome to participate and submit their ideas.
Prizes
1. Participant prize – prizes for everyone who posts an eligible idea:
🎁 InterSystems Branded T-Shirt
2. Expert Award – winner will be selected by the team of InterSystems experts, and will get:
🎁 LEGO Star Wars™ R2-D2™ / BOSE Sleepbuds™ II / BOSE SoundLink Flex Bluetooth® speaker bundle
3. Community Award – an idea with the most votes will get:
🎁 LEGO Star Wars™ R2-D2™ / BOSE Sleepbuds™ II / BOSE SoundLink Flex Bluetooth® speaker bundle
Important note: InterSystems employees can only get the participation prize. Expert and Community awards can only be won by non-InterSystems members of the Community.
Contest period
📝 September 26 - October 16: Publication of ideas and voting period.
Publish an idea(s) throughout this period. Registered members of the Ideas portal can vote for published ideas – these votes are counted towards the Community award.
Note: The sooner you publish your idea(s), the more time you will have to collect votes.
So!
Post your idea(s) on the InterSystems Ideas portal, get prizes, and stay tuned for your idea's status updates!
Good luck 👍
Important note: All prizes are subject to availability and shipping options. Some items may not be available to ship internationally to specific countries. Prizes cannot be delivered to residents of Crimea, Russia, Belarus, Iran, North Korea, Syria, or other US-embargoed countries. We will let you know if a prize is not available and offer a possible replacement. Hey Community,
We're so excited to launch the first InterSystems Idea-A-Thon starting this Monday, September 26th!
Important note: only ideas submitted on Monday from 00:00 AM EDT time are eligible for the competition.
Can't wait to see your brilliant ideas in our Idea-A-Thon! Good luck 👍 Hey Community,
InterSystems Idea-A-Thon just started!
Already 2 bright ideas joined this competition! Please check them here >> Idea-A-Thon Ideas
Don't forget to submit your ideas, vote for the ones you like best, and most importantly, comment on them ;) Hey Community!
Especially for the 1st InterSystems Idea-A-Thon, we've prepared a special promo video for our Ideas portal:
➡️ Welcome to the InterSystems Ideas
Don't forget to submit your ideas until October 16 to join our Idea-Thon ;)
p.s. 44 ideas already in the competition... Hello Community!
Last week of 💡Idea-A-Thon💡 Contest just started!
60 ideas compete for the main prizes!🎁
Two leading ideas are:
Nodejs with IRIS a dynamic platform by @Sharafat Hussain
Code snippets library by @Danny Wijnschenk
➡️ Vote and comment here on your favorite ideas until October 16! Hello Developers!Last call for submitting your ideas! 3 days left until the end of our Idea-A-Thon.⏰➡️ And don't forget to upvote and comment on the ideas you like!
Article
Eduard Lebedyuk · Feb 19, 2016
Suppose you have developed your own app with InterSystems technologies stack and now want to perform multiple deployments on the customers' side. During the development process you've composed a detailed installation guide for your application, because you need to not only import classes, but also fine-tune the environment according to your needs.To address this specific task, InterSystems has created a special tool called %Installer. Read on to find out how to use it.%Installer
Using this tool, you can define the installation manifest, which describes the desired Caché configuration instead of the installation steps. You need only to describe what you want, and Caché will automatically generate the necessary code to modify the environment for you. Therefore, you should distribute only the manifest itself, while all the installation code will be generated for the specific Caché server at compile time.To define a manifest, create a new XData block with detailed description of the target configuration and then implement a method to generate Caché ObjectScript code for this XData block (this code is always the same). Once the manifest is ready, you can access it from a terminal or Caché ObjectScript code or automatically during Caché installation. The manifest must be executed in the %SYS namespace. Manifests can handle both system parameters (superport, OS, mgr directory, etc.) and arbitrary user-supplied parameters. In general, each installation class must meet the following requirements:
Contain a link to %occInclude.incContain an XData block with the Caché server configurationThe block can be have any valid nameAdd [XMLNamespace = INSTALLER] after the block's name if you want to see prompts from StudioThe root item (there must only be one) is called <Manifest> and comprises all other itemsYou also need to implement the setup() method which will generate the necessary program code for the XData block.
Installer basics
You can execute an installation manifest in several ways:
In the %SYS namespace using a terminal or from a Caché ObjectScript code
do ##class(MyPackage.MyInstaller).setup()
Automatically during the installation of Caché. To do this, export the installer's class into DefaultInstallerClass.xml stored in the folder with Caché installation package (i.e. where setup_cache.exe or cinstall are stored). During Caché installation, this class will be imported into the %SYS namespace and executed via the setup() method.
Example
Let's consider a simple example. Create the class called App.Installer containing an installer that will generate a new namespace with the user-defined name, create default web app and import code into this new namespace:
Include %occInclude
Class App.Installer {
/// You can see generated method in zsetup+1^App.Installer.1
XData Install [ XMLNamespace = INSTALLER ]
{
<Manifest>
<If Condition='(##class(Config.Namespaces).Exists("${Namespace}")=0)'>
<Log Text="Creating namespace ${Namespace}" Level="0"/>
<Namespace Name="${Namespace}" Create="yes" Code="${Namespace}" Ensemble="0" Data="${Namespace}">
<Configuration>
<Database Name="${Namespace}" Dir="${MGRDIR}${Namespace}" Create="yes"/>
</Configuration>
</Namespace>
<Log Text="End Creating namespace ${Namespace}" Level="0"/>
</If>
<Role Name="AppRole" Description="Role to access and use the App" Resources="%DB_CACHESYS:RW,%Admin_Secure:U" />
<Namespace Name="${Namespace}" Create="no">
<CSPApplication Url="/csp/${Namespace}" Directory="${CSPDIR}${Namespace}" AuthenticationMethods="64" IsNamespaceDefault="true" Grant="AppRole" />
<IfDef Var="SourceDir">
<Log Text="SourceDir defined - offline install from ${SourceDir}" Level="0"/>
<Import File="${SourceDir}"/>
</IfDef>
</Namespace>
</Manifest>
}
///Entry point method, you need to call
/// At class compile time it generate Caché ObjectScript code from the manifest
/// After that you can run this installer from a terminal:
/// Set pVars("Namespace")="NewNamespace"
/// Set pVars("SourceDir")="C:\temp\distr\"
/// Do ##class(App.Installer).setup(.pVars)
ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 0, pInstaller As %Installer.Installer) As %Status [ CodeMode = objectgenerator, Internal ]
{
Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "Install")
}
}
In this example, installer performs the following actions:
Checks if a namespace with the same name as the value of Namespace variable exists (for clarity let's specify that the Namespace variable is set to NewNamespace)If not, then logs that a new namespace called NewNamespace will be createdDefines a new namespace:Name is NewNamespaceCreates a new namespaceRoutines database is NewNamespaceDo not enable EnsembleGlobals database is NewNamespaceCreates a new databaseName is NewNamespace;Creates it in the mgr/NewNamespace folder (note that the MGRDIR variable is available by default)Creation of the namespace is completed and loggedCreates new role: AppRole (with resources %DB_CACHESYS:RW and %Admin_Secure:U)Default web application /csp/NewNamespace is created (it also grants AppRole automatically)If SourceDir variable is defined then imports all files from there into NewNamespace
To run this installer in a terminal, execute the following commands:
Set pVars("Namespace")="NewNamespace"
Set pVars("SourceDir")="C:\temp\distr\"
Do ##class(App.Installer).setup(.pVars)
During execution terminal displays relevant information:
2016-02-17 19:26:17 0 App.Installer: Installation starting at 2016-02-17 19:26:17, LogLevel=0
2016-02-17 19:26:17 0 : Creating namespace NewNamespace
2016-02-17 19:26:17 0 : End Creating namespace NewNamespace
2016-02-17 19:26:17 0 : SourceDir defined - offline install from C:\temp\distr\
2016-02-17 19:26:18 0 App.Installer: Installation succeeded at 2016-02-17 19:26:18
2016-02-17 19:26:18 0 %Installer: Elapsed time .545148s
To receive even more information about what is going on specify LogLevel (from 0 (default) to 3 (raw); higher number = more information).
Do ##class(App.Installer).setup(.pVars, 3)
Now let's talk about what can be done in installer manifest.
Availible nodes
A manifest is composed of the following items:
NodeParent nodeAttributes (default values)DescriptionArgInvoke, ErrorValue – value of an argumentPasses an argument into a method called via Invoke or ErrorClassMappingConfigurationPackage – a package to be mappedFrom – name of the source database used for mappingCreates a class mapping from a database to the namespace which contains this Configuration itemCompileNamespaceClass – names of classes for compilationFlags – compilation flags (ck)IgnoreErrors – ignore errors (0)Compilers classes. Calls $System.OBJ.Compile(Class, Flags)ConfigurationNamespace Used for creating namespaces and databases. Closing tag activates mappings and updates the CPF fileCopyClassNamespaceSrc — source classTarget — target classReplace — remove the source class (0)Copies or moves the source class definition to the target oneCopyDirManifestSrc — source directoryTarget — target directoryIgnoreErrors — ignore errors (0)Copies a directoryCopyFileManifestSrc — source fileTarget — target fileIgnoreErrors — ignore errors (0)Copies a fileCredentialProductionName – name of the access credentialsUsername – user namePassword – user passwordOverwrite – overwrite if the account already existsCreates or overrides the access credentialsCSPApplicationNamespaceAuthenticationMethods – enabled authentication methodsAutoCompile – automatic compilation (in CSP settings)CSPZENEnabled – the CSP/ZEN flagChangePasswordPage – path to change password pageCookiePath – session cookie pathCustomErrorPage – path to custom error pageDefaultSuperclass – default superclassDefaultTimeout – session timeoutDescription – descriptionDirectory – path to CSP filesEventClass – event class nameGrant – list of roles assigned upon logging into the systemGroupById – group by Id propertyInboundWebServicesEnabled – inbound web services flagIsNamespaceDefault – Namespace Default Application flagLockCSPName – Lock CSP Name flagLoginClass – path to login pagePackageName – package name propertyPermittedClasses – permitted classes propertRecurse – recurce flag (serve subdirectories) (0)Resource – resource required to access web appServeFiles – service files propertyServeFilesTimeout – time, in seconds, of how long to cache static files.TwoFactorEnabled – two-step authenticationUrl – name of the web applicationUseSessionCookie – use cookies for the sessionCreates or modifies a web application. For details, refer to documentation and the Security.Applications classDatabaseConfigurationBlockSize – block size in bytes of the databaseClusterMountMode – mount the database as a part of the clusterCollation – sorting orderCreate – whether to create a new database (yes/no/overwrite (yes))Dir – directoryEncrypted – encrypt databaseEncryptionKeyID – ID of the encryption keyExpansionSize – size in MB to expand byInitialSize – initial sizeMaximumSize – maximum sizeMountAtStartup – mount upon launchMountRequired – specifies that the database MUST be successfully mounted at startup.Name – database namePublicPermissions – public permissionsResource – resourceStreamLocation – directory where the streams associated with this database go.Creates or modifies a database. For details, refer to documentation, the Config.Databases and SYS.Database classesDefaultManifestName – variable nameValue – variable valueDir – variable value (if this is a path to a folder/file)Sets the variable value (if it is not set yet)ElseManifest, NamespaceWill be executed when the if statement is falseErrorManifestStatus – error codeSource – source of the errorThrows an exception. Note that ${} and #{} syntax is not availableForEachManifestIndex – variable nameValues – list of values for the variableCollection-controlled loopGlobalMappingConfigurationGlobal – global nameFrom – name of the database for mapping
Collation – sorting order (Caché Standard)Maps a globalIfManifest, NamespaceCondition – a conditional statementConditional if statementIfDefManifest, NamespaceVar – variable nameConditional if statement used when the variable is already setIfNotDefManifest, NamespaceVar – variable nameConditional if statement used when the variable is not set yetImportNamespaceFile – file/folder for importFlags — compilation flags (ck)IgnoreErrors — ignore errors (0)Recurse – import recursively (0)Imports files. Calls:$System.OBJ.ImportDir(File,,Flags,,Recurse) and $System.OBJ.Load(File, Flags)InvokeNamespaceClass – class nameMethod – method nameCheckStatus – check the returned statusReturn – write the result into a variableMakes a call to a method of a class with various arguments and returns the execution resultsLoadPageNamespaceName – path to the CSP pageDir – folder with CSP pagesFlags — compilation flags (ck)IgnoreErrors — ignore errors (0)Loads CSP file using $System.CSP.LoadPage(Name, Flags) and $System.CSP.LoadPageDir(Dir, Flags)LogManifestLevel – logging level from 0 (minimum) up to 3 (detailed)Text – string up to 32,000 characters in lengthAdds a message to a log when the logging level is greater or equal to the "level" attributeManifest Root item. The only one root item in a manifest; contains all other itemsNamespaceManifestName – name of the namespaceCreate – whether to create a new namespace (yes/no/overwrite (yes))Code – database for program codeData – databaseEnsemble – enable Ensemble for the namespaceAll other attributes are applicable to the Ensemble web applicationsDefines the installer's scopeProductionNamespaceName – production nameAutoStart – automatic launch of the productionConfigures the Ensemble productionResourceManifestName – resource nameDescription – resource descriptionPermission – public permissionsCreates or modifies a resource.RoleManifestName – name of the roleDescription – role description (can't contain commas)Resources – resourcesgiven to role, represented as "MyResource:RW,MyResource1:RWU"
RolesGranted – whether to grant the corresponding rolesCreates a new roleRoutineMappingConfigurationRoutines – routine nameType – routines type (MAC, INT, INC, OBJ or ALL)From – source databaseCreates a new mapping for routinesSettingProductionItem – configurable itemTarget – parameter type: Item, Host, AdapterSetting – parameter nameValue – parameter valueConfigures an item in the Ensemble production Makes a call to the Ens.Production:ApplySettings methodSystemSettingManifestName – class.property of the Config packageValue – attribute valueSets the values for attributes of the Config package (using the Modify method)UserManifestUsername – user namePasswordVar – variable containing the passwordRoles – list of user's rolesFullname – full nameNamespace – startup namespaceRoutine – starting routineExpirationDate – date after which the user will be deactivatedChangePassword – change the password upon next login into the systemEnabled – whether the user is activatedCreates or modifies a user.VarManifestName — variable nameValue – variable valueAssigns a value to the variable
Variables
User-supplied variables
Some attributes can contain expressions (strings) that are expanded when the manifest is executed. There are three types of expressions that can be expanded, as follows:
${<Variable_name>} – value of the variable (user-defined or environment variable; see below) is calculated during the execution of the manifest;${#<Parameter_name>} – will be replaced with the value of the specified parameter from the installer's class during compilation;#{<Caché_ObjectScript_code>} — the value of the specified Caché ObjectScript statement will be calculated during the execution of the manifest. Make sure to put quotation marks as required.
Parameter values are defined during compilation and therefore can be a part of a variable or Caché ObjectScript statement. Since variables are interpreted before the Caché ObjectScript code, you can use them in Caché ObjectScript statements, e.g: #{$ZCVT("${NAMESPACE}","L")}.
System variables
The following variables are always available:
VariableDescriptionSample valueSourceDir(Available only when the installer is run) Directory from which the installation (setup_cache.exe or cinstall) is running./InterSystems/distr/ISCUpgrade(Available only when the installer is run) Indicates whether this is a new installation or an upgrade. This variable is either 0 (new installation) or 1 (upgrade).0 (installation)1 (update)CFGDIRSee INSTALLDIR./InterSystems/Cache/CFGFILEPath to the CPF file/InterSystems/Cache/cache.cpfCFGNAMEName of the instanceCACHECPUCOUNTNumber of CPU cores4CSPDIRThe CSP directory/InterSystems/Cache/csp/HOSTNAMEName of the web serverSCHOOL15HTTPPORTPort of the web server80INSTALLDIRDirectory where Caché is installed/InterSystems/Cache/MGRDIRManagement directory (mgr)/InterSystems/Cache/mgr/PLATFORMOperating systemUNIXPORTPort of the Caché superserver1972PROCESSORName of the platformx86-64VERSIONVersion of Caché2015.1.1
Debugging
Sometimes it may be hard to understand what values can be assigned as node attributes' values. To figure this out, check the generated int code for the setup method. In most cases, the main call is made to the tInstaller.<ElementName> which is an object of the %Installer.Installer class which, in turn, will make direct calls to the system methods. Alternatively, you can check the code of the %Installer.<ElementName> class in which the node attributes are class properties. The program code is generated in the %OnBeforeGenerateCode, %OnGenerateCode and %OnAfterGenerateCode methods.For debugging purposes, I recommend that you wrap a call to the installer into a transaction. For example, you can use the TSTART/TROLLBACK commands to easily undo all changes made within Caché (however, external changes, such as creating a new database file, will not be reverted).
Lastly, don't forget to set LogLevel to 3.
Examples
The MDX2JSON project provides an installer. To install the project, import the installer.xml file containing the MDX2JSON.Installer class into any namespace. You can perform import either from the SMP or by drag&dropping the file into Studio.Then run the following command in a terminal:
do ##class(MDX2JSON.Installer).setup()
As a result, Caché will load application files from the GitHub repository and then perform installation in the default MDX2JSON namespace/MDX2JSON database, map the MDX2SJON package to %All and SAMPLES, map the ^MDX2SJON global to %All and SAMPLES create the REST application called /MDX2JSON, and so on – you will see all these steps in the terminal. For more detailed information on MDX2JSON installer, please refer to the project readme.
Even more examples
Example from the documentation.The Sample.Installer class in the Samples namespace.The CacheGitHubCI projects provides an installer.The SYSMON Dashboards project provides an installer.The DeepSee Audit project provides an installer.
Summary
%Installer is a convenient tool for distributing and deploying applications based on InterSystems Caché and Ensemble.
References
Documentation Great article.I like to use this approach with CacheUpdater tool. It adds a Task in Caché with parameters of github repo URL and credentials if needed.So if I need to update the app with new code from github repo I just run the task. @Eduard.Lebedyuk it is possible to import a HL7 Schema from Installer? Hi David! How does HL7 schema look like? Is it a class or Global or what? How do you import an HL7 Schema from ObjectScript?
You can call any method with Invoke.
I'm not aware of anything HL7 specific in %Installer, but maybe HealthShare has something. I see.
So I guess I should use EnsLib.HL7.SchemaDocument class https://docs.intersystems.com/irisforhealthlatest/csp/documatic/%25CSP.Documatic.cls?APP=1&LIBRARY=ENSLIB&CLASSNAME=EnsLib.HL7.SchemaDocument but can't find an example of how import/export programatically.
In response to @Evgeny.Shvarov I am talking about Custom HL7 Schemas (https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.cls?KEY=EHL72_tools#EHL72_customhl7schema_editor) in IRIS for Health. Use custom schemas is something very usual and I think that to include this import feature in Installer could be very useful... I'll try to make it works and if I am success I'll post the how-to :-D ##class(EnsLib.EDI.XML.SchemaXSD).Import("C:\path\to\schema.xsd") Do auto install using DefaultInstallerClass.xml wotk with IRIS For Health? In my expirience it does not. But after IRIS is installed I can manualy import the DefaultInstallerClass.xml and run the setup method in terminal and it works.
That is how my install package looks:
Maybe I'm missing something. Looks like it doesn't work with single file kits https://docs.intersystems.com/iris20222/csp/docbook/DocBook.UI.Page.cls?KEY=GCI_manifest#GCI_manifest_invoke_auto Thanks for this!