Clear filter
Question
Bren Mochocki · Aug 16, 2021
It appears the link to download IRIS is down:https://download.intersystems.com/download/login.csp
!
Announcement
Anastasia Dyubaylo · Aug 9, 2021
Hey Developers,
Watch the new video on InterSystems Developers YouTube:
⏯ Adaptive Analytics in InterSystems IRIS
Get an overview of InterSystems IRIS Adaptive Analytics, which brings ease-of-use and scalability to analytics end-users. Learn more about the benefits and availability of this new offering, announced in October 2020.
🗣 Presenter: @Carmen.Logue, Product Manager - Analytics and AI, InterSystems
Enjoy and stay tuned!
Announcement
Anastasia Dyubaylo · Nov 25, 2021
Hey Community,
We invite you to join the next French stream on InterSystems Technologies #7, hosted by @Guillaume.Rongier7183!
Date & Time: December 2nd, 12:00 Paris time.
👉 Direct link to join: https://bit.ly/30UV6xp
On the agenda this month:
🗞 News
https://community.intersystems.com/post/sql-search-index-json-objects#comments0
https://community.intersystems.com/post/how-script-download-installation-kits-wrc
SQL Load statement demo:
https://docs.intersystems.com/iris20212/csp/docbook/DocBook.UI.Page.cls?KEY=RSQL_loaddata
Tradeshows & Conferences :
https://santexpo.live/
https://www.supplychain-event.com/
https://www.aiforhealth.fr/
https://www.meetup.com/fr-FR/FHIR-France/events/278358909/
💡 Did you know?
Data type: VarString vs String
Neat trick: how to change max RAM process limit on the fly (OnInit + $ZStorage)
🗂 Focus on
Python & InterSystems IRIS: How to interact with InterSystems IRIS in Python
Don’t miss the French Stream #7 👉 https://bit.ly/30UV6xp
Enjoy watching the prev streams on YouTube:
Stream #1
Stream #2
Stream #3
Stream #4
Stream #5
Stream #6
Stay tuned!
Announcement
Anastasia Dyubaylo · Nov 29, 2021
Hey Developers,
This week is a voting week for the InterSystems Security contest! So, it's time to give your vote to the best solutions built with InterSystems IRIS.
🔥 You decide: VOTING IS HERE 🔥
How to vote? Details below.
Experts nomination:
InterSystems experienced jury will choose the best apps to nominate the prizes in the Experts Nomination. Please welcome our experts:
⭐️ @Andreas.Dieckow, Principal Product Manager⭐️ @Robert.Kuszewski, Product Manager⭐️ @Raj.Singh5479, Product Manager⭐️ @Sean.Klingensmith, Senior Systems Developer⭐️ @Wanqing.Chen, Systems Developer⭐️ @Pravin.Barton, Developer⭐️ @Timothy.Leavitt, Development Manager⭐️ @Francois.LeFloch, Senior Solutions Engineer⭐️ @Marc.Mundt, Senior Sales Engineer⭐️ @Eduard.Lebedyuk, Sales Engineer⭐️ @Alberto.Fuentes, Sales Engineer⭐️ @Guillaume.Rongier7183, Sales Engineer⭐️ @Evgeny.Shvarov, Developer Ecosystem Manager
Community nomination:
For each user, a higher score is selected from two categories below:
Conditions
Place
1st
2nd
3rd
If you have an article posted on DC and an app uploaded to Open Exchange (OEX)
9
6
3
If you have at least 1 article posted on DC or 1 app uploaded to OEX
6
4
2
If you make any valid contribution to DC (posted a comment/question, etc.)
3
2
1
Level
Place
1st
2nd
3rd
VIP Global Masters level or ISC Product Managers
15
10
5
Ambassador GM level
12
8
4
Expert GM level or DC Moderators
9
6
3
Specialist GM level
6
4
2
Advocate GM level or ISC Employees
3
2
1
Blind vote!
The number of votes for each app will be hidden from everyone. Once a day we will publish the leaderboard in the comments to this post.
The order of projects on the Contest Page will be as follows: the earlier an application was submitted to the competition, the higher it will be in the list.
P.S. Don't forget to subscribe to this post (click on the bell icon) to be notified of new comments.
To take part in the voting, you need:
Sign in to Open Exchange – DC credentials will work.
Make any valid contribution to the Developer Community – answer or ask questions, write an article, contribute applications on Open Exchange – and you'll be able to vote. Check this post on the options to make helpful contributions to the Developer Community.
If you changed your mind, cancel the choice and give your vote to another application!
Support the application you like!
Note: contest participants are allowed to fix the bugs and make improvements to their applications during the voting week, so don't miss and subscribe to application releases! I liked the new expert method to choose the best apps, congrats! So! After the first day of the voting we have:
Expert Nomination, Top 3
iris-disguise by @Henry.HamonPereira
IRIS Middlewares by @davimassaru.teixeiramuta
zap-api-scan-sample by @José.Pereira
➡️ Voting is here.
Community Nomination, Top 3
Server Manager 3.0 Preview by @John.Murray
passwords-tool by @Dmitry.Maslenniko
iris-disguise by @Henry.HamonPereira
➡️ Voting is here.
Experts, we are waiting for your votes! 🔥
Participants, improve & promote your solutions! Here are the results after 2 days of voting:
Expert Nomination, Top 3
iris-disguise by @Henry Pereira
Server Manager 3.0 Preview by @John.Murray
zap-api-scan-sample by @José Roberto Pereira
➡️ Voting is here.
Community Nomination, Top 3
iris-disguise by @Henry Pereira
Server Manager 3.0 Preview by @John Murray
passwords-tool by @Dmitry.Maslennikov
➡️ Voting is here.
So, the voting continues.
Please support the application you like! Voting for the InterSystems Security contest goes ahead!
And here're the results at the moment:
Expert Nomination, Top 3
iris-disguise by @Henry Pereira
Data_APP_Security by @Muhammad.Waseem
iris-saml-example by @Dmitry.Maslennikov
➡️ Voting is here.
Community Nomination, Top 3
iris-disguise by @Henry Pereira
API Security Mediator by @Yuri.Gomes
zap-api-scan-sample by @José.Pereira
➡️ Voting is here. In the expert vote, how many points are computed for each expert's vote? Developers!
Only 3 days left till the end of the voting period. Please support our participants with your votes!
At the moment we have next results:
Expert Nomination, Top 3
iris-disguise by @Henry Pereira
iris-saml-example by @Dmitry.Maslennikov
zap-api-scan-sample by @José Roberto Pereira
➡️ Voting is here.
Community Nomination, Top 3
iris-disguise by @Henry Pereira
zap-api-scan-sample by @José Roberto Pereira
API Security Mediato by @Yuri.Gomes
➡️ Voting is here.
Have a good weekend) Hey Yuri, I don't have this info. But from my point of view, it's pointless to know that, since we don't have the information of "current points". They changed the way of showing that for a reason, and this is where the fun lives. It will be a thriller until the end, and that's ok. Last day of voting! ⌛
Please check out the Contest Board.Our contestants need your votes! 📢
Question
Rob Rubinson · Nov 28, 2021
Is InterSystems ODBC driver backwards compatible? If I use cache version 2018, can I upgrade the ODBC drivers to the 2021 version or it is better to upgrade to the 2018? Rob, the ODBC drivers for IRIS are not compatible with Caché and Ensemble.
Erik what about the ODBC drivers not for IRIS? Earlier ODBC driver versions should be compatible with Caché 2018.1, but we recommend updating clients to the latest driver for your Caché version. There aren't any 2021.x ODBC drivers for Caché on the WRC download page. If you have one and you want to be sure you have a good driver, reach out to the WRC so we can understand your specific situation.
Erik
Article
Yuri Marx Pereira Gomes · Aug 2, 2021
This article suggests to you some patterns to create REST API applications using IRIS.
Note: source code in https://github.com/yurimarx/movie
Class Pattern to the REST Application
To begin, see my suggestion for classes needed to create IRIS API applications:
IRISRESTApplication: CSP.REST class that will be the central controller for all REST requests and responses processed by the business services.
BusinessService: class with a business topic implementation. It can use one or more Persistent Domain Classes to persist and query data required by the business topic requirements.
Persistent Domain: persistent class to manage a SQL table.
Prereqs
VSCode;
Docker Desktop;
InterSystems ObjectScript Extension Pack.
Class Diagram to the Sample Application
I will create a Movie Catalog application to demonstrate the patterns suggested in the article:
Note: thanks to the https://openexchange.intersystems.com/package/iris-rest-api-template application. It was the base to this tutorial.
Setup the Sample Application
1. Create a folder movie in your file system. Open this folder in a new VSCode window.
2. Create the Dockerfile file inside movie folder to run IRIS Community edition into a Docker container instance. Content:
Docker file content
ARG IMAGE=intersystemsdc/iris-community:2020.3.0.221.0-zpm
ARG IMAGE=intersystemsdc/iris-community:2020.4.0.524.0-zpm
ARG IMAGE=intersystemsdc/iris-community
FROM $IMAGE
USER root
WORKDIR /opt/irisapp
RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp
USER ${ISC_PACKAGE_MGRUSER}
COPY src src
COPY module.xml module.xml
COPY iris.script /tmp/iris.script
RUN iris start IRIS \
&& iris session IRIS < /tmp/iris.script \
&& iris stop IRIS quietly
3. Create the docker-compose.yml file inside movie folder to allows you run your docker instance and other instances together (not in this sample, but it is a good practice run from docker-compose instead dockerfile. Content:
Docker composer content
version: '3.6'
services:
iris:
build:
context: .
dockerfile: Dockerfile
restart: always
ports:
- 51773
- 1972:1972
- 52773:52773
- 53773
volumes:
- ./:/irisdev/app
4. Create the iris.script file inside movie folder to do some actions before run IRIS. This file is important to do custom terminal actions necessary for the application, like disable password expiration. Content:
iris.script content
;do $System.OBJ.LoadDir("/opt/irisapp/src","ck",,1)
zn "%SYS"
Do ##class(Security.Users).UnExpireUserPasswords("*")
zn "USER"
zpm "load /opt/irisapp/ -v":1:1
halt
5. Create the module.xml file inside movie folder to install and run your application using ZPM. This file is important to do the application endpoint configuration and install swagger-ui (web app used to run and test your API using swagger file). Content:
Module.xml content
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25">
<Document name="movie.ZPM">
<Module>
<Name>movie</Name>
<Version>1.0.0</Version>
<Packaging>module</Packaging>
<SourcesRoot>src</SourcesRoot>
<Resource Name="dc.movie.PKG"/>
<Dependencies>
<ModuleReference>
<Name>swagger-ui</Name>
<Version>1.*.*</Version>
</ModuleReference>
</Dependencies>
<CSPApplication
Url="/movie-api"
DispatchClass="dc.movie.MovieRESTApp"
MatchRoles=":{$dbrole}"
PasswordAuthEnabled="1"
UnauthenticatedEnabled="0"
Recurse="1"
UseCookies="2"
CookiePath="/movie-api"
/>
</Module>
</Document>
</Export>
You can see CSPApplication tag, used to run the application API in the /movie-api URI and enable or disable password to consume the API.
6. Create the LICENSE file inside movie folder to setting the license of your application. Content:
LICENSE content
MIT License
Copyright (c) 2019 InterSystems Developer Community Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7. Create the README.md file inside movie folder to document your application to the users using markdown language. Content:
## movie-rest-application
This is a sample of a REST API application built with ObjectScript in InterSystems IRIS.
8. Create .vscode folder inside movie folder. Create settings.json file inside .vscode folder to configure server connection between VSCode and your IRIS instance. Content:
Settings content
{
"files.associations": {
"Dockerfile*": "dockerfile",
"iris.script": "objectscript"
},
"objectscript.conn" :{
"ns": "USER",
"username": "_SYSTEM",
"password": "SYS",
"docker-compose": {
"service": "iris",
"internalPort": 52773
},
"active": true
},
"sqltools.connections": [
{
"namespace": "USER",
"connectionMethod": "Server and Port",
"showSystem": false,
"previewLimit": 50,
"server": "localhost",
"port": 32770,
"askForPassword": false,
"driver": "InterSystems IRIS",
"name": "objectscript-docker",
"username": "_SYSTEM",
"password": "SYS"
}
]
}
9. Create the folder src inside movie folder to put your source code folders and files.
10. Create dc folder inside src folder. This is a convention when your build projects to the InterSystems Developer Community, otherwise is not necessary.
11. Create movie folder inside dc folder. This folder will be the folder to your objectscript classes.
12. Create our first class, MovieRESTApp.cls file, inside src\dc\movie folder. This file will be the IRISRESTApplication class. Content:
MovieRESTApp content
Class dc.movie.MovieRESTApp Extends %CSP.REST
{
Parameter CHARSET = "utf-8";
Parameter CONVERTINPUTSTREAM = 1;
Parameter CONTENTTYPE = "application/json";
Parameter Version = "1.0.0";
Parameter HandleCorsRequest = 1;
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<!-- Server Info -->
<Route Url="/" Method="GET" Call="GetInfo" Cors="true"/>
<!-- Swagger specs -->
<Route Url="/_spec" Method="GET" Call="SwaggerSpec" />
</Routes>
}
ClassMethod %ProcessResult(pStatus As %Status = {$$$OK}, pResult As %DynamicObject = "") As %Status [ Internal ]
{
#dim %response As %CSP.Response
SET tSC = $$$OK
IF $$$ISERR(pStatus) {
SET %response.Status = 500
SET tSC = ..StatusToJSON(pStatus, .tJSON)
IF $isobject(tJSON) {
SET pResult = tJSON
} ELSE {
SET pResult = { "errors": [ { "error": "Unknown error parsing status code" } ] }
}
}
ELSEIF pStatus=1 {
IF '$isobject(pResult){
SET pResult = {
}
}
}
ELSE {
SET %response.Status = pStatus
SET error = $PIECE(pStatus, " ", 2, *)
SET pResult = {
"error": (error)
}
}
IF pResult.%Extends("%Library.DynamicAbstractObject") {
WRITE pResult.%ToJSON()
}
ELSEIF pResult.%Extends("%JSON.Adaptor") {
DO pResult.%JSONExport()
}
ELSEIF pResult.%Extends("%Stream.Object") {
DO pResult.OutputToDevice()
}
QUIT tSC
}
ClassMethod SwaggerSpec() As %Status
{
Set tSC = ##class(%REST.API).GetWebRESTApplication($NAMESPACE, %request.Application, .swagger)
Do swagger.info.%Remove("x-ISC_Namespace")
Set swagger.basePath = "/movie-api"
Set swagger.info.title = "Movie API"
Set swagger.info.version = "1.0"
Set swagger.host = "localhost:52773"
Return ..%ProcessResult($$$OK, swagger)
}
}
Note 1: The class extends CSP.REST to be used as the REST Endpoint.
Note 2: the parameter chaset is used to encode requests and responses with UTF-8.
Note 3: the CONVERTINPUTSTREAM is used to force the request content in the UTF-8, without this you can have problems with special latin chars.
Note 4: CONTENTTYPE is used to declare the content using JSON, not XML.
Note 5: HandleCorsRequest = 1 is necessary to allows you consume the API from other servers different from the IRIS server.
Note 6: Routes are used to declare API URI to each class method.
Note 7: SwaggerSpec from CSP.REST class allows you generate the API swagger (API web documentation) content.
Now you have the following folders and files:
13. Open VSCode Terminal (menu Terminal > New Terminal) and type:
docker-compose up -d --build
This will build the docker instance and run it.
14. Test your API with Swagger-UI. In the browser and type: http://localhost:52773/swagger-ui/index.html. Pay attention to the address bar (fix the url, if necessary to correct address)
Connection beetween VSCode and IRIS
1. Click in the ObjectScript bar (in the VSCode footer)
2. Select Toogle Connection in the Top:
3. Check the connection status into ObjectScript Explorer (you will be able to see folders and classes created):
Persistent Classes to the Movie Catalog Application
In this section we will create the persistent domain classes to store and query the business data. See the DBeaver Diagram:
1. Create the folder model inside src\dc\movie folder.
2. Create the Actor.cls file inside model folder. Write the content:
Class dc.movie.model.Actor Extends (%Persistent, %JSON.Adaptor)
{
Parameter %JSONREFERENCE = "ID";
Property actorId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ];
Property name As %VarString(MAXLEN = 120);
Property dob As %Date;
Property genre As %Integer(VALUELIST = ",1,2");
}
3. Create the Movie.cls file inside model folder. Write the content:
Class dc.movie.model.Movie Extends (%Persistent, %JSON.Adaptor)
{
Parameter %JSONREFERENCE = "ID";
Property movieId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ];
Property name As %VarString(MAXLEN = 120);
Property releaseDate As %Date;
Property duration As %Integer;
Property imdb As %String(MAXLEN = 300);
Property movieCategory As dc.movie.model.MovieCategory;
ForeignKey MovieCategoryFK(movieCategory) References dc.movie.model.MovieCategory();
}
4. Create the MovieCategory.cls file inside model folder. Write the content:
Class dc.movie.model.MovieCategory Extends (%Persistent, %JSON.Adaptor)
{
Parameter %JSONREFERENCE = "ID";
Property movieCategoryId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ];
Property name As %VarString(MAXLEN = 120);
}
5. Create the Casting.cls file inside model folder. Write the content:
Class dc.movie.model.Casting Extends (%Persistent, %JSON.Adaptor)
{
Parameter %JSONREFERENCE = "ID";
Property castingId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ];
Property movie As dc.movie.model.Movie;
ForeignKey MovieFK(movie) References dc.movie.model.Movie();
Property actor As dc.movie.model.Actor;
ForeignKey ActorFK(actor) References dc.movie.model.Actor();
Property characterName As %String(MAXLEN = 100);
Index CastingIndex On (movie, actor) [ Unique ];
}
See the created files:
Note 1: Parameter %JSONREFERENCE = "ID" allows return ID value inside JSON response.
Note 2: Property actorId As %Integer [ Calculated, SqlComputeCode = { set {*}={%%ID}}, SqlComputed ] and the other similar properties are used to return class+id into JSON response.
Note 3: (VALUELIST = "1,2") set possible values to 1 or 2 only.
Note 4: ForeignKey MovieFK(movie) References dc.movie.model.Movie() and similar are used to create a SQL foreign key reference.
Note 5: Index CastingIndex On (movie, actor) [ Unique ] and similar are used to not allows duplicate values combining properties in the On (movie and actor).
Note 6: I'm using Camel Case to property names because a best practice for JSON attribute names.
Business Service Classes to the Movie Catalog Application
In this section we will create the classes with business logic (methods to do persistence, query and calculations).
1. Create the service folder inside src\dc\movie.
2. Create CrudUtilService.cls file inside service folder. Write the content:
CrudUtilService content
Class dc.movie.service.CrudUtilService Extends %CSP.REST
{
Parameter CHARSET = "utf-8";
Parameter CONVERTINPUTSTREAM = 1;
Parameter CONTENTTYPE = "application/json";
Parameter Version = "1.0.0";
Parameter HandleCorsRequest = 1;
/// Return all the records
ClassMethod GetAll(DomainClass As %Persistent) As %Status
{
#dim tSC As %Status = $$$OK
Set rset = DomainClass.ExtentFunc()
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Write "["
if rset.%Next() {
Set actor = DomainClass.%OpenId(rset.ID)
Do actor.%JSONExport()
}
While rset.%Next() {
Write ","
Set actor = DomainClass.%OpenId(rset.ID)
Do actor.%JSONExport()
}
Write "]"
Quit tSC
}
/// Return one record
ClassMethod GetOne(DomainClass As %Persistent, id As %Integer) As %Status
{
#dim tSC As %Status = $$$OK
#dim e As %Exception.AbstractException
#; Set the response header to plain text
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Set domain = DomainClass.%OpenId(id)
If '$IsObject(domain) Quit ..Http404()
Do domain.%JSONExport()
Quit tSC
}
/// Creates a new record
ClassMethod Create(DomainClass As %Persistent) As %Status
{
#dim tSC As %Status = $$$OK
#dim e As %Exception.AbstractException
Set domain = DomainClass.%New()
Set data = {}.%FromJSON(%request.Content)
$$$TOE(tSC, domain.%JSONImport(data))
$$$TOE(tSC, domain.%Save())
Write domain.%JSONExport()
Set %response.Status = 204
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Quit tSC
}
/// Update a record with id
ClassMethod Update(DomainClass As %Persistent, id As %Integer) As %Status
{
#dim tSC As %Status = $$$OK
#dim e As %Exception.AbstractException
Set domain = DomainClass.%OpenId(id)
If '$IsObject(domain) Return ..Http404()
Set data = {}.%FromJSON(%request.Content)
$$$TOE(tSC, domain.%JSONImport(data))
$$$TOE(tSC, domain.%Save())
Write domain.%JSONExport()
Set %response.Status = 200
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Quit tSC
}
/// Delete a record with id
ClassMethod Delete(DomainClass As %Persistent, id As %Integer) As %Status
{
#dim tSC As %Status = $$$OK
#dim e As %Exception.AbstractException
Set domain = DomainClass.%OpenId(id)
If '$IsObject(domain) Return ..Http404()
$$$TOE(tSC, domain.%DeleteId(id))
Set %response.Status = 200
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Quit tSC
}
}
3. Create MovieService.cls file inside service folder. Write the content:
MovieService content
Class dc.movie.service.MovieService Extends %CSP.REST
{
ClassMethod GetAll() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.Movie).%New())
}
ClassMethod GetOne(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.Movie).%New(), id)
}
ClassMethod Create() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.Movie).%New())
}
ClassMethod Update(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.Movie).%New(), id)
}
ClassMethod Delete(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.Movie).%New(), id)
}
/// Return casting from the movie
ClassMethod GetMovieCasting(id As %Integer) As %Status
{
#dim tSC As %Status = $$$OK
Set qry = "SELECT actor->name AS actorName, characterName, movie->name AS movieName FROM dc_movie_model.Casting WHERE movie = ?"
Set tStatement = ##class(%SQL.Statement).%New()
Set qStatus = tStatement.%Prepare(qry)
If tSC'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
Set rset = tStatement.%Execute(id)
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Set result = []
While rset.%Next() {
Set item = {}
Set item.actorName = rset.actorName
Set item.movieName = rset.movieName
Set item.characterName = rset.characterName
Do result.%Push(item)
}
Write result.%ToJSON()
Quit tSC
}
}
4. Create MovieCategoryService.cls file inside service folder. Write the content:
MovieCategoryService content
Class dc.movie.service.MovieCategoryService
{
ClassMethod GetAll() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.MovieCategory).%New())
}
ClassMethod GetOne(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.MovieCategory).%New(), id)
}
ClassMethod Create() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.MovieCategory).%New())
}
ClassMethod Update(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.MovieCategory).%New(), id)
}
ClassMethod Delete(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.MovieCategory).%New(), id)
}
}
5. Create ActorService.cls file inside service folder. Write the content:
ActorService content
Class dc.movie.service.ActorService
{
ClassMethod GetAll() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.Actor).%New())
}
ClassMethod GetOne(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.Actor).%New(), id)
}
ClassMethod Create() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.Actor).%New())
}
ClassMethod Update(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.Actor).%New(), id)
}
ClassMethod Delete(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.Actor).%New(), id)
}
}
6. Create CastingService.cls file inside service folder. Write the content:
CastingService content
Class dc.movie.service.CastingService
{
ClassMethod GetAll() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetAll(##class(dc.movie.model.Casting).%New())
}
ClassMethod GetOne(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).GetOne(##class(dc.movie.model.Casting).%New(), id)
}
ClassMethod Create() As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Create(##class(dc.movie.model.Casting).%New())
}
ClassMethod Update(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Update(##class(dc.movie.model.Casting).%New(), id)
}
ClassMethod Delete(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CrudUtilService).Delete(##class(dc.movie.model.Casting).%New(), id)
}
}
7. Update the file MovieRESTApp.cls to create paths to all new service class methods. Write the content:
MovieRESTApp updated content
Class dc.movie.MovieRESTApp Extends %CSP.REST
{
Parameter CHARSET = "utf-8";
Parameter CONVERTINPUTSTREAM = 1;
Parameter CONTENTTYPE = "application/json";
Parameter Version = "1.0.0";
Parameter HandleCorsRequest = 1;
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<!-- Server Info -->
<Route Url="/" Method="GET" Call="GetInfo" Cors="true"/>
<!-- Swagger specs -->
<Route Url="/_spec" Method="GET" Call="SwaggerSpec" />
<!-- List all movies -->
<Route Url="/movies" Method="GET" Call="GetAllMovies" />
<!-- Get a movie -->
<Route Url="/movies/:id" Method="GET" Call="GetMovie" />
<!-- Get the movie casting -->
<Route Url="/movies/casting/:id" Method="GET" Call="GetMovieCasting" />
<!-- Create new movie -->
<Route Url="/movies" Method="POST" Call="CreateMovie" />
<!-- Update a movie -->
<Route Url="/movies/:id" Method="PUT" Call="UpdateMovie" />
<!-- Delete a movie -->
<Route Url="/movies/:id" Method="DELETE" Call="DeleteMovie" />
<!-- List all movie categories -->
<Route Url="/categories" Method="GET" Call="GetAllMovieCategories" />
<!-- Get a movie category -->
<Route Url="/categories/:id" Method="GET" Call="GetMovieCategory" />
<!-- Create new movie category -->
<Route Url="/categories" Method="POST" Call="CreateMovieCategory" />
<!-- Update a movie category -->
<Route Url="/categories/:id" Method="PUT" Call="UpdateMovieCategory" />
<!-- Delete a movie category -->
<Route Url="/categories/:id" Method="DELETE" Call="DeleteMovieCategory" />
<!-- List all actors -->
<Route Url="/actors" Method="GET" Call="GetAllActors" />
<!-- Get a actor -->
<Route Url="/actors/:id" Method="GET" Call="GetActor" />
<!-- Create new actor -->
<Route Url="/actors" Method="POST" Call="CreateActor" />
<!-- Update a actor -->
<Route Url="/actors/:id" Method="PUT" Call="UpdateActor" />
<!-- Delete a actor -->
<Route Url="/actors/:id" Method="DELETE" Call="DeleteActor" />
<!-- List all castings -->
<Route Url="/castings" Method="GET" Call="GetAllCastings" />
<!-- Get a actor -->
<Route Url="/castings/:id" Method="GET" Call="GetCasting" />
<!-- Create new actor -->
<Route Url="/castings" Method="POST" Call="CreateCasting" />
<!-- Update a actor -->
<Route Url="/castings/:id" Method="PUT" Call="UpdateCasting" />
<!-- Delete a actor -->
<Route Url="/castings/:id" Method="DELETE" Call="DeleteCasting" />
</Routes>
}
/// List movies
ClassMethod GetAllMovies() As %Status
{
Return ##class(dc.movie.service.MovieService).GetAll()
}
/// Get movie casting
ClassMethod GetMovieCasting(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieService).GetMovieCasting(id)
}
/// Get a movie
ClassMethod GetMovie(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieService).GetOne(id)
}
// Create a new movie
ClassMethod CreateMovie() As %Status
{
Return ##class(dc.movie.service.MovieService).Create()
}
// Update a movie
ClassMethod UpdateMovie(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieService).Update(id)
}
// Delete a movie
ClassMethod DeleteMovie(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieService).Delete(id)
}
/// List movies categories
ClassMethod GetAllMovieCategories() As %Status
{
Return ##class(dc.movie.service.MovieCategoryService).GetAll()
}
/// Get a movie category
ClassMethod GetMovieCategory(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieCategoryService).GetOne(id)
}
// Create a new movie category
ClassMethod CreateMovieCategory() As %Status
{
Return ##class(dc.movie.service.MovieCategoryService).Create()
}
// Update a movie category
ClassMethod UpdateMovieCategory(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieCategoryService).Update(id)
}
// Delete a movie category
ClassMethod DeleteMovieCategory(id As %Integer) As %Status
{
Return ##class(dc.movie.service.MovieCategoryService).Delete(id)
}
/// List actors
ClassMethod GetAllActors() As %Status
{
Return ##class(dc.movie.service.TestActorService).GetAll()
}
/// Get an actor
ClassMethod GetActor(id As %Integer) As %Status
{
Return ##class(dc.movie.service.ActorService).GetOne(id)
}
// Create a new actor
ClassMethod CreateActor() As %Status
{
Return ##class(dc.movie.service.ActorService).Create()
}
// Update an actor
ClassMethod UpdateActor(id As %Integer) As %Status
{
Return ##class(dc.movie.service.ActorService).Update(id)
}
// Delete an actor
ClassMethod DeleteActor(id As %Integer) As %Status
{
Return ##class(dc.movie.service.ActorService).Delete(id)
}
/// List castings
ClassMethod GetAllCastings() As %Status
{
Return ##class(dc.movie.service.CastingService).GetAll()
}
/// Get a casting
ClassMethod GetCasting(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CastingService).GetOne(id)
}
// Create a new casting item
ClassMethod CreateCasting() As %Status
{
Return ##class(dc.movie.service.CastingService).Create()
}
// Update a casting
ClassMethod UpdateCasting(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CastingService).Update(id)
}
// Delete a casting
ClassMethod DeleteCasting(id As %Integer) As %Status
{
Return ##class(dc.movie.service.CastingService).Delete(id)
}
/// General information
ClassMethod GetInfo() As %Status
{
SET version = ..#Version
SET fmt=##class(%SYS.NLS.Format).%New("ptbw")
SET info = {
"Service": "Movie API",
"version": (version),
"Developer": "Yuri Gomes",
"Status": "Ok",
"Date": ($ZDATETIME($HOROLOG))
}
Set %response.ContentType = ..#CONTENTTYPEJSON
Set %response.Headers("Access-Control-Allow-Origin")="*"
Write info.%ToJSON()
Quit $$$OK
}
ClassMethod %ProcessResult(pStatus As %Status = {$$$OK}, pResult As %DynamicObject = "") As %Status [ Internal ]
{
#dim %response As %CSP.Response
SET tSC = $$$OK
IF $$$ISERR(pStatus) {
SET %response.Status = 500
SET tSC = ..StatusToJSON(pStatus, .tJSON)
IF $isobject(tJSON) {
SET pResult = tJSON
} ELSE {
SET pResult = { "errors": [ { "error": "Unknown error parsing status code" } ] }
}
}
ELSEIF pStatus=1 {
IF '$isobject(pResult){
SET pResult = {
}
}
}
ELSE {
SET %response.Status = pStatus
SET error = $PIECE(pStatus, " ", 2, *)
SET pResult = {
"error": (error)
}
}
IF pResult.%Extends("%Library.DynamicAbstractObject") {
WRITE pResult.%ToJSON()
}
ELSEIF pResult.%Extends("%JSON.Adaptor") {
DO pResult.%JSONExport()
}
ELSEIF pResult.%Extends("%Stream.Object") {
DO pResult.OutputToDevice()
}
QUIT tSC
}
ClassMethod SwaggerSpec() As %Status
{
Set tSC = ##class(%REST.API).GetWebRESTApplication($NAMESPACE, %request.Application, .swagger)
Do swagger.info.%Remove("x-ISC_Namespace")
Set swagger.basePath = "/movie-api"
Set swagger.info.title = "Movie API"
Set swagger.info.version = "1.0"
Set swagger.host = "localhost:52773"
Return ..%ProcessResult($$$OK, swagger)
}
}
8. The files and folders to the final project are:
9. Test your new methods acessing http://localhost:52773/swagger-ui/index.html.
Note 1: REST paths are following business topic in plural with /id when we need pass id to the entity and camel case to paths to.
Note 2: We use verb GET to queries, POST to new records, PUT to update record and DELETE to delete a record.
Note 3: In <Route Url="/movies/casting/:id" Method="GET" Call="GetMovieCasting" /> I used /casting indicating a second purpose (get the movie and it casting). This method runs ToJSON(), because is a DynamicArray ([]) with Dynamic items ({}).
Note 4: I created the CrudUtilService class utility to do generic CRUD methods, following the Dont Repeat Yourself principle.
Enjoy this tutorial!
Hi Yuri
You didn't use GoJS by any chance for the UML etc... If you look in the General Section of Discord I have written a chunk of stuff about GoJS and how a developer could build the necessary data collectors into their classes and then having but the data sets render the diagrams through GoJS Thanks for the tip! I did use StarUML, but in the next time I will consider GoJS Great article.
Some comments on formatting:
Move large code blocks under spoiler to improve readability using button.
There are a lot of empty lines in code blocks, they can be safely removed.
On the article itself my only issue is you create 5 methods per class:
GET /class
POST /class
GET /class/object
PUT /class/object
DELETE /class/object
That's a lot of code even for 4 classes, but what about a case where there are 10 classes? 50? 100? Generally I would recommend writing 5 methods which would process objects of any allowed class (see RESTForms2). Fixed and improved, thanks!!! Hi Yuri
I forgot to mention that I agree with Eduard that your article is excellent.
Nigel Thanks!!! Excellent work @Yuri.Gomes, lots of useful details for the reader! I like DRY too :-) Thanks @Luca.Ravazzolo
Question
Muhammad Waseem · Sep 3, 2021
Hi,
Under the social tab of my profile I found "InterSystems SSO" account along with my other social accounts.
What is InterSystems SSO account and to utilize it?
Thanks Just curious - where are you seeing this? Could you please include a URL?
The InterSystems SSO account is what controls your access to open as well as restricted applications provided by InterSystems to help customers and prospects get stuff done. If you go to Login.InterSystems.com you can see the various apps available to you (after you sign in). This would include things like D.C., OEX, Learning, Download, etc for Prospects, and supported customers would also get access to WRC, iService, HS Docs, CCR, etc (depending on what products they have).
Hope that helps - let me know if any additional clarification is needed. SSO is part of Social Tab in Edit Profile in Global Masters.it allows sign in using WRC SSO
https://globalmasters.intersystems.com/ It is along with other social accounts Thanks Robert Cemper, What is the difference between Normal and SSO Account ? SSO account can be shared for WRC (if enabled), DC, OEX, Learnig, ..Global Masters is an external application that can make use of SSObut has its own independent accounts as well.
Article
Yuri Marx Pereira Gomes · Oct 19, 2021
In the last years the data architecture and platforms focused into Big Data repositories and how toprocess it to deliver business value. From this effort many technologies were created to process tera and petabytes of data, see:
The fundamental piece to the Big Data technologies is HDFS (Hadoop Distributed File System). It is a distributed file system to store tera or petabytes of data into arrays of storages, memory and CPU working together. In addition of the Hadoop we have other components, see:
In a Big Data project the first step is create the data ingestion, integration, transformation/enrichment, with data quality as a requirement. In this area we have:
Apache Kafka: data event flow, in real time asyncronous events, were each event deliver data items to be ingested by the Big Data using Kafka clients. It is possible process milions of data event per second, creating real time data streams.
Apache NiFi: it is an ETL capable to create integration maps that connect with multiples formats, technologies and type of data sources to deliver data to HDFS, Databases or HBase repositories. Acts also as a CDC tool.
Apache Sqoop: it is an Data Ingestion tool for SQL Databases.
Apache Flume: collect data from the log of the datasources to push to the HDFS or HBase.
ESB: it is a service bus used to connect internal and external datasources into a corporate data backbone to send, receive and process data between enterprise data resources, including Big Data repositories. The ESB has connectors/adapters to the main data resources, like Kafka, SQL Databases, NoSQL databases, E-mail, Files, FTP, JMS messages and other. The InterSystems IRIS has an ESB. The ESB can automate data process, delivering complex integrations to the Big Data repositories.
HDFS: it is the most used resource to store big data volumes, with performance, realiabity and availability. The data storage is distributed into data nodes working in an active-active HA and using common machines. So, it is cheaper than store into RDMS products.
HBase: it is like HDFS, but it is used to store NoSQL data, like objects or documents.
Sharding DB: are data stores that use distributed data nodes to allow process Big Data SQL or NoSQL repositories into proprietary formats. The main example is MongoDB, but InterSystems IRIS it is a Shard DB too, including options to store SQL, NoSQL (JSON) or OLAP datastores.
YARN and ZooKeeper: are tools to centralize and allows the Big Data tools share configuration, resources, resource names and metadata.
Apache Spark: Apache Spark is a distributed processing system used for big data workloads. It utilizes in-memory caching, and optimized query execution for fast analytic queries against data of any size. It provides development APIs in Java, Scala, Python and R, and supports code reuse across multiple workloads—batch processing, interactive queries, real-time analytics, machine learning, and graph processing (AWS definition). The InterSystems IRIS has a Spark adapter that can be used to read and write HDFS data.
Apache Hive: it is a distributed, fault-tolerant data warehouse system that enables analytics at a massive scale. A data warehouse provides a central store of information that can easily be analyzed to make informed, data driven decisions. Hive allows users to read, write, and manage petabytes of data using SQL. Hive is built on top of Apache Hadoop, which is an open-source framework used to efficiently store and process large datasets. As a result, Hive is closely integrated with Hadoop, and is designed to work quickly on petabytes of data. What makes Hive unique is the ability to query large datasets, leveraging Apache Tez or MapReduce, with a SQL-like interface (AWS definition). The InterSystems IRIS don't have native adapter for Hive, but I created it (see: https://community.intersystems.com/post/using-sql-apache-hive-hadoop-big-data-repositories).
Apache Pig: it is a library that runs on top of Hadoop, providing a scripting language that you can use to transform large data sets without having to write complex code in a lower level computer language like Java. The library takes SQL-like commands written in a language called Pig Latin and converts those commands into Tez jobs based on directed acyclic graphs (DAGs) or MapReduce programs. Pig works with structured and unstructured data in a variety of formats. (AWS definition).
Apache Drill: it is a tool to do queries for the main Big Data products using SQL sintax. Drill supports a variety of NoSQL databases and file systems, including HBase, MongoDB, MapR-DB, HDFS, MapR-FS, Amazon S3, Azure Blob Storage, Google Cloud Storage, Swift, NAS and local files. A single query can join data from multiple datastores. For example, you can join a user profile collection in MongoDB with a directory of event logs in Hadoop (Apache Drill definition). I will build an adapter to Apache Drill in the near future.
ESB Adapters: it is an interoperability platform, with ready connectors to query and process data from multiple formats and protocols. The InterSystems IRIS has adapter to HTTP, FTP, File, SQL, MQTT (IoT) and many other datasources. These adapters can compose data flows (productions) to deliver the data for multiple targets, including hadoop repositories.
InterSystems IRIS it is a good Big Data architecture option with:
1. An excellent integration/ETL layer, as an ESB platform.2. A fantastic distributed data store when using IRIS Database Sharding.3. An important tool to query and process Big Data information, using its adapters. The InterSystems IRIS can also deliver reports, BI Dashboards and data microservices.4. A good tool to work with Kafka, Spark, Hadoop and Hive, to deliver Big Data with additional resources, like ESB, Analytics, Machine Learning, Data workflows (BPL productions) and native support to the main languages (Python, R, Java, .Net, Node.js).
See a sample of this into my new app: https://openexchange.intersystems.com/package/IRIS-Big-Data-SQL-Adapter. Thanks! And enjoy!
Announcement
Anastasia Dyubaylo · Oct 26, 2021
Hey Community,
We're pleased to invite you to the French stream on InterSystems Technologies #6!
This event hosted by @Guillaume.Rongier7183 for French-speaking InterSystems developers will be live stream November 4th at 12:00 Paris time.
👉 Direct link to join: https://youtu.be/Gn6A1MnsxFY
On the agenda this month:
🗞 News
https://code.visualstudio.com/blogs/2021/09/29/bracket-pair-colorization
https://openexchange.intersystems.com/contest/18
Virtual Summit overview https://www.intersystems.com/VS21Reg
💡 Did you know?
Projections in ObjectScript, how to execute code during compilation
🗂 Focus on
AtScale
Don’t miss the French Stream #6 👉 https://youtu.be/Gn6A1MnsxFY!
Enjoy watching the prev streams on YouTube:
Stream #1
Stream #2
Stream #3
Stream #4
Stream #5
Stay tuned!
Article
Jose-Tomas Salvador · Nov 9, 2021
For some years I missed being able to offer, to everybody interested in ObjectScript, a tutorial more or less complete, to start with ObjectScript. Something that could help more and make things easier to those new developers that come to our technology... something intermediate, halfway between the common "Hello World!", that doesn't really get you further, and the "Advanced Training", that is unaffordable because of lack of time,etc.
If there were something truly helpful not only as an introduction to the ecosystem, but as a starting point, as a boost, to really start to walk into ObjectScript and move forward by yourself... wouldn't that be awesome?
In short... as I say, the idea that something like that should exist, it's going around me for a while... and then, the pandemic... and we had to stay at home, almost no holidays, and loooonnggg weekends,... what a better situation to do what we always say we would do if we had time?
So..no sooner said than done... I started to work on it several months ago and spend some free time here and there to develop this idea... you will tell me how it is (be kind), because:
Today I can announce officially the birth of ¡¡¡1st Video Tutorial in Spanish of ObjectScript 101++ !!!
Ok, ok,... plus, plus, .... I didn't date to call it 102... or intermediate or so....... It's composed of 6 videos plus one with a short introduction...
Wait... yes... I know... I said Spanish... and this is community in english...I know... It's uploaded in the ES community since September...but last week I published the last video there and I thought that it could also be useful to english native speakers that understand (or are learning) spanish... that's why I decided to post it also here. Also, I'm dealing with subtitles in YouTube... so to include the english translation. I'll link the videos for which I consider the english translation is fine as soon as they're ready. Right now, only the first 3 are reviewed (I will need some more weekends ).
Code samples and exercises used in different parts of the tutorial are in GitHub. To see the videos better, my advice is to do it in full size screen... they are also available in YouTube.
IMPORTANT: It's not an InterSystems official training and doesn't intend to (it can't in any way) replace the formal classroom training, which are more extense, rigurous and complete. My intention is for this tutorial to be an additional resource to introduce you into the ObjectScript world as a starting point and a spur, something that helps you to move forward by yourself, together with other resources from eLearning, formal training, documentation or this community!
¡¡Enjoy!!
Chapter 0 - Introduction
Chapter 1 - Settling down
Chapter 2 - Iterating
Chapter 3 - My Execution Context
Chapter 4 - Indirection and Globals
Chapter 5 - Objects in ObjectScript
Chapter 6 - What about SQL?
@Jose-Tomas.Salvador - thank you for the effort you put into creating this and making it available to the Community :) Ok, I've just reviewed the translation of Chapter 4 to english. Here I talk briefly about Indirection in ObjectScript and, mostly, about Globals... Enjoy! Well, this took some more time.... but arrived on time before end of year. Chapter 5 captions reviewed!! In this chapter I talk about OO.OO in ObjectScript, a bit of JSON native support, Macros, Error handling,... with guided hands-on.
Just one left. Enjoy! It was funny really... and served me to realize how hard is to create this kind of material. Now I appreciate it much more. :-) Well, it has been a long trip... but Chapter 6, "What's about SQL?" is finally published with reviewed English CC...
In this last chapter I'll show you what's about the Multi-Model architecture of InterSystems IRIS, and how ObjectScript is able to work also with SQL paradigm in a very easy way to also cover that feature of the platform.We'll do hands-on exercises of embedded and dynamic SQL using the small class model we defined in the previous chapter... which now we'll see as an E/R model.
And... That's all folks!
Happy Coding! worth watching content, thanks! Hi again, I've just added to the article the slides that I used during the video tutorial. Feel free to use all of some of them. If you do, the only thing I would kindly ask you is to include a link as a reference to this article within our community.
For the ones that contacted me, you were right, the repository in GitHub was set as private. It's set to public now: GitHub Repository - Examples
Announcement
Anastasia Dyubaylo · Nov 13, 2021
Hey Community,
The new video is worth watching on InterSystems Developers YouTube:
⏯ Data Warehousing with InterSystems
Get a quick tour of classic and emerging terms used to describe logical and physical data stores that go beyond exclusive application use. With these concepts in mind, see how InterSystems® technology helps streamline your data landscape.
🗣 Presenter: @Benjamin.DeBoe, InterSystems Product Manager
Subscribe to InterSystems Developers YouTube and stay tuned!
Announcement
Anastasia Dyubaylo · Jan 25, 2022
Hey Community,
Learn about the changes we've made to InterSystems IRIS Containers, including security updates and the new web gateway container:
⏯ InterSystems IRIS Container Updates
🗣 Presenter: @Eve.Phelps, Senior Systems Developer, InterSystems
Enjoy watching on InterSystems Developers YouTube channel and stay tuned!
Announcement
Anastasia Dyubaylo · Apr 24, 2022
Hey Developers,
What is the best way to containerize your InterSystems IRIS application? Discover your options:
⏯ Containerizing InterSystems IRIS Applications
🗣 Presenter: @Evgeny.Shvarov, Developer Ecosystem manager, InterSystems
Enjoy watching the new video on InterSystems Developers YouTube!
Announcement
Anastasia Dyubaylo · Jun 29, 2022
Hey Community,
We're thrilled to invite you to the next InterSystems in-person event! Join us for a true community event, once again bringing together InterSystems customers and partners – to learn, inspire, and share innovation challenges with each other:
➡️ InterSystems UK & Ireland Summit 2022
🗓 Date: October 18-19, 2022
📍 Location: Birmingham, United Kingdom – The Vox Conference Centre
A wide range of prominent speakers will provide a wealth of knowledge and expertise, with the event entirely focused on making sure you have the information required to not only help you within your own role but to positively impact on the growth and success of your organisation.
Hear the latest product roadmaps from InterSystems specialists
Network with like-minded peers and be inspired by their levels of innovation
Get face-to-face once again with peers and InterSystems experts in interactive breakouts, experience labs, and workshops
We can’t wait to see you all again in October!
➡️ Register today at www.intersystems.com/uk/uki-summit
Announcement
Derek Robinson · Jun 29, 2022
Hi All! We have recently updated the Exploring Healthcare Analytics with InterSystems exercise to a new version. Originally from a 2021 Virtual Summit experience lab, this exercise now focuses more specifically on using InterSystems IRIS Adaptive Analytics with InterSystems IRIS for Health. It features a new and improved data model and exercise to explore. Feel free to give it a try!