Search

Clear filter
Announcement
Raj Singh · Mar 30, 2022

InterSystems Language Server version 2.0.0

InterSystems is pleased to announce version 2.0.0 of the Language Server for VS Code. The Language Server augments the VS Code ObjectScript extension to provide better syntax coloring, embedded documentation, code completion and more. Detailed information is available in the GitHub repo's README. Version 2.0.0 adds support for a number of new platform architectures including M1 Macs! It also reduces package size, improves SQL coloring, and fixes a number of other issues detailed in the CHANGELOG. As always, if you already have the extension installed, VS Code should automatically update your extension when you restart or reload. If you're a new user, use these instructions to get started.
Announcement
Anastasia Dyubaylo · Apr 6, 2022

InterSystems at "J On The Beach" International Conference in Málaga, Spain

Hey Developers, Good news! One more upcoming in-person event is nearby. We're pleased to invite you to join "J On The Beach", an international rendezvous for developers and DevOps around Big Data technologies. A fun conference to learn and share the latest experiences, tips & tricks related to Big Data technologies, and, the most important part, it’s On The Beach! 🗓 April 27-29, 2022 📍Málaga, Spain This year, InterSystems is a Gold Sponsor of the JOTB. We're more than happy to invite you and your colleagues to our InterSystems booth for a personal conversation. As always, there will be some surprises on it... 😁 In addition, on the first day of the Conference @David.Reche and @Eduardo.Anglada will give a talk called "Captain Kirk, exoplanet found on route using Auto Machine Learning. 🎯 More details can be found at jonthebeach.com Looking forward to seeing you soon!
Announcement
Anastasia Dyubaylo · Jul 11, 2022

InterSystems Full Stack Contest 2022: Voting time!

Hey Community, It's voting time! Let's cast your votes for the best applications in the InterSystems Full Stack Contest 2022: 🔥 VOTE FOR THE BEST APPS 🔥 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⭐️ @Benjamin.DeBoe, Product Manager⭐️ @Robert.Kuszewski, Product Manager⭐️ @Raj.Singh5479, Product Manager⭐️ @Alexander.Koblov, Support Specialist⭐️ @Daniel.Kutac, Senior Sales Engineer⭐️ @Guillaume.Rongier7183, Sales Engineer⭐️ @Steve.Pisani, Senior Solution Architect⭐️ @Eduard.Lebedyuk, Senior Cloud Engineer⭐️ @Alexander.Woodhead, Technical Specialist⭐️ @Timothy.Leavitt, Development Manager ⭐️ @Jeffrey.Fried, Director of Product Management⭐️ @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! Since the beginning of the voting we have the results: Expert Nomination, Top 3 Kozo by @Sean.Connelly iris-climate-change by @Muhammad.Waseem Carbon Footprint Counter by @Yuri.Gomes ➡️ Voting is here. Community Nomination, Top 3 iris-climate-change by @Muhammad.Waseem Carbon Footprint Counter by @Yuri.Gomes interoperability-manager by @Oliver.Wilms ➡️ Voting is here. So, the voting continues. Please support the application you like! Here are the results after 2 days of voting: Expert Nomination, Top 3 Kozo by @Sean Connelly iris-climate-change by @Muhammad Waseem interoperability-manager by @Oliver.Wilms Carbon Footprint Counter by @Yuri.Gomes World ice level by @Oleh.Dontsov ➡️ Voting is here. Community Nomination, Top 3 iris-climate-change by @Muhammad Waseem interoperability-manager by @Oliver.Wilms Carbon Footprint Counter by @Yuri Marx Kozo by @Sean Connelly World ice level by @Oleh.Dontsov ➡️ Voting is here. So, the voting continues. Please support the application you like! Devs! Here are the top 5 for now: Expert Nomination, Top 3 Kozo by @Sean Connelly iris-climate-change by @Muhammad Waseem interoperability-manager by @Oliver Wilms iris-for-money by @Oliver.Wilms Carbon Footprint Counter by @Yuri Marx ➡️ Voting is here. Community Nomination, Top 3 iris-climate-change by @Muhammad Waseem interoperability-manager by @Oliver Wilms iris-for-money by @Oliver.Wilms Carbon Footprint Counter by @Yuri Marx Arctic sea ice viewer by @Oleh.Dontsov ➡️ Voting is here. Voting for the InterSystems Full Stack Contest 2022 goes ahead! And here're the results at the moment: Expert Nomination, Top 3 iris-climate-change by @Muhammad Waseem Kozo by @Sean Connelly Carbon Footprint Counter by @Yuri Marx Arctic sea ice viewer by @Oleh Dontsov interoperability-manager by @Oliver Wilms ➡️ Voting is here. Community Nomination, Top 3 iris-climate-change by @Muhammad Waseem Arctic sea ice viewer by @Oleh Dontsov interoperability-manager by @Oliver Wilms Carbon Footprint Counter by @Yuri Marx Kozo by @Sean Connelly ➡️ Voting is here. Developers! Last call!Only a few hours left to the end of voting! Cast your votes for applications you like!
Announcement
Anastasia Dyubaylo · Jul 18, 2022

Online Meetup with InterSystems Full Stack Contest Winners

Hi Community, Let's meet together at the online meetup with the winners of the InterSystems Full Stack contest – a great opportunity to have a discussion with InterSystems Experts team as well as our contestants. Winners' demo included! Date & Time: Friday, July 22 – 12:00 PM EDT Join us to learn more about winners' applications and to have a talk with our experts. ➡️ REGISTER TODAY! See you at our virtual meetup! Hey Developers, Watch the recording of the meetup on InterSystems Developers YouTube: ⏯ Online Meetup with InterSystems Full Stack Contest Winners
Announcement
Anastasia Dyubaylo · Dec 27, 2021

2nd InterSystems Tech Article Contest: And the Winners are...

Hey everyone, Lots of new content to read! Thanks to our wonderful participants of the 2nd InterSystems Tech Article Contest! 🌟 25 AMAZING ARTICLES 🌟 So it's time to announce the best of them! Let's meet the winners and their articles: ⭐️ Expert Awards – winners selected by InterSystems experts: 🥇 1st place: Data anonymization, introducing iris-Disguise by @Henry.HamonPereira 🥈 2nd place: IntegratedML hands-on lab by @José.Pereira 🥉 3rd place and two winners: VSCode-ObjectScript on GitHub by @Dmitry.Maslennikov Invite the FHIR® Accelerator Service to your Kubernetes Microservice Party by @Ron.Sweeney1582 ⭐️ Community Award – winner selected by Community members, article with the most likes: 🏆 Data anonymization, introducing iris-Disguise by @Henry.HamonPereira Hope this win will be a great Christmas present for all of the winners! ⭐️ This time, we'd like to reward some more authors for the number of contributions: @Yuri.Gomes: 4 articles! @MikhailenkoSergey: 3 articles! These guys will get Apple AirPods Pro OR Amazon Kindle 8G Paperwhite OR Raspberry Pi 4 8GB with InterSystems IRIS Community Edition ARM installed! And... Let's congratulate all our heroes at https://community.intersystems.com/contests/2: @Robert.Cemper1003 @Henrique.GonçalvesDias @Muhammad.Waseem @Rob.Tweed @John.Murray @alex.kosinets @Irene.Mikhaylova @Oliver.Wilms @Rizmaan.Marikar2583 THANK YOU ALL! You have made an incredible contribution to our Dev Community! Happy Holidays to everyone! 🎅 The prizes are in production now. We will contact all the participants when they are ready to ship Thanks my reward and congrats for the participants, great articles! Congratulations everyone. Very impressive! ![yeee](https://media0.giphy.com/media/l4FGAREbOSRLKMiNq/giphy.gif) What a wonderful surprise!! Thank you all community and congratulations to all participants Congratulations all, and happy new year Congratulations to ALL. It was nice competition Congratulations to the authors :-) Thanks everybody!!! Congratulations! We're lucky to have airpods as the third place prize. Those were easy to split equally between the tied contestants :-) Congratulations! Well done everyone! And now we have beautiful badges for all the winners on Global Masters tied to levels - so these badges will help you to move up through GM levels! Congrats and Happy New Year! Dear participants, regarding prizes and swag delivery: we will be in touch with you at the beginning of January - shortly after the Holidays.
Article
José Pereira · Dec 27, 2021

Using Python to Implement an IMAP Client in InterSystems IRIS

In the previous articles, we learned the basics of using IMAP protocol to handle messages from mailboxes in an e-mail server. That was cool and interesting, but you could take advantage of implementations created by other ones, available in libraries ready to use. One of the improvements to the IRIS data platform is the ability to write Python code alongside ObjectScript in the same IRIS process. This new feature is called [Embedded Python](https://community.intersystems.com/post/start-learning-about-embedded-python). Embedded Python lets us bring to our ObjectScript code the power of the huge [Python ecosystem’s libraries](https://pypi.org/). In this article, we’ll use one of those libraries, called [imaplib](https://docs.python.org/3/library/imaplib.html), to implement an IMAP client and integrate it with the [IRIS Email Framework](https://community.intersystems.com/post/implementing-imap-client-intersystems-iris-part-ii). We’ll also review a practical example of how to use embedded Python to resolve real-world challenges on the IRIS platform with the help of the Python ecosystem. You can find all code implemented here in this GitHub [repository](https://github.com/jrpereirajr/iris-imap-inbound-adapter-demo), in the [python directory](https://github.com/jrpereirajr/iris-imap-inbound-adapter-demo/tree/main/src/dc/demo/imap/python). Note that Python code just works in recent IRIS versions. In this example, the used version was 2021.1.0.215.3-zpm. You can follow updates about Embedded Python [here](https://community.intersystems.com/tags/python). ## Using Embedded Python The key to using embedded Python is the class %SYS.Python. By using this class, we can: * Import Python libraries: `##class(%SYS.Python).Import(“package-name”)` * Import custom Python modules (*.py files) available into the local system: `##class(%SYS.Python).Import(“module-file.py”)` * Get some Python built-in types to be used in assignments or parameters, for instance: * Python None object: `##class(%SYS.Python).None()` * Python True object: `##class(%SYS.Python).True()` * Python False object: `##class(%SYS.Python).False()` * Convert ObjectScript strings to Python Bytes objects (8-bit strings): `##class(%SYS.Python).Bytes(“ObjectScript string”)` These methods create Python objects and return an ObjectScript object. We can use the Python object’s properties and methods directly in our ObjectScript code. For instance, let’s see how we can implement this Python [recipe](https://docs.python.org/3/library/secrets.html#recipes-and-best-practices) for using the secrets library to generate passwords: USER>Set string = ##class(%SYS.Python).Import("string") USER>Set secrets = ##class(%SYS.Python).Import("secrets") USER>ZWrite secrets // let's check what this object is... secrets=1@%SYS.Python ; ; USER>ZWrite string // same for this one... string=2@%SYS.Python ; ; USER>Set alphabet = string."ascii_letters" _ string.digits // here we are accessing Python properties from string object USER>Set pwd = "" USER>For i=1:1:8 { Set pwd = pwd _ secrets.choice(alphabet) } USER>Write pwd Qv7HuOPV In this code, we use several properties and methods from Python objects to set ObjectScript variables. We use ObjectScript variables as parameters for Python objects methods. Another key point to using embedded Python is unique attributes and methods, sometimes called magical methods. Because everything in [Python data models](https://docs.python.org/3/reference/datamodel.html) are objects, these attributes and methods provide the Python interpreter's interface. For example, here’s how we retrieve an item from a list by its index, using the [\_\_getitem\_\_](https://docs.python.org/3/reference/datamodel.html#object.\_\_getitem\_\_) special method: USER>Set b = ##class(%SYS.Python).Import("builtins") USER>Set list = b.list() // creates a Python list USER>Do list.append(1) USER>Do list.append(2) USER>Do list.append(3) USER>ZWrite list list=4@%SYS.Python ; [1, 2, 3] ; USER>w list."__getitem__"(0) // in Python, indexes are 0-based 1 USER>w list."__getitem__"(2) 3 In the same way, we can get the length of the list by using the \_\_len\_\_ special method: USER>Set listLen = list."__len__"() USER>ZWrite listLen listLen=3 We can combine them to iterate the list using ObjectScript: USER>For i=0:1:(listLen - 1) { Write list."__getitem__"(i), ! } 1 2 3 If we need to use constant values like None, True, or False, we can use the following methods from the %SYS.Python class: USER>Set none = ##class(%SYS.Python).None() USER>Set true = ##class(%SYS.Python).True() USER>Set false = ##class(%SYS.Python).False() USER>ZWrite none, true, false none=5@%SYS.Python ; None ; true=6@%SYS.Python ; True ; false=7@%SYS.Python ; False ; Similarly, we can convert an ObjectScript string to a Python Bytes object: USER>Set bytes = ##class(%SYS.Python).Bytes("This is a string") USER>ZWrite bytes bytes=8@%SYS.Python ; b'This is a string' ; Finally, we define our custom Python modules and import them into the ObjectScript context. You can find more useful resources on how to use embedded Python [here](https://community.intersystems.com/tags/python). For instance, check out this nice [example](https://community.intersystems.com/post/websocket-client-embedded-python) by [Robert Cemper](https://community.intersystems.com/user/robert-cemper-0). ## Writing an Alternative IMAP Client To use imaplib to implement our IMAP client, we use the regular [ObjectScript](https://community.intersystems.com/post/implementing-imap-client-intersystems-iris-part-i). We override its methods with the imaplib methods instead of implementing the IMAP protocol from the beginning. First, we create a new class named dc.demo.imap.python.IMAPPy. This class uses two properties to store references to Python objects: Class dc.demo.imap.python.IMAPPy Extends dc.demo.imap.IMAP { /// Stores the imaplib object reference Property imaplib As %SYS.Python; /// Stores the imaplib client instance Property client As %SYS.Python; ... Next, we import the imaplib library into the ObjectScript context, in the class constructor: Method %OnNew() As %Status [ Private ] { Set ..imaplib = ##class(%SYS.Python).Import("imaplib") Return $$$OK } Now, we can access all imaplib properties and methods using the imaplib class property. The first method that we override was the Connect method. This method uses the imaplib IMAP4_SSL method to make a connection to the IMAP server. It stores the imaplib client instance as a client property. The login method of the imaplib client will authenticate login requests, as follows: Method Connect(pServer As %String, pUserName As %String, pPassword As %String) As %Status { If ..Connected Return $$$ERROR($$$ConnectedError) Set sc = $$$OK Try { Set ..Server = pServer Set ..UserName = pUserName Set ..client = ..imaplib."IMAP4_SSL"(..Server) Set resp = ..client.login(..UserName, pPassword) Set ..Connected = 1 } Catch ex { Set sc = ex.AsStatus() } Return sc } The next method we override is the Disconnect method. This method now calls the logout method from the imaplib client: Method Disconnect() As %Status { Set sc = $$$OK Try { If ..Connected { Set tuple = ..client.logout() Set ..Connected = 0 } } Catch ex { Set sc=ex.AsStatus() } Return sc } The method GetMailBoxStatus was overridden to use the select method from imaplib to specify which mailbox to access. Method GetMailBoxStatus(ByRef NumberOfMessages As %Integer, ByRef NumberOfBytes As %Integer) As %Status { Set sc = $$$OK Try { Do ..CheckConnection() Set resp = ..client.select(..MailboxName) Set ackToken = resp."__getitem__"(0) Set dataArray = resp."__getitem__"(1) Set NumberOfMessages = dataArray."__getitem__"(0) Set NumberOfBytes = -1 } Catch ex { Set sc=ex.AsStatus() } Return sc } Note that this method returns a tuple, so the special method \_\_getitem\_\_ allows us to retrieve information. Also, remember that a tuple can store another tuple, so we can recursively use \_\_getitem\_\_. The following method overridden was GetSizeOfMessages. This method now uses the select method to choose the current mailbox and the fetch method to get the size of the message stored in the MessageNumber parameter. Method GetSizeOfMessages(MessageNumber As %String = "", ByRef ListOfSizes As %ArrayOfDataTypes) As %Status { Set sc = $$$OK Try { Do ..CheckConnection() // select the mailbox Set resp = ..client.select(..MailboxName) // hack to ensure that MessageNumber is of type %String Set MessageNumber = MessageNumber_"" Set resp = ..client.fetch(MessageNumber, "(RFC822.SIZE)") Set ackToken = resp."__getitem__"(0) Set dataArray = resp."__getitem__"(1) Set:('$ISOBJECT($Get(ListOfSizes))) ListOfSizes = ##class(%ArrayOfDataTypes).%New() Set data = dataArray."__getitem__"(0) Set msgIdx = +$Piece(data, " ", 1) Set size = +$Piece(data, " ", 3) Do ListOfSizes.SetAt(size, msgIdx) } Catch ex { Set sc=ex.AsStatus() } Return sc } We override the GetMessageUIDArray method in the same way to use the fetch method, but now we use it to get the UID codes: Method GetMessageUIDArray(MessageNumber As %String = "", ByRef ListOfUniqueIDs As %ArrayOfDataTypes) As %Status { Set sc = $$$OK Try { Do ..CheckConnection() // select the mailbox Set resp = ..client.select(..MailboxName) Set mailboxSize = resp."__getitem__"(1)."__getitem__"(0) If (mailboxSize > 0) { // hack to ensure that MessageNumber is of type %String Set MessageNumber = MessageNumber_"" // then get the mailbox UIDs Set param = $CASE(MessageNumber, "":"1:*", :MessageNumber) Set resp = ..client.fetch(param, "UID") Set ackToken = resp."__getitem__"(0) Set dataArray = resp."__getitem__"(1) Set len = dataArray."__len__"() } Else { Set len = 0 } Set:('$ISOBJECT($Get(ListOfUniqueIDs))) ListOfUniqueIDs = ##class(%ArrayOfDataTypes).%New(len) For i = 1:1:len { Set data = dataArray."__getitem__"(i - 1) Set msgIdx = +$Piece(data, " ", 1) Set size = +$Piece(data, " ", 3) Do ListOfUniqueIDs.SetAt(size, msgIdx) } } Catch ex { Set sc=ex.AsStatus() } Return sc } Note the use of the \_\_getitem\_\_ and \_\_len\_\_ methods to iterate over the tuples in the dataArray variable: … Set len = dataArray."__len__"() … For i = 1:1:len { Set data = dataArray."__getitem__"(i - 1) Set msgIdx = +$Piece(data, " ", 1) Set size = +$Piece(data, " ", 3) Do ListOfUniqueIDs.SetAt(size, msgIdx) } Next, we override the Fetch method, which we use to retrieve the whole message body: Method Fetch(MessageNumber As %Integer, ByRef Msg As %Net.MailMessage, Delete As %Boolean, messageStream As %BinaryStream) As %Status { Set sc = $$$OK Try { Do ..CheckConnection() // select the mailbox Set resp = ..client.select(..MailboxName) // hack to ensure that MessageNumber is of type %String Set MessageNumber = MessageNumber_"" // get the whole message Set resp = ..client.fetch(MessageNumber, "BODY.PEEK[]") Set rawMsg = ..TransversePythonArray(resp."__getitem__"(1)) ... } Catch ex { Set sc=ex.AsStatus() } Return sc } Note the presence of the method TransversePythonArray. Because the message body returned by the fetch method is a composition of collections, we created this method to recursively transverse this collection and flatten it into a single string. ClassMethod TransversePythonArray(pArray As %SYS.Python) As %String { Set acc = "" If ($IsObject(pArray)) { Set len = pArray."__len__"() For i = 1:1:len { Set item = pArray."__getitem__"(i - 1) If ($IsObject(item)) { Set acc = acc_..TransversePythonArray(item) } Else { Set acc = acc_item } Set acc = acc_$Char(13, 10) } } Else { Set acc = pArray_$Char(13, 10) } Return acc } We also override the Ping method to use the imaplib noop method. Method Ping() As %Status { Set sc = $$$OK Try { Do ..CheckConnection() Set resp = ..client.noop() } Catch ex { Set sc=ex.AsStatus() } Return sc } The last method overridden was the CommitMarkedAsDeleted method. It now uses the methods store and expunge to mark messages for deletion and to commit such operations. Method CommitMarkedAsDeleted() As %Status [ Internal, Private ] { Set sc = $$$OK Try { Do ..CheckConnection() // select the mailbox Set resp = ..client.select(..MailboxName) // transverse array in inverse order to keep numbers integrity, // that is, ensures that when the number is deleted no other // message can assume such number Set messageNumber = $Order(..MarkedAsDeleted(""), -1) While (messageNumber '= "") { // hack to ensure that messageNumber is of type %String Set messageNumber = messageNumber_"" Set resp = ..client.store(messageNumber, "+FLAGS", "\Deleted") Set messageNumber = $Order(..MarkedAsDeleted(messageNumber), -1) } Kill ..MarkedAsDeleted Set resp = ..client.expunge() } Catch ex { Set sc=ex.AsStatus() } Return sc } ## Conclusion This method is much easier to implement compared to the original one, where we had to implement each IMAP command manually using IRIS TCP commands. Now that you’ve seen a good example of how we can use the rich Python library ecosystem for real-world problems, start powering up your ObjectScript applications! ## References * [imaplib — IMAP4 protocol client](https://docs.python.org/3/library/imaplib.html) * [Video: Embedded Python in InterSystems IRIS: Sneak Peek](https://community.intersystems.com/post/new-video-embedded-python-intersystems-iris-sneak-peek) * [Embedded Python: Bring the Python Ecosystem to Your ObjectScript App](https://learning.intersystems.com/course/view.php?id=1572) * [Learn Python Network Programming: Python - IMAP](https://www.tutorialspoint.com/python_network_programming/python_imap.htm) * [Python Documentation: Recipes and Best Practices](https://docs.python.org/3/library/secrets.html#recipes-and-best-practices) * [Python Documentation: Data Model](https://docs.python.org/3/reference/datamodel.html) * [WebSocket Client with Embedded Python](https://community.intersystems.com/post/websocket-client-embedded-python) * [InterSystems Developer Community: #Python](https://community.intersystems.com/tags/python) Hi, @José.Pereira! Ia it possible to build a ZPM module for the case? And publish it on Open Exchange?
Announcement
Evgeny Shvarov · Dec 28, 2021

Technology Bonuses for InterSystems IRIS Datasets Contest 2021

Hi Developers! Here're the technology bonuses for the InterSystems IRIS Datasets Contest 2021 that will give you extra points in the voting: Dataset Usage Demo Repository - 4 LOAD DATA Usage - 3 Questionnaire - 2 Unique Real Dataset - 4 Docker container usage - 2 ZPM Package deployment - 3 Online Demo - 2 Code Quality pass - 1 First Article on Developer Community - 2 Second Article On DC - 1 Video on YouTube - 3 See the details below. Dataset Usage Demo Repository - 4 points Your application for the contest is a dataset itself. So it's very important and helpful if you submit another repo with the usage example of the data. Just mention the second demo repository in the README.md of your dataset repo and collect 4 extra points. LOAD DATA Usage - 3 points InterSystems IRIS 2021.2 preview release comes with the new feature to LOAD DATA. Use it in your dataset or demo repo and collect 3 extra points. Questionnaire - 2 Share your feedback in the questionnaire and collect 2 extra points! Unique Real Dataset - 4 Publish a new real-world dataset that has at least 10k rows and is not trivial and collect 4 bonus points. A good example of a trivial dataset could be the temperature reading of your Google Nest device. We will count the trivial once of a kind, the first published get the preference. Docker container usage - 2 points The application gets a 'Docker container' bonus if it uses InterSystems IRIS running in a docker container. Here is the simplest template to start from. ZPM Package deployment - 3 points You can collect the bonus if you build and publish the ZPM(ObjectScript Package Manager) package for your Full-Stack application so it could be deployed with: zpm "install your-multi-model-solution" command on IRIS with ZPM client installed. ZPM client. Documentation. Online Demo of your project - 2 pointsCollect 2 more bonus points if you provision your project to the cloud as an online demo. You can do it on your own or you can use this template - here is an Example. Here is the video on how to use it. Code quality pass with zero bugs - 1 point Include the code quality Github action for code static control and make it show 0 bugs for ObjectScript. Article on Developer Community - 2 points Post an article on Developer Community that describes the features of your project and collect 2 points for the article. The Second article on Developer Community - 1 point You can collect one more bonus point for the second article or the translation regarding the application. The 3rd and more will not bring more points but the attention will all be yours. Video on YouTube - 3 points Make the Youtube video that demonstrates your product in action and collect 3 bonus points per each. The list of bonuses is subject to change. Stay tuned! Good luck in the competition! UPD: Using Demo repo SHOULD have the functionality that shows the usage of the dataset - analytics, any meaningful UI around, etc. - something that shows why the dataset is good and how it can be used. Same for the Online Demo What is Unique Real Dataset? Real data means - not generated data. Unique means new and never existed before. In fact, it is the dataset you own - e.g. your collection of coins, or your library. Or the set of observations of any kind. Thanks I think dataset-finance should qualify as Unique Real Dataset.
Article
Yuri Marx · Jan 5, 2022

InterSystems IRIS Open Datasets for predict important diseases

According to the WHO, The top global causes of death, in order of total number of lives lost, are associated with three broad topics (source: https://www.who.int/news-room/fact-sheets/detail/the-top-10-causes-of-death): Cardiovascular (ischaemic heart disease, stroke), Respiratory (chronic obstructive pulmonary disease, lower respiratory infections) and Neonatal conditions – which include birth asphyxia and birth trauma, neonatal sepsis and infections, and preterm birth complications. I created an application that's provides real data (without personal data) for some of these top 10 scenarios of diseases identified by WHO. The datasets for this application are: Diabetes dataset: data to predict diabetes diagnosis Heart Disease: data to predict heart disease Kidney Disease: data to predict kidney disease Breast Cancer: data to predict breast cancer Maternal Health Risk: data to predict maternal health risk level To download and install the application go to https://openexchange.intersystems.com/package/Health-Dataset Follow these instructions: 1. Clone/git pull the repo into any local directory $ git clone https://github.com/yurimarx/automl-heart.git 2. Open a Docker terminal in this directory and run: $ docker-compose build 3. Run the IRIS container: $ docker-compose up -d 4. Do a Select to the HeartDisease dataset: SELECT age, bp, chestPainType, cholesterol, ekgResults, exerciseAngina, fbsOver120, heartDisease, maxHr, numberOfVesselsFluro, sex, slopeOfSt, stDepression, thallium FROM dc_data_health.HeartDisease 5. Do a Select to the Kidney Disease dataset: SELECT age, al, ane, appet, ba, bgr, bp, bu, cad, classification, dm, hemo, htn, pc, pcc, pcv, pe, pot, rbc, rc, sc, sg, sod, su, wc FROM dc_data_health.KidneyDisease 6. Do a Select to the Diabetes dataset: SELECT Outcome, age, bloodpressure, bmi, diabetespedigree, glucose, insulin, pregnancies, skinthickness FROM dc_data_health.Diabetes 7. Do a Select to the Breast Cancer dataset: SELECT areamean, arease, areaworst, compactnessmean, compactnessse, compactnessworst, concavepointsmean, concavepointsse, concavepointsworst, concavitymean, concavityse, concavityworst, diagnosis, fractaldimensionmean, fractaldimensionse, fractaldimensionworst, perimetermean, perimeterse, perimeterworst, radiusmean, radiusse, radiusworst, smoothnessmean, smoothnessse, smoothnessworst, symmetrymean, symmetryse, symmetryworst, texturemean, texturese, textureworst FROM dc_data_health.BreastCancer 8. Do a Select to the Maternal Health Risk dataset: SELECT BS, BodyTemp, DiastolicBP, HeartRate, RiskLevel, SystolicBP, age FROM dc_data_health.MaternalHealthRisk These datasets can be used into AutoML/Machine Learning applications to support breast cancer, heart disease, kidney disease and diabetes diagnostics (support only, because human doctor diagnosis is mandatory). Enjoy! Hi Yuri, Your video is now on InterSystems Developers YouTube: ⏯ Health Datasets using InterSystems IRIS Have a good weekend) Great! Thanks!
Discussion
Evgeny Shvarov · Jul 20, 2021

What is the Best Tool to Edit Data in InterSystems IRIS?

Hi folks! How do you edit data in IRIS or Caché? What do you use? Change globals directly via Management Portal? Change data using SQL? Use your favorite dev tool? Which one? Crafted your own? Share your experience, please? Hi, we are updating the data using an update query via the management portal. Globals need to change then we are using the terminal to change it. Recently, started to Visual studio code extension of SQL Tools. but frequently check and update the above would not work out. each time change query parameters. so we created a zen page to do the CRUD operations to the particular table. I see, thank you @Karunanithi.Veerarajan I don't have a real favorite. - for similar changes in multiple records, I use SQL in SMP, rarely also $system.SQL.Shell() from terminal- for single changes, I use Global Edit in SMP and direct access in terminal equally- for special objects I often write my class related customized edit method I believe the best answer is: It depends.Depends on the data architecture of the original project, whether the data structure is GLOBAL, relative SQL or Objects. For example, in my current project, I have data in objects originating from Ensemble and metrics and monitoring data in relational tables. The native part of Ensemble is never subject to change, but the part concerning relational tables sometimes needs editing. When it happens I prefer to use third party SQL manager like DBeaver. In another project, fully specified in Globals, the preferred way of editing large amounts of data was to write scripts in ObjectScript. Edit globals directly, only in very specific situations. And keep in mind that, if the global is referring to an SQL table, there is always the risk of corrupting an index. Hi. The team I work in has been supporting old MUMPS and then Cache systems for many years, and have two rules for fixing data on live systems: 1. Never write a kill statement directly at the command line.It's quick and convenient, but we've seen many occasions where big chunks of, or, before the database parameter to stop it, whole globals were removed by accident. Cue major panics, hours of restore and de-journal. etc. 2. Don't write SQL updates directly (SMP, command line, etc). Because if you get the WHERE wrong then all rows in a table suddenly vanish or have the same value. :-) So we use a local command line tool for global amendments that uses the old %G style selection search to display one node at a time, so that you can then edit the data, or kill (with a warning first if there are sub nodes you may have forgotten about). We also have a local command line tool for SQL/objects. This takes in a table name and WHERE clause, and only allows editing and deleting when the query finds only one row. Anything more than a few nodes/rows and we usually write a proper bit of script on our dev server, and get it checked and tested before running in live. Better safe than sorry. What a thrilling and scary story, Mike! I need this editing feature for development purposes only. Thanks Marcio, I agree Why such a complicated question, I wonder. Can anyone answer immediately the "Best Tool" for any given job (other than a salesman, of course)? I'm a fan of writing my own SQL commands on the SQL Browser (it gives me a sense of power that comes from using the raw tools some deity provided for me) but hey, if it's as simple as editing a bunch of records, well my choice is Dbeaver Community Edition (through JDBC) but it's not the only one based on java (that's why JDBC driver is needed). The one I downloaded came with its own OpenJDK (but it's not full java as some .dll, .dylib or .so libraries are included). It seems you can even install it as some Eclipse plugin if you want! I haven't tested this one yet though. Well it's simple and you can use the jar that's in the <instance-dir>/dev/java/lib/JDK11/intersystems-jdbc-<version>.jar. It offers to download one as you establish your first connection to an "InterSystems IRIS" or "Cache" database, check this Dbeaver officially supports .... It has a nice "view data" for a table and allows to edit in a grid (you have to "save" in order to trigger all the UPDATE commands necessary or see them prior to submitting/saving). It's filterable so you see just a range of data you want to edit as in "ID between 40 and 50". If you have some primary key (other than the ID column which is hidden to the beaver but you still can use it to filter data) then the updates will use it no questions asked, otherwise you can use all the columns for the updates but you know how that can have unwanted repercussions. It also has the usual import and export (using csv files with mapped columns, just don't use any identity columns!) and the community edition is supposed to be under an apache license. If you really like of course you can buy some license that gives you a full load of functionalities but if it's just to edit some records, I'd stick to the community edition. Thanks, Robert! For those who are not aware - SMP stands for System Management Portal - the web UI to manage IRIS. Thanks, Robert! For those who are not aware - SMP stands for System Management Portal - the web UI to manage IRIS. Thanks, Pablo! Yes, I like DBeaver too. RESTForms, duh.
Article
Yuri Marx · Oct 29, 2021

Enterprise Architecture views with InterSystems IRIS and Zachman Framework

The Zachman Framework™ is an ontology - a theory of the existence of a structured set of essential components of an object for which explicit expressions is necessary and perhaps even mandatory for creating, operating, and changing the object (the object being an Enterprise, a department, a value chain, a “sliver,” a solution, a project, an airplane, a building, a product, a profession or whatever or whatever). Source: https://www.zachman.com/about-the-zachman-framework. In this article I use the Zachman Framework to detail how can you use InterSystems IRIS to promote your enterprise architecture project. The InterSystems IRIS can represent things important to the business using Persistent Classes with encapsulated reusable business logic that can be consumed as REST, Language Gateways (Python, Java, .Net and Node.js) or into IRIS productions (BPL, Business Services and Business Operations). The Analytics dashboards created with IRIS Analytics (Deepsee), IRIS Reports and IRIS Adaptative Analytics (AtScale) materialize business important things as dashboards for business staff. Finally, the InterSystems IRIS Interoperability productions automate things important to the business with BPL, DTL, Business Rules and Business Services and Operations in a business component consumed as REST, HTTP resource and other popular formats and protocols. The InterSystems IRIS automate business processes, including human tasks, using InterSystems IRIS productions with BPL. The business process indicators can be monitored using InterSystems Analytics capabilities (DeepSee, IRIS Reports and IRIS Adaptative Analytics) The InterSystems IRIS supports the main languages (english, portuguese, spanish, japanese and other) to operate the business globally. The database, components and analytics artifacts can be deployed in a distributed network or in the cloud. The InterSystems IRIS supports the definition of roles, people and resources with a integrated security model into the API Gateway (APIM) and in the database, interoperability and component layers, using OAuth, JWT, LDAP, RBAC and other models. In the Analytics users can colaborate and share business artifacts, creating corporate insights. The InterSystems IRIS has support to the international time zones and support operate data and application as real time or batch schedule events as syncronous or asyncronous request or responses, using the most popular protocols (kafka, mqtt, rest, http, smtp, and other). The data into these events can be monitored and analyzed with IRIS Analytics options (DeepSee, SAM, Adaptative Analytics and IRIS Reports). The IRIS Analytics options (Deepsee, IRIS Reports, Adaptative Analytics) allows you create KPIs to analyse the progress of business goals and strategies. The IRIS API Management can map business goals and strategies to the corporate REST Services (digital business assets) and promote its reuse with InterSystems Interoperability productions (create compositions to realize the strategy). The IRIS Multimodel Database is prepared to support relational, class oriented, analytics and document data models. The IRIS Interoperability productions can use BPL to model and execute business processes and can compose the use of machine learning, Java, .Net, Python and Object Script components and other corporate digital assets consumed using adapters. The IRIS deployment model supports creating business microsservices into docker services distributed into business services or technology services (ESB as service, Analytics as service, Database as service) into private and public clouds. The InterSystems IRIS interoperability BPL can model and execute workflows with automated and human tasks. With InterSystems IRIS you can schedule the deployment of reports (InterSystems Reports), dashboads output (DeepSee) and component/orchestration logic using the InterSystems BPL and Business Rules engine. IRIS support produce and consume events and messages too, including MQTT (IoT), Kafka and JMS. The Business Plan can be realized using IRIS Data Platform in all layers: 1. Data: planning to get, process and analyse data can be done with IRIS Interoperability BPL and Adapters with data storage in a multimodel database (SQL, Document/JSON, OLAP). 2. Application: create services and microservices using Java, .Net, Python and ObjectScript as REST services or interoperability services that realize the business requirements planned. 3. Technology: the business continuity is possible because IRIS supports HA and distributed computing in Data (shards), in Application (docker services) and in analytics (docker analytics services). The InterSystems IRIS create your ORM model automatically (each class is a table and properties can be relations between classes). So your logical model is translated to pyshical model as SQL and Classes at same time. The Application architecture in the InterSystems IRIS can be monolitic, as services or as microservices, because IRIS supports host, docker and kubernetes deployments. The IRIS application architecture is open to the main languages (Java, .Net, Python, ObjectScript and Node.js/JavaScript). Finally the IRIS application architecture supports analytics, data and language services and microservices implementations. IRIS supports AWS, Azure, Google Cloud and other public and private distributed architectures. IRIS supports sharding to distributed data repositories too. For applications, IRIS can serve data responses to Angular, Vue, React, React Native, Flutter and other popular UI options, including NPM package to allows the controller classes interact with IRIS components using Node.js/Javascript. In the analytics area, IRIS deliver analytics insights to Power BI, Tableau and Excel (Adaptative Analytics). The processing into IRIS can be asyncronous or syncronous. All processing can be orchestrated using APIM or using IRIS ESB/BPL. The dashboards and reports can be processed into the User Portal or into the the applications (embedded). The InterSystems IRIS has a business rules engine integrated to the BPL workflow, allow you using the business rules with your business process or data/service workflows. For AI business rules is possible compose with Python and R machine learning components inside the business process (BPL) or you can use IntegratedML too, to train and execute AI rules using SQL sentences. The Physical Data Model in IRIS can be monolitic or distributed (shards) and the data is multimodel (SQL, NoSQL (JSON), OLAP and Virtual Cubes (AtScale)). The InterSystems IRIS allows you design analytical, data, interoperability and open language systems into monolitic or microservice deployments, using private or public clouds. With IRIS the technology architeture is end-to-end, including: 1. API Management with InterSystems API Management; 2. ESB, Integration Adapters and Workflow with InterSystems Interoperability (Ensemble); 3. Business Services and Microservices using the most popular languages; 4. Analytics with IRIS Reports, IRIS Adaptative Analytics and DeepSee; 5. Advanced Analytics and Data Science with IntegratedML and Python/R gateways; 6. Deployment into VM, Docker, Kubernetes or hosts. IRIS deliver responses and process requests using REST/API Gateway or using Node.js NPM package. For analytical visualizations, IRIS deliver MDX or SQL data for PowerBI, Tableau and other. The InterSystems IRIS allow you control: 1. API with InterSystems API Management; 2. Services and Microservices with InterSystems API Management and InterSystems Interoperability productions (BPL); 3. Services and Microservices with Language Gateways (for Java, Python, .Net and Javascript/Node.js); 4. Data as InterSystems IRIS multimodel database (SQL, NoSQL - JSON - DocDB, OLAP - DeepSee); 5. Analytical with IRIS Analytics and Adaptative Analytics (AtScale); 6. Cognitive with IRIS IntegratedML and Python/R language support. The InterSystems IRIS has a rule engine inside InterSystems Interoperability.
Announcement
Evgeny Shvarov · Sep 10, 2021

Technology Bonuses Results for Projects in the InterSystems Analytics Contest!

Hi Developers! We had a set of technology bonuses for the InterSystems IRIS Analytics contest. And here is how projects collected it: Project AtScale PowerBI Tableau Logi IRIS BI IRIS NLP Docker ZPM Unit Testing Online Demo Article on DC Video on YouTube Total Bonus Nominal 4 3 3 3 3 3 2 2 2 3 2 3 33 iris-analytics-datastudio 3 3 3 9 promjet-stats 4 3 3 3 2 3 18 pop-song-analytics 3 2 5 Analytics OKR 3 2 2 2 9 iris-analytics-for-money 3 2 5 AlertDashboard 3 3 We can discuss bonuses here or on the Discord channel
Question
prashanth ponugoti · Nov 27, 2021

Monitoring Dashboard for InterSystems Heath share Health connect

Hi All, We have a requirement for one webpage that should be access in our VPN with out authentication. If it asks user name password that also fine. This page should be a dashboard for the ensemble health monitoring. Support Team seating Area we have big SMART Monitor which always shows this webpage. Support engineers keep on eye on this monitor, if it shows action required then . they will act upon immediately. Expecting some widgets like Queue Status Inbound application status Out bound operations status Database statistics Mirror Information etc. I can see some widgets in management portal. But We need separate web application page. I am developing one solution for my support team requirements. Here I am going to Propose Solution. Ensemble Integration: Create Customized Business Service to poll Cache to get the required details and send to Business Process Create Customised Business Process to check the configured business rules and invoke Business Operation. Create a Business Operation to make a POST call for to my Rest Service. Rest Service: This Service Parse JSON Payload and insert or update into respective table in MYSQL database instance React Web Page: This UI will show the DB summary in respective widgets Please advice me any alternative Idea? Is there any tolls available for this? Thanks, Prashanth It's better to look at something like Grafana. Here are a few articles about using it. Big article with many details and my article with direct connection to IRIS If you need some help with the development and configuration of such monitoring, I can help with it. Another solution can be with SAM : https://docs.intersystems.com/components/csp/docbook/DocBook.UI.Page.cls?KEY=ASAM https://community.intersystems.com/post/new-video-viewing-customizing-metrics-sam You can also enable interoperability metrics (only on IRIS 2021.1+) with : // Enable Intero metrics for SAM zw ##class(Ens.Util.Statistics).EnableSAMForNamespace() zw ##class(Ens.Util.Statistics).EnableSAMIncludeHostLabel()
Question
Martin Fukátko · Nov 27, 2021

VSCode can't start InterSystems Language Server

Hi, I have VSCode on my Windows 10 notebook with intersystems-community.objectscript-pack installed. I'm successfully connected to remote IRIS (2021.1). I can export classes, change them, save and import back to IRIS. But every time VSCode starts, the message "Request initialize failed with message: Dynamic Linking Error: Win32 error 126" is displayed and InterSystems Language Server does not start. Has anyone solved this problem yet? Windows 32bit, is not it? Only 64 bit is supported. Are you using 32-bit Windows? If so, see https://github.com/intersystems/language-server/issues/197 I think same issue as https://githubmemory.com/repo/intersystems/language-server/issues/186?page=2 . @pvdmm Thanks for the log, I think that your problem is due to a couple of missing DLLs: msvcp120.dll and msvcr120.dll These can be installed using the Visual C++ 2013 redistributable package available from https://support.microsoft.com/en-us/topic/update-for-visual-c-2013-redistributable-package-d8ccd6a5-4e26-c290-517b-8da6cfdf4f10 This is a link to an page talking about a bugfix update but it is the latest version (5) of these tools, linked from a Microsoft page titled "The latest supported Visual C++ downloads". Please install this and then try running VSCode again. If this fixes your problem the Language Server team can work out the best way to fix this issue for future installations of the extension. Thank you @Ohata.Yuji You seem to be right. In the meantime, I managed to start Language Server as follows:VScode runs smoothly on my second computer, so I looked for differences. I have Caché installed on the second computer, Iris on the troubled one. The problem disappeared when I installed Caché on the troubled one. It is Windows 64 bit. But the problem is solved now.
Announcement
Anastasia Dyubaylo · Dec 9, 2021

Video: InterSystems HealthShare Unified Care Record

Hey Developers, Learn about the recent changes to InterSystems HealthShare Unified Care Record and what is coming next: ⏯ InterSystems HealthShare Unified Care Record Presenters:🗣 @Sebastian.Musielak, Product Manager, HealthShare Operations, InterSystems🗣 Melanie Davies, Product Manager, Unified Care Record, InterSystems Subscribe to the InterSystems Developers YouTube channel and stay tuned!
Article
José Pereira · Sep 15, 2021

Implementing an IMAP Client in InterSystems IRIS - part II

In the first part we got a quick introduction on the IMAP protocol commands, now it's time to use IRIS and implement them and create our own IMAP client! IRIS Email Framework The IRIS platform has default interfaces and classes for working with email. Developers originally designed those artifacts for POP3 implementation. However, this doesn’t mean that we can’t use and extend these interfaces and classes to implement an IMAP client. So let’s talk about them: %Net.FetchMailProtocol: This is the base class for email retrieval. The IMAP client extends it. %Net.MailMessage: This is the MIME message. It extends %Net.MailMessagePart. %Net.MailMessagePart: This encapsulates a MIME message part for multipart messages. This class has an array for itself, enabling a tree representation of message subparts. %Net.MIMEReader: This utility class has methods to parse a message’s MIME content, generating a %Net.MIMEPart instance. %Net.MIMEPart: This encapsulates the message’s MIME parts and provides methods to get information about them. Implementing an IMAP Client In this section, we present implementation details about an IMAP client, an inbound interoperability adapter, and a simple production example. Note that, in favor of saving space, we won’t show most implementation methods. Instead, we link to each one’s full implementation details. You can find the complete source code on GitHub. Creating a Basic IMAP Client As we discussed before, IMAP is a plain text-based protocol over TCP. This means the base code to implement a client for such a protocol is a TCP client. The IRIS platform provides standard ObjectScript commands to perform I/O operations: OPEN, USE, READ, WRITE, and CLOSE. Here is a simple example of how to connect to the MS Outlook server, log in, then log out: ClassMethod SimpleTest() { // connection configuration SET dev = "|TCP|993" SET host = "outlook.office365.com" SET port = "993" SET mode = "C" SET sslConfig = "ISC.FeatureTracker.SSL.Config" SET timeout = 30 // connection to MS Outlook IMAP server OPEN dev:(host:port:mode:/TLS=sslConfig):timeout THROW:('$TEST) ##class(%Exception.General).%New("Sorry, can't connect...") USE dev READ resp($INCREMENT(resp)):timeout WRITE "TAG1 LOGIN user@outlook.com password", ! READ resp($INCREMENT(resp)):timeout WRITE "TAG2 LOGOUT", ! READ resp($INCREMENT(resp)):timeout CLOSE dev // come back to default device (terminal) and prints responses USE 0 ZWRITE resp } This is its output: USER>d ##class(dc.Demo.Test).SimpleTest() resp=3 resp(1)="* OK The Microsoft Exchange IMAP4 service is ready. [QwBQ..AA==]"_$c(13,10) resp(2)="TAG1 OK LOGIN completed."_$c(13,10) resp(3)="* BYE Microsoft Exchange Server IMAP4 server signing off."_$c(13,10)_"TAG2 OK LOGOUT completed."_$c(13,10) There are some highlights in this code: We set the mode variable to C, which is carriage return mode. This setting is mandatory for IMAP. The flag /TLS establishes a secure layer of communication (SSL). We must set this flag value to a valid SSL IRIS connection. The OPEN command initiates the connection. The special boolean variable $TEST returns 1 when a command with a timeout is successful or 0 if the timeout expires. In this example, if the OPEN command exceeds 30 seconds, the code throws an exception. After a connection is established successfully, the command USE owns the TCP device, redirecting all READ and WRITE commands to this device. The WRITE command issues commands to the IMAP server, and the READ command gets their output. To finish the connection, we must use the CLOSE command. After owning the device, all calls to READ and WRITE commands execute on the device specified in the dev variable, after using the USE dev command. To come back to the terminal and write to it again, you need to issue a USE 0 command first. Each READ command has a limited buffer to store the server response. When the response size exceeds this limit, you need to issue another READ command to read the complete response. Of course, it’s possible to increase the buffer size, but a better approach is to be ready to deal with such a situation. As we discussed before, IMAP requires a tag for each command. This tag is helpful to check if the code retrieved the complete response or if it needs to issue another READ command. In this case, we implement the ReadResponse method to ensure the code reads the whole message. Implementing the %Net.FetchMailProtocol Interface for IMAP The %Net.FetchMailProtocol abstract class abstracts email retrieval on the IRIS platform. We implement the following methods: Connect: This establishes a connection to the IMAP server and logs in a user. GetMailBoxStatus: This gets the size of the mailbox and how many messages are in it. GetSizeOfMessages: This gets the size of one or all messages identified by a message number. GetMessageUIDArray: This gets an array with one or all message UIDs in the inbox. GetMessageUID: This gets the UID corresponding to a message number. Fetch: This retrieves a message’s content, possibly multipart content, identified by a message number. It retrieves the message content encapsulated in a %Net.MailMessage object. FetchFromStream: This is the same as Fetch, but gets content from an encapsulated EML message content in a %BinaryStream object, instead of calling the IMAP server. FetchMessage: This is the same as Fetch, but returns specific message headers in ByRef variables. FetchMessageInfo: This retrieves only message headers and the text of the message. DeleteMessage: This adds a message to the deletion array. RollbackDeletes: This cleans up the deletion array. QuitAndCommit: This deletes all messages in the deletion array and disconnects from the IMAP server. QuitAndRollback: This cleans up the deletion array and disconnects from the IMAP server. Ping: This pings the IMAP server to keep the session alive. First, we create a new class to implement the interface: dc.Demo.IMAP. This class inherits several properties, which we must set to establish a connection to the IMAP server. We create a helper class as well: dc.Demo.IMAPHelper. This class parses methods for IMAP responses, gets all parts of a multipart message, and stores peripheral features, including a method to send commands and ensure the entire response is read. The first method we implement is the Connect method. This method establishes a connection to the IMAP server using the configuration encapsulated in the class properties. It issues a login as well. This method uses the IRIS platform’s OPEN command to establish the connection to the IMAP server and the IMAP command LOGIN to authenticate to the server. The next method we implement is GetMailBoxStatus. This method uses the SELECT command to select a mailbox and it brings some additional information as well, like how many messages are in the mailbox. IMAP doesn’t have a ready-to-use command to get the size of all messages. Of course, it’s possible to iterate through all messages and sum their sizes. However, this strategy will probably cause slowness issues. So in this implementation, we don’t retrieve the size for all messages. The next method is GetSizeOfMessages. This method gets the size of one or more messages in the inbox. When no message number is defined, this method throws an exception due to the same IMAP limitation we explained for the GetMailBoxStatus method. We use the IMAP command FETCH <message_number> (RFC822.SIZE) to retrieve a message size by its number. The GetMessageUIDArray method comes next, which uses the IMAP commands SELECT and UID SEARCH [ALL | <message_number>] and parses its response to get the UID array. The next method is GetMessageUID. This method gets a UID for a defined message number and uses the same logic as the GetMessageUIDArray method. Following this is the Fetch method. It uses the IMAP commands SELECT and FETCH <message_number> BODY to retrieve message content, which is coded in MIME format. Fortunately, the IRIS platform has a reader for MIME content, the %Net.MIMEReader class. This class gets the message in a stream and returns the parsed message in a %Net.MIMEPart object. After getting the MIME content, the method creates a %Net.MailMessage object, fills it with data from the %Net.MIMEPart object, and returns it. The MIME content is encapsulated in a %Net.MIMEPart object that maps into a %Net.MailMessagePart object through the GetMailMessageParts method in the dc.Demo.IMAPHelper class. The next method is FetchFromStream. This method receives a stream object with an EML message and converts it to a %Net.MailMessage object. This method does not retrieve content from the server. Following are the FetchMessage and FetchMessageInfo methods, which are special cases of the Fetch method. The DeleteMessage method marks a message for deletion, whereas the RollbackDeletes method just cleans up the array of messages marked for deletion. Next is the QuitAndCommit method. It disconnects from the IMAP server and calls the method CommitMarkedAsDeleted for message deletion. The method QuitAndRollback just disconnects from the IMAP server and cleans up the array of messages marked for deletion. The last method, Ping, issues a NOOP command to keep the IMAP session alive. Implementing an Inbound Interoperability Adapter for IMAP The base class for email interoperability inbound in the IRIS platform is EnsLib.EMail.InboundAdapter. This inbound adaptor requires these configurations: The email server host address The email server port A credential ID which stores the username and password for accessing the server An SSL configuration This class was extended to create a new IMAP inbound adapter class: dc.Demo.IMAPInboundAdapter. To use this new adapter, we set which mailbox to use in the Mailbox production parameter. Its default value is INBOX. The implementation is simple, it just overrides the MailServer property and sets its type to dc.Demo.POP3ToIMAPAdapter IMAP client. This adapter maps the POP3 flow to the IMAP one, as the base adapter class was designed for POP3 commands. Thus, this POP3 to IMAP adapter enables us to perform all the original inbound adapter logic using IMAP commands instead of POP3 commands. In the dc.Demo.POP3ToIMAPAdapter class, we use the IMAP client IMAPClient of type dc.Demo.IMAP as a proxy for server communication. However, as dc.Demo.POP3ToIMAPAdapter extends %Net.POP3, it must override all abstract methods in %Net.FetchMailProtocol. Also, we had to implement new methods that the %Net.POP3 client had implemented directly: ConnectPort and FetchMessageHeaders. In the same way, we created ConnectedGet and SSLConfigurationSet methods to set and get properties that %New.POP3 also implemented directly. Setting up a Simple Production To make all these classes work together, we set up a simple production. Check out Creating a Production to get more information about IRIS Interoperability productions. This production includes a business service and a business operation, which uses the IMAP inbound adapter to check for new messages. This code was inspired by the Demo.Loan.FindRateProduction interoperability sample. In short, this production: Uses the GetMessageUIDArray method to get all available messages in the configured mailbox Loops over them, tracing their output, fetched by the Fetch method Checks if each message subject matches a criterion — starting with "[IMAP test]" Responds to the sender if the message subject matches the criteria, otherwise ignores the message Deletes all of the messages so that it won’t analyze them again In this example, we configure an IMAP server from Yahoo Mail imap.mail.yahoo.com, on port 993. We also use the default IRIS SSL configuration “ISC FeatureTacker.SSL.Config”. Next, we configure a credential called imap-test containing a username and password, as follows: As the image below shows, the production starts and keeps querying the IMAP server for new messages. When there are new messages, the inbound adapter grabs their information, like the header and subject, and lets production take further action based on this information. In this example, the production checks if the message subject starts with "[IMAP test]" and sends back a message to the sender. When a message doesn’t match the criteria, production just ignores it. Conclusion In this article, we discussed an IMAP client implementation. First, we explored some essential background on IMAP and its main commands. Then, we detailed the implementation, covering the client itself and how to connect it to the IRIS platform. We also presented an extension to the default interoperability adapter to use IMAP, and a simple production example. Now that you know more about IMAP and its settings and you know how to connect it to IRIS, you can set up email capabilities in your applications. To learn more about the IMAP topics we discussed here, explore the resources below. Resources Atmail’s IMAP 101: Manual IMAP Sessions Fastmail’s Why is IMAP better than POP? IETF’s Internet Message Access Protocol IETF’s Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies InterSystems’ I/O Devices and Commands InterSystems’ Using the Email Inbound Adapter Nylas’ Everything you need to know about IMAP