#Open Exchange

0 Followers · 659 Posts

InterSystems Data Platform Solutions Open Exchange is a gallery of software solutions, tools, and frameworks which were developed with InterSystems Data Platform (Caché, Ensemble, HealthShare, InterSystems IRIS, InterSystems IRIS for Health) or are intended to help in development, deployment and support the solutions built with InterSystems Data Platform.

You can use any of the published assets or you can publish your own tool, technology example or solution.

Discover Open Exchange.

Article Robert Cemper · May 13, 2024 2m read

If one of your packages on OEX receives a review you get notified by OEX only of YOUR own package.   
The rating reflects the experience of the reviewer with the status found at the time of review.   
It is kind of a snapshot and might have changed meanwhile.   
Reviews by other members of the community are marked by * in the last column.

I also placed a bunch of Pull Requests on GitHub when I found a problem I could fix.    
Some were accepted and merged, and some were just ignored.     
So if you made a major change and expect a changed review just let me know.

0
0 93
Article Robert Cemper · May 3, 2024 1m read

If one of your packages on OEX receives a review you get notified by OEX only of YOUR own package.   
The rating reflects the experience of the reviewer with the status found at the time of review.   
It is kind of a snapshot and might have changed meanwhile.   
Reviews by other members of the community are marked by * in the last column.

I also placed a bunch of Pull Requests on GitHub when I found a problem I could fix.    
Some were accepted and merged, and some were just ignored.     
So if you made a major change and expect a changed review just let me know.

0
0 92
Article Robert Cemper · Apr 3, 2024 2m read

If one of your packages on OEX receives a review you get notified by OEX only of YOUR own package.   
The rating reflects the experience of the reviewer with the status found at the time of review.   
It is kind of a snapshot and might have changed meanwhile.   
Reviews by other members of the community are marked by * in the last column.

I also placed a bunch of Pull Requests on GitHub when I found a problem I could fix.    
Some were accepted and merged, and some were just ignored.     
So if you made a major change and expect a changed review just let me know.

0
0 90
Article Robert Cemper · Mar 12, 2024 2m read

If one of your packages on OEX receives a review you get notified by OEX only of YOUR own package.   
The rating reflects the experience of the reviewer with the status found at the time of review.   
It is kind of a snapshot and might have changed meanwhile.   
Reviews by other members of the community are marked by * in the last column.

I also placed a bunch of Pull Requests on GitHub when I found a problem I could fix.    
Some were accepted and merged, and some were just ignored.     
So if you made a major change and expect a changed review just let me know.

0
0 101
Article Yuri Marx · Mar 7, 2024 4m read

Killer presentations are essential for opening doors, doing business and delighting customers. These types of presentations move away from the traditional and tiring topics and portions of texts, or even pictures of happy people to get closer to the interests of their audience.The best presentations materialize what customers are looking for into something they can see working. Instead of promises, examples in execution and the ability to be very close to what you want to do.

2
2 245
Article Luis Angel Pérez Ramos · Feb 29, 2024 4m read

As most of you probably already know, since approximately the end of 2022 InterSystems IRIS included the columnar storage functionality to its database, well, in today's article we are going to put it to the test in comparison to the usual row storage.

Columnar Storage

What is the main characteristic of this type of storage? Well, if we consult the official documentation we will see this fantastic table that explains the main characteristics of both types of storage (by rows or by columns):

4
4 510
Article Lily Taub · Mar 19, 2019 9m read

Intro

Most server-client communication on the web is based on a request and response structure. The client sends a request to the server and the server responds to this request. The WebSocket protocol provides a two-way channel of communication between a server and client, allowing servers to send messages to clients without first receiving a request. For more information on the WebSocket protocol and its implementation in InterSystems IRIS, see the links below.

This tutorial is an update of "Asynchronous Websockets -- a quick tutorial" for Caché 2016.2+ and InterSystems IRIS 2018.1+.

Asynchronous vs Synchronous Operation

In InterSystems IRIS, a WebSocket connection can be implemented synchronously or asynchronously. How the WebSocket connection between client and server operates is determined by the “SharedConnection” property of the %CSP.WebSocket class.

  • SharedConnection=1 : Asynchronous operation

  • SharedConnection=0: Synchronous operation

A WebSocket connection between a client and a server hosted on an InterSystems IRIS instance includes a connection between the IRIS instance and the Web Gateway. In synchronous WebSocket operation, the connection uses a private channel. In asynchronous WebSocket operation, a group of WebSocket clients share a pool of connections between the IRIS instance and the Web Gateway. The advantage of an asynchronous implementation of WebSockets stands out when one has many clients connecting to the same server, as this implementation does not require that each client be handled by an exclusive connection between the Web Gateway and IRIS instance.

In this tutorial we will be implementing WebSockets asynchronously. Thus, all open chat windows share a pool of connections between the Web Gateway and the IRIS instance that hosts the WebSocket server class.

Chat Application Overview

The “hello world” of WebSockets is a chat application in which a user can send messages that are broadcast to all users logged into the application. In this tutorial, the components of the chat application include:

  • Server: implemented in a class that extends %CSP.WebSocket

  • Client: implemented by a CSP page

The implementation of this chat application will achieve the following:

  • Users can broadcast messages to all open chat windows

  • Online users will appear in the “Online Users” list of all open chat windows

  • Users can change their username by composing a message starting with the “alias” keyword and this message will not be broadcast but will update the “Online Users” list

  • When users close their chat window they will be removed from the “Online Users” list

For the chat application source code, please visit this GitHub repository.

The Client

The client side of our chat application is implemented by a CSP page containing the styling for the chat window, the declaration of the WebSocket connection, WebSocket events and methods that handle communication to and from the server, and helper functions that package messages sent to the server and process incoming messages.

First, we’ll look at how the application initiates the WebSocket connection using a Javascript WebSocket library.

    ws = new WebSocket(((window.location.protocol === "https:")? "wss:":"ws:")
                    + "//"+ window.location.host + "/csp/user/Chat.Server.cls");

new creates a new instance of the WebSocket class. This opens a WebSocket connection to the server using the "wss” (indicates the use of TLS for the WebSocket communication channel) or “ws” protocol. The server is specified by the web server port number and host name of the instance that defines the Chat.Server class (this information is contained in the window.location.host variable). The name of our server class (Chat.Server.cls) is included in the WebSocket opening URI as a GET request for the resource on the server.

The ws.onopen event fires when the WebSocket connection is successfully established, transitioning from a connecting to a open state.

    ws.onopen = function(event){
        document.getElementById("headline").innerHTML = "CHAT - CONNECTED";
    };

This event updates the header of the chat window to indicate that the client and server are connected.

Sending Messages

The action of a user sending a message triggers the send function. This function serves as a wrapper around the ws.send method, which contains the mechanics for sending the client message to the server over the WebSocket connection.

function send() {
	var line=$("#inputline").val();
	if (line.substr(0,5)=="alias"){
	    alias=line.split(" ")[1];
		if (alias==""){
		    alias="default";
		}
		var data = {}
		data.User = alias
		ws.send(JSON.stringify(data));
        } else {
	    var msg=btoa(line);
	    var data={};
	    data.Message=msg;
	    data.Author=alias;
	    if (ws && msg!="") {
		    ws.send(JSON.stringify(data));
	    }
	}
	$("#inputline").val("");
}

send packages the information to be sent to the server in a JSON object, defining key/value pairs according to the type of information being sent (alias update or general message). btoa translates the contents of a general message into a base-64 encoded ASCII string.

Receiving Messages

When the client receives a message from the server, the ws.onmessage event is triggered.

ws.onmessage = function(event) {
	var d=JSON.parse(event.data);
	if (d.Type=="Chat") {
	    $("#chat").append(wrapmessage(d));
            $("#chatdiv").animate({ scrollTop: $('#chatdiv').prop("scrollHeight")}, 1000);
	} else if(d.Type=="userlist") {
		var ul = document.getElementById("userlist");
		while(ul.firstChild){ul.removeChild(ul.firstChild)};
		$("#userlist").append(wrapuser(d.Users));
	} else if(d.Type=="Status"){
		document.getElementById("headline").innerHTML = "CHAT - connected - "+d.WSID;
	}
};

Depending on the type of message the client receives (“Chat”, “userlist”, or “status”), the onmessage event calls wrapmessage or wrapuser to populate the appropriate sections of the chat window with the incoming data. If the incoming message is a status update the status header of the chat window is updated with the WebSocket ID, which identifies the bidirectional WebSocket connection associated with the chat window.

Additional Client Components

An error in the communication between the client and the server triggers the WebSocket onerror method, which issues an alert that notifies us of the error and updates the page's status header.

ws.onerror = function(event) {
	document.GetElementById("headline").innerHTML = "CHAT - error";
	alert("Received error"); 
};

The onclose method is triggered when the WebSocket connection between the client and server is closed and updates the status header.

ws.onclose = function(event) {
	ws = null;
	document.getElementById("headline").innerHTML = "CHAT - disconnected";
}

The Server

The server side of the chat application is implemented by the Chat.Server class, which extends %CSP.WebSocket. Our server class inherits various properties and methods from %CSP.WebSocket, a few of which I’ll discuss below. Chat.Server also implements custom methods to process messages from and broadcast messages to the client(s).

Before Starting the Server

OnPreServer() is executed before the WebSocket server is created and is inherited from the %CSP.WebSocket class.

Method OnPreServer() As %Status
{
    set ..SharedConnection=1
    if (..WebSocketID '= ""){ 
        set ^Chat.WebSocketConnections(..WebSocketID)=""
    } else {
        set ^Chat.Errors($INCREMENT(^Chat.Errors),"no websocketid defined")=$HOROLOG 
    }
    Quit $$$OK
}

This method sets the SharedConnection class parameter to 1, indicating that our WebSocket connection will be asynchronous and supported by multiple processes that define connections between the InterSystems IRIS instance and the Web Gateway. The SharedConnection parameter can only be changed in OnPreServer(). OnPreServer() also stores the WebSocket ID associated with the client in the ^Chat.WebSocketConnections global.

The Server Method

The main body of logic executed by the server is contained in the Server() method.

Method Server() As %Status
{
    do ..StatusUpdate(..WebSocketID)
    for {		
        set data=..Read(.size,.sc,1) 
        if ($$$ISERR(sc)){
            if ($$$GETERRORCODE(sc)=$$$CSPWebSocketTimeout) {
                //$$$DEBUG("no data")
      	    }
            if ($$$GETERRORCODE(sc)=$$$CSPWebSocketClosed){
                kill ^Chat.WebSocketConnections(..WebSocketID)
                do ..RemoveUser($g(^Chat.Users(..WebSocketID)))	
                kill ^Chat.Users(..WebSocketID)
                quit  // Client closed WebSocket
            }
        } else{
            if data["User"{
                do ..AddUser(data,..WebSocketID)
            } else {
                set mid=$INCREMENT(^Chat.Messages)
                set ^Chat.Messages(mid)=data
                do ..ProcessMessage(mid)
            }
        }
    }
    Quit $$$OK
}

This method reads incoming messages from the client (using the Read method of the %CSP.WebSockets class), adds the received JSON objects to the ^Chat.Messages global, and calls ProcessMessage() to forward the message to all other connected chat clients. When a user closes their chat window (thus terminating the WebSocket connection to the server), the Server() method’s call to Read returns an error code that evaluates to the macro $$$CSPWebSocketClosed and the method proceeds to handle the closure accordingly.

Processing and Distributing Messages

ProcessMessage() adds metadata to the incoming chat message and calls SendData(), passing the message as a parameter.

ClassMethod ProcessMessage(mid As %String)
{
    set msg = ##class(%DynamicObject).%FromJSON($GET(^Chat.Messages(mid)))
    set msg.Type="Chat"
    set msg.Sent=$ZDATETIME($HOROLOG,3)
    do ..SendData(msg)
}

ProcessMessage() retrieves the JSON formatted message from the ^Chat.Messages global and converts it to an InterSystems IRIS object using the %DynamicObject class' %FromJSON method. This allows us to easily edit the data before we forward the message to all connected chat clients. We add a Type attribute with the value “Chat,” which the client uses to determine how to deal with the incoming message. SendData() sends out the message to all the other connected chat clients.

ClassMethod SendData(data As %DynamicObject)
{
    set c = ""
    for {
        set c = $order(^Chat.WebSocketConnections(c))
        if c="" Quit
        set ws = ..%New()
        set sc = ws.OpenServer(c)
        if $$$ISERR(sc) { do ..HandleError(c,"open") } 
        set sc = ws.Write(data.%ToJSON())
        if $$$ISERR(sc) { do ..HandleError(c,"write") }
    }
}

SendData() converts the InterSystems IRIS object back into a JSON string (data.%ToJSON()) and pushes the message to all the chat clients. SendData() gets the WebSocket ID associated with each client-server connection from the ^Chat.WebSocketConnections global and uses the ID to open a WebSocket connection via the OpenServer method of the %CSP.WebSocket class. We can use the OpenServer method to do this because our WebSocket connections are asynchronous – we pull from the existing pool of IRIS-Web Gateway processes and assign one the WebSocket ID that identifies the server’s connection to a specific chat client. Finally, the Write()%CSP.WebSocket method pushes the JSON string representation of the message to the client.

Conclusion

This chat application demonstrates how to establish WebSocket connections between a client and server hosted by InterSystems IRIS. For continue reading on the protocol and its implementation in InterSystems IRIS, take a look at the links in the introduction.

7
3 6042
Announcement Elena E · Feb 22, 2024

Big news from the Open Exchange platform!
We've been busy behind the scenes, not just giving the place a new look but also packing in some nifty features we think you'll love—many of which were inspired by your requests and feedback. It's all part of our ongoing mission to boost the quality of the apps and ensure the world sees the incredible work you're putting in. From streamlining your workflow to boosting collaboration, our aim is to support and highlight your creativity. Excited for you to explore and experience the new enhancements!

4
0 280
Article Robert Cemper · Feb 18, 2024 2m read

If one of your packages on OEX receives a review you get notified by OEX only of YOUR own package.   
The rating reflects the experience of the reviewer with the status found at the time of review.   
It is kind of a snapshot and might have changed meanwhile.   
Reviews by other members of the community are marked by * in the last column.

I also placed a bunch of Pull Requests on GitHub when I found a problem I could fix.    
Some were accepted and merged, and some were just ignored.     
So if you made a major change and expect a changed review just let me know.

0
0 146
Announcement Robert Cemper · Feb 11, 2024

If one of your packages on OEX receives a review you get notified by OEX only of YOUR own package.   
The rating reflects the experience of the reviewer with the status found at the time of review.   
It is kind of a snapshot and might have changed meanwhile.   
Reviews by other members of the community are marked by * in the last column.

I also placed a bunch of Pull Requests on GitHub when I found a problem I could fix.    
Some were accepted and merged, and some were just ignored.     
So if you made a major change and expect a changed review just let me know.

1
0 202
Article Maria Nesterenko · Jan 28, 2024 4m read

Striking a Balance Between Health Analytics and Engaging Features

In today's digital era, health and lifestyle apps have flooded the market, promising a wide array of benefits from fitness tracking to nutrition planning and focusing on trendy features, such as step counting, calorie tracking, and habit monitoring. While  the surge in app development is undoubtedly a positive sign of society's growing interest in health and wellness features can be engaging and motivate users to adopt healthier lifestyles, they often lack the depth required for serious health analytics. 

10
0 302
Article xuanyou du · Jan 30, 2024 1m read

I created this application considering how to convert images such as prescription forms into FHIR messages

It recognizes the text in the image through OCR technology and extracts it, which is then transformed into fhir messages through AI (LLA language model).

Finally, sending the message to the fhir server of IntereSystems can verify whether the message meets the fhir requirements. If approved, it can be viewed on the select page.

4
1 240
Article Oliver Wilms · Jan 31, 2024 2m read

An App that converts HL7 messages to JSON objects. About a year ago I started a GitHub repo for collecting stuff related to HL7. Recently my team added an HL7 interface to our Interoperability Production and we were asked to persist HL7 messages. We created a Kafka topic to receive HL7 messages. We use Kafka Bridges to send messages to Kafka topics. Kafka messages are sent to the Kafka Bridge in JSON format.

0
0 232
Article Alexey Nechaev · Nov 27, 2023 4m read

A few months ago, I faced a significant challenge: streamlining the handling of business logic in our application. My goal was to extract the business logic from the code and hand it over to analysts. Dealing with a multitude of rules could easily result in a code littered with countless "if" statements, especially if the coder lacked an understanding of cyclomatic complexity. Such code becomes a source of pain for those working with it—difficult to write, test, and develop.

1
0 350
Article Daniel Aguilar · Jan 17, 2024 7m read

        

Hello, community!

Ihave been tinkering around with Flutter lately and, as a result, came up with some apps that can use Firebase as a database. When I realized there was an available Python library, I felt the urge to create something for InterSystems IRIS that would communicate with the Firebase RealTime Database and perform CRUD operations. Later, I stumbled upon the following idea from Evgeny in the portal:

https://ideas.intersystems.com/ideas/DP-I-146 

That is when  I got down to work!


 

Are you curious to see my findings? Then buckle up because we’re about to take off!

0
1 415
Article Nikolay Solovyev · Jun 24, 2020 2m read

ZPM is a package manager designed for convenient deployment of applications and modules on the IRIS platform.

Module developers, in order for their module to be installed using ZPM, need to follow a series of simple steps.

  • Write module code
  • Create a module.xml file that contains the meta description of the module
  • Using the test registry, publish the module, verify that it is published
  • Install the module from the test registry
  • Publish the module. To publish in the public registry pm.community.intersystems.com, you need to publish the module in https://openexchange.intersystems.com, specifying the github url of your package and tick the “Publish in Package Manager” checkbox.

Creating a module.xml file manually can be tedious, so the generate command will now be created in zpm (starting with version 0.2.3).

The generate command is for creating module.xml for your project.

How to use:

Run zpm in terminal And then type generate

USER>zpm
zpm: USER>generate /temp/zzz

As an argument (in this case /temp/zzz) specify the path to the directory with your project. The module.xml file will be created in this directory.

Then answer questions:

zpm: USER>generate /temp/zzz

Enter module name: my-module
Enter module version: 1.0.0 => 1.0.1
Enter module description: module description
Enter module keywords: test,zpm,docker
Enter module source folder: src => 

Existing Web Applications:
    /csp/user
    /registry
    Enter a comma separated list of web applications or * for all: /csp/user
    Enter path to csp files for /csp/user:  web
Dependencies:
    Enter module:version or empty string to continue: sslclient:*  
    Enter module:version or empty string to continue: 
zpm: USER>
  • module source folder – relative path to your code (classes, routines), usually src. All classes and routines in this folder are loaded into current namespace.
  • If your module includes web applications, indicate which web applications from the current namespace should be added to module.xml
  • If your module contains dependencies, specify the module and its version. Use * for the latest version.

If you need to add author and license information to module.xml, use the -author (-a) modifier.

zpm: USER>generate -author /temp/zzz

The generate command also supports a different option: use the -template (-t) modifier. The module.xml is created with the fictional data, which you need to change manually.

zpm: USER>generate -template /temp/zzz

Watch this video demonstrating the usage of the generate command.

2
2 594
Question Rob Ellis · Dec 27, 2023

Is it possible to get a code quality stamp of approval on the Open Exchange with an application written in Javascript?
My Iris Whiz application is a browser extension written in Javascript and I wonder if having the code quality stamp missing from my application page will put people off from using it.
 

2
0 205
Article Robert Cemper · Dec 23, 2023 1m read

If one of your packages on OEX receives a review you get notified by OEX only of YOUR own package.   
The rating reflects the experience of the reviewer with the status found at the time of review.   
It is kind of a snapshot and might have changed meanwhile.   
Reviews by other members of the community are marked by * in the last column.

I also placed a bunch of Pull Requests on GitHub when I found a problem I could fix.    
Some were accepted and merged, and some were just ignored.     
So if you made a major change and expect a changed review just let me know.

0
0 157
Article Muhammad Waseem · Jun 5, 2023 8m read

Hi Community,

In this article, we will learn the below topics listed below:

  1. What is Docker?
  2. Some of the Docker benefits
  3. How does Docker work?
  4. Docker Image
  5. Docker Container
  6. Docker Image repository
  7. InterSystems's Docker image repository
  8. Docker Installation
  9. Docker Basic Commands
  10. Running IRIS community edition by using docker
  11. Docker Desktop GUI

So Let's start.


1. What is Docker?

10
8 1205
Article Lorenzo Scalese · Aug 16, 2023 11m read

Hi developers!

Today I would like to address a subject that has given me a hard time. I am sure this must have been the case for quite a number of you already (so-called “the bottleneck”). Since this is a broad topic, this article will only focus on identifying incoming HTTP requests that could be causing slowness issues. I will also provide you with a small tool I have developed to help identify them.

Our software is becoming more and more complex, processing a large number of requests from different sources, be it front-end or third-party back-end applications. To ensure optimal performance, it is essential to have a logging system capable of taking a few key measurements, such as the response time, the number of global references and the number of lines of code executed for each HTTP response. As part of my work, I get involved in the development of EMR software as well as incident analysis.  Since user load comes mostly from HTTP requests (REST API or CSP application), the need to have this type of measurement when generalized slowness issues occur has become obvious.

5
9 1348
Article Kurro Lopez · Dec 8, 2023 8m read

 

Artificial intelligence is not limited only to generating images through text with instructions or creating narratives with simple directions.

You can also make variations of a picture or include a special background to an already existing one.

Additionally, you can obtain the transcription of audio regardless of its language and the speed of the speaker.

So, let's analyze how the file management works.

2
1 518