Search

Clear filter
Question
Rob Rubinson · Nov 28, 2021

InterSystems ODBC driver backwards compatible?

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

InterSystems IRIS REST Application Patterns

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

What is InterSystems SSO social account?

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

Big Data components and the InterSystems IRIS

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

French Stream On InterSystems Technologies #6

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

InterSystems ObjectScript 101++ (EN)

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

Video: Data Warehousing with InterSystems IRIS

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

[Video] InterSystems IRIS Container Updates

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

[Video] Containerizing InterSystems IRIS Applications

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

InterSystems UK & Ireland Summit 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

Updated Exercise - Healthcare Analytics with InterSystems

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

Learning InterSystems by Developer Community Articles

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

InterSystems - Database Management / Remote Connectivity

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

The 1st InterSystems Idea-A-Thon

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

Deploying Applications in InterSystems Cache with %Installer

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!