0 Followers · 185 Posts

Java is a general-purpose computer-programming language that is concurrent, class-based, object-oriented, and specifically designed to have as few implementation dependencies as possible.

Article Davi Massaru Teixeira Muta · Oct 11, 2025 9m read

Technical Documentation — Quarkus IRIS Monitor System

1. Purpose and Scope

This module enables integration between Quarkus-based Java applications and InterSystems IRIS’s native performance monitoring capabilities.
It allows a developer to annotate methods with @PerfmonReport, which triggers IRIS’s ^PERFMON routines automatically around method execution, generating performance reports without manual intervention.


2. System Components

2.1 Annotation: @PerfmonReport

  • Defined as a CDI InterceptorBinding.
  • Can be applied to methods or classes.
  • Directs the framework to wrap method execution with IRIS monitoring logic.

2.2 Interceptor: PerfmonReportInterceptor

  • Intercepts calls to annotated methods.

  • Execution flow:

    1. Log start event (LOG.infof("INIT: …"))
    2. Call monitorSystem.startPerfmon()
    3. Proceed with context.proceed()
    4. In a finally block:
      • Call monitorSystem.generateReportPerfmon(...)
      • Call monitorSystem.stopPerfmon()
      • Log end event with execution time
  • Ensures that monitoring is always ended, even if an exception is thrown.

2.3 DAO Bean: MonitorSystem

  • CDI bean annotated with @ApplicationScoped.

  • Holds a single instance of IRIS initialized at startup.

  • Configuration injected via @ConfigProperty (JDBC URL, user, password).

  • Uses DriverManager.getConnection(...) to obtain a raw IRISConnection.

  • Contains methods:

    • startPerfmon()
    • generateReportPerfmon(String reportName)
    • stopPerfmon()
  • Each calls the appropriate ObjectScript methods in iris.src.dc.AdapterPerfmonProc via iris.classMethodVoid(...).

2.4 ObjectScript Adapter: iris.src.dc.AdapterPerfmonProc

  • Defines the routines that encapsulate ^PERFMON logic:

      Class iris.src.dc.AdapterPerfmonProc Extends %RegisteredObject
      {
          ClassMethod start() As %Status
          {
              Set namespace = $NAMESPACE
              zn "%SYS"
              set status = $$Stop^PERFMON()
              set status = $$Start^PERFMON()
              zn namespace
              return status
          }
    
          ClassMethod generateReport(nameReport As %String = "report.txt") As %Status
          {
              Set namespace = $NAMESPACE
              zn "%SYS"
              Set tempDirectory = ##class(%SYS.System).TempDirectory()
              set status = $$Report^PERFMON("R","R","P", tempDirectory_"/"_nameReport)
              zn namespace
    
              return status
          }
    
          ClassMethod stop() As %Status
          {
              Set namespace = $NAMESPACE
              zn "%SYS"
              Set status = $$Stop^PERFMON()
              zn namespace
    
              return status
          }
      }
    
  • Operates in namespace %SYS to access ^PERFMON routines, then returns to the original namespace.


3. Execution Flow

  1. A request enters the Quarkus application.

  2. The CDI interceptor detects the @PerfmonReport annotation and intercepts the method call.

  3. monitorSystem.startPerfmon() is invoked, triggering IRIS ^PERFMON monitoring.

  4. The business method executes normally (data access, transformations, logic, etc.).

  5. After the method returns or throws an exception, the interceptor ensures:

    • monitorSystem.generateReportPerfmon(...) is called to create a .txt performance report.
    • monitorSystem.stopPerfmon() is executed to stop the monitoring session.
    • The total Java-side execution time is logged using Logger.infof(...).
  6. The generated report file is stored in the IRIS temporary directory, typically: /usr/irissys/mgr/Temp/

    • The file name follows the pattern: <ClassName><MethodName><timestamp>.txt

4. Technical Challenges and Solutions

ChallengeSolution
ClassCastException when using pooled JDBC connectionsUse DriverManager.getConnection(...) to obtain a native IRISConnection instead of the pooled ConnectionWrapper.
Overhead from repeatedly opening connectionsMaintain a single IRIS instance within an @ApplicationScoped bean, initialized via @PostConstruct.
Ensuring ^PERFMON is always stopped even on exceptionsUse try-finally in the interceptor to call stopPerfmon() and generateReportPerfmon().
Configuration portabilityInject connection settings (jdbc.url, username, password) using @ConfigProperty and application.properties.
Managing concurrent monitor sessionsAvoid annotating highly concurrent endpoints. Future versions may implement session-level isolation.

5. Use Cases and Benefits

  • Enables real-time visibility into IRIS runtime activity from Java code.
  • Simplifies performance analysis and query optimization for developers.
  • Useful for benchmarking, profiling, and system regression testing.
  • Can serve as a lightweight performance audit trail for critical operations.

6. Practical Example of Use

The complete source code and deployment setup are available at:


6.1 Overview

The application runs a Quarkus server connected to an InterSystems IRIS instance configured with the FHIRSERVER namespace.
The ORM layer is implemented using Hibernate ORM with PanacheRepository, allowing direct mapping between Java entities and IRIS database classes.

When the application starts (via docker-compose up), it brings up:

  • The IRIS container, hosting the FHIR data model and ObjectScript routines (including AdapterPerfmonProc);
  • The Quarkus container, exposing REST endpoints and connecting to IRIS via the native JDBC driver.

6.2 REST Endpoint

A REST resource exposes a simple endpoint to retrieve patient information:

@Path("/patient")
public class PatientResource {

    @Inject
    PatientService patientService;

    @GET
    @Path("/info")
    @Produces(MediaType.APPLICATION_JSON)
    public PatientInfoDTO searchPatientInfo(@QueryParam("key") String key) {
        return patientService.patientGetInfo(key);
    }
}

This endpoint accepts a query parameter (key) that identifies the patient resource within the FHIR data repository.


### 6.3 Service Layer with @PerfmonReport

The PatientService class contains the business logic to retrieve and compose patient information. It is annotated with @PerfmonReport, which means each request to /patient/info triggers IRIS performance monitoring:

@ApplicationScoped
public class PatientService {

    @Inject
    PatientRepository patientRepository;

    @PerfmonReport
    public PatientInfoDTO patientGetInfo(String patientKey) {

        Optional<Patient> patientOpt = patientRepository.find("key", patientKey).firstResultOptional();
        Patient patient = patientOpt.orElseThrow(() -> new IllegalArgumentException("Patient not found"));

        PatientInfoDTO dto = new PatientInfoDTO();
        dto.setKey(patient.key);
        dto.setName(patient.name);
        dto.setAddress(patient.address);
        dto.setBirthDate(patient.birthDate != null ? patient.birthDate.toString() : null);
        dto.setGender(patient.gender);
        dto.setMedications(patientRepository.findMedicationTextByPatient(patientKey));
        dto.setConditions(patientRepository.findConditionsByPatient(patientKey));
        dto.setAllergies(patientRepository.findAllergyByPatient(patientKey));

        return dto;
    }
}

6.4 Execution Flow

A request is made to: GET /patient/info?key=Patient/4

Quarkus routes the request to PatientResource.searchPatientInfo().

The CDI interceptor detects the @PerfmonReport annotation in PatientService.patientGetInfo().

Before executing the service logic:

  • The interceptor invokes MonitorSystem.startPerfmon(), which calls the IRIS class iris.src.dc.AdapterPerfmonProc.start().

  • The method executes business logic, querying patient data using Hibernate PanacheRepository mappings.

After the method completes:

  • MonitorSystem.generateReportPerfmon() is called to create a performance report.

  • MonitorSystem.stopPerfmon() stops the IRIS performance monitor.

A .txt report is generated under: usr/irissys/mgr/Temp/

Example filename: PatientService_patientGetInfo_20251005_161906.txt

6.5 Result

The generated report contains detailed IRIS runtime statistics, for example:

                         Routine Activity by Routine

Started: 10/11/2025 05:07:30PM                    Collected: 10/11/2025 05:07:31PM

Routine Name                        RtnLines  % Lines   RtnLoads  RtnFetch  Line/Load Directory
----------------------------------- --------- --------- --------- --------- --------- ---------
Other                                     0.0       0.0       0.0       0.0         0
PERFMON                                  44.0       0.0       0.0       0.0         0 /usr/irissys/mgr/
%occLibrary                         3415047.0      34.1   48278.0       0.0      70.7 /usr/irissys/mgr/irislib/
iris.src.dc.AdapterPerfmonProc.1          7.0       0.0       2.0       0.0       3.5 /usr/irissys/mgr/FHIRSERVER/
%occName                            5079994.0      50.7       0.0       0.0         0 /usr/irissys/mgr/irislib/
%apiDDL2                            1078497.0      10.8   63358.0       0.0      17.0 /usr/irissys/mgr/irislib/
%SQL.FeatureGetter.1                 446710.0       4.5   66939.0       0.0       6.7 /usr/irissys/mgr/irislib/
%SYS.WorkQueueMgr                       365.0       0.0       1.0       0.0     365.0 /usr/irissys/mgr/
%CSP.Daemon.1                            16.0       0.0       1.0       0.0      16.0 /usr/irissys/mgr/irislib/
%SYS.TokenAuth.1                         14.0       0.0       5.0       0.0       2.8 /usr/irissys/mgr/
%Library.PosixTime.1                      2.0       0.0       0.0       0.0         0 /usr/irissys/mgr/irislib/
%SYS.sqlcq.uEXTg3QR7a7I7Osf9e8Bz...      52.0       0.0       1.0       0.0      52.0 /usr/irissys/mgr/
%SYS.SQLSRV                              16.0       0.0       0.0       0.0         0 /usr/irissys/mgr/
%apiOBJ                                 756.0       0.0       0.0       0.0         0 /usr/irissys/mgr/irislib/
FT.Collector.1                            0.0       0.0       0.0       0.0         0 /usr/irissys/mgr/
SYS.Monitor.FeatureTrackerSensor.1        0.0       0.0       0.0       0.0         0 /usr/irissys/mgr/
%SYS.Monitor.Control.1                    0.0       0.0       0.0       0.0         0 /usr/irissys/mgr/
%SYS.DBSRV.1                            252.0       0.0       4.0       0.0      63.0 /usr/irissys/mgr/
%sqlcq.FHIRSERVER.cls12.1                19.0       0.0       0.0       0.0         0 /usr/irissys/mgr/irislocaldata/
%sqlcq.FHIRSERVER.cls13.1                74.0       0.0       0.0       0.0         0 /usr/irissys/mgr/irislocaldata/
%sqlcq.FHIRSERVER.cls14.1                74.0       0.0       0.0       0.0         0 /usr/irissys/mgr/irislocaldata/
%sqlcq.FHIRSERVER.cls15.1                52.0       0.0       0.0       0.0         0 /usr/irissys/mgr/irislocaldata/
%SYS.System.1                             1.0       0.0       0.0       0.0         0 /usr/irissys/mgr/

This data provides precise insight into what routines were executed internally by IRIS during that REST call — including SQL compilation, execution, and FHIR data access.

Insight: The %sqlcq.FHIRSERVER.* routines capture all SQL cache queries executed by Quarkus within the method. Monitoring these routines allows developers to analyze query execution, understand code behavior, and identify potential performance bottlenecks. This makes them a powerful tool for development and debugging of FHIR-related operations.

image

6.6 Summary

This example demonstrates how a standard Quarkus service can transparently leverage IRIS native monitoring tools using the @PerfmonReport annotation. It combines:

  • CDI interceptors (Quarkus)

  • Hibernate PanacheRepositories (ORM)

  • IRIS native ObjectScript routines (^PERFMON)

The result is a fully automated and reproducible performance profiling mechanism that can be applied to any service method in the application.

1
0 44
Question Dmitrii Baranov · Oct 12, 2025

I need to build an integration solution that reads messages from a Kafka topic. The topic has 3 partitions and contains several million messages.

For certain reasons, I can only use the standard EnsLib.Kafka.Service class and cannot use either KafkaClient or Python.

To measure performance and collect statistics I created a simple key + timestamp table with no indexes (so it is unlikely to be a bottleneck). Next, I started an instance of EnsLib.Kafka.Service. In the OnProcessInput method, I receive a message, extract the key from it, get the current time, and write the row to the table.

The statistics shows that as messages are read, performance degrades literally by the minute. In the first minute, the business service is capable of processing up to 25000 messages per minute, then performance gradually decreases, and after 10 minutes performance drops to 2000 messages per minute.

Pool Size = 1, Call Interval = 5 First run 2025-10-11 19:01:00 25880 2025-10-11 19:02:00 12468 2025-10-11 19:03:00 8013 2025-10-11 19:04:00 6626 2025-10-11 19:05:00 5023 2025-10-11 19:06:00 4947 2025-10-11 19:07:00 3912 2025-10-11 19:08:00 3539 2025-10-11 19:09:00 3529 2025-10-11 19:10:00 3169 2025-10-11 19:11:00 2955 2025-10-11 19:12:00 2914 2025-10-11 19:13:00 2771 2025-10-11 19:14:00 2624 2025-10-11 19:15:00 2446 2025-10-11 19:16:00 2754 2025-10-11 19:17:00 2545 2025-10-11 19:18:00 2350 2025-10-11 19:19:00 2314 2025-10-11 19:20:00 2274 Pool Size = 1, Call Interval = 5 Second run 2025-10-11 19:22:00 22892 2025-10-11 19:23:00 15239 2025-10-11 19:24:00 11489 2025-10-11 19:25:00 8267 2025-10-11 19:26:00 6351 2025-10-11 19:27:00 5268 2025-10-11 19:28:00 4779 2025-10-11 19:29:00 4502 2025-10-11 19:30:00 3854 2025-10-11 19:31:00 4048 2025-10-11 19:32:00 3675 2025-10-11 19:33:00 3434 2025-10-11 19:34:00 2981 2025-10-11 19:35:00 3101 2025-10-11 19:36:00 2869 2025-10-11 19:37:00 2343

I tried to play with other configuration properties (CallInterval, ReceiveSettings = { "pollInterval": 1000 }) but that didn't help and even caused Java OutOfMemory error.

How can this problem be solved?

5
0 42
Article André Dienes Friedrich · Sep 26, 2025 3m read

 

Building a Sensor Data Demo with Spring Boot and InterSystems IRIS

In the era of IoT and connected devices, sensor data is everywhere—tracking temperature in logistics, monitoring equipment performance, or recording environmental conditions. But capturing, storing, and analyzing this data in real time requires more than just hardware sensors.

0
0 46
Question Scott Roth · Sep 8, 2025

We currently have Business Operation that we built to use the EnsLib.SQL.OutboundAdapter so we can make Microsoft SQL Server Stored Procedure calls. The BO is attached to a Java Gateway Service.

Some of our MS SQL Databases have moved from being OnPrem to Azure Cloud. We have started seeing where we are receiving errors on the BO saying that we cannot connect to the Azure Database, but we never receive a Disconnect from the Azure Database.

2
0 37
Question Kim Jiyong · May 2, 2025

Hello, we are currently using the Cache Database released in January 2018.

There are no specific classes or SQL mappings in the namespaces where data is stored.

Only a few routines(.mac) and stored data are in the global area.

In this case, when accessing the Cache DB through Java, is it essential to write SQL mappings or wrapper classes? The reason I ask is that our team doesn't have advanced developers who specialize in Cache.

Alternatively, is it possible to directly call pre-existing routines from Java?

I apologize for the translation;

2
0 73
Question Andrew Sklyarov · Mar 26, 2025

Here is my code:

Method getStocks(pRequest As Stock.Message.Req, Output pResponse As Ens.StreamContainer) As %Status
{
     s tSC = pRequest.NewResponse(.pResponse)
     q:$$$ISERR(tSC) tSC

     #dim pRS As EnsLib.SQL.GatewayResultSet

     s tSC = ..Adapter.ExecuteQuery(.pRS, "select jsonb_agg(s) #>> '{}' FROM prod.stocks s where s.""Warehouse"" = ?", pRequest.Warehouse)
     q:$$$ISERR(tSC) tSC

     s pResponse = ##class(Ens.StreamContainer).%New()
     s pResponse.Stream = ##class(%GlobalCharacterStream).%New()

3
0 197
Question Igor Pak · Mar 7, 2025

Hello, dear colleagues.

I need to connect to a remote JavaGateway from an Ensemble service.

I am trying to use the EnsLib.JavaGateway.Service with a remote host where the JVM is running.

I can successfully ping the remote Java Gateway from EnsLib.JavaGateway.Service, and Ensemble reports that the service status is OK.

There are no network issues, and all necessary ports are accessible.

My requests work without any problems when I specify localhost in EnsLib.JavaGateway.Service. However, when I specify a remote JVM, I get the following error:

1
0 115
Article Scott Roth · Jan 24, 2025 3m read

Not sure there are many that connect to MS SQL to execute queries, stored procedures, etc, but our Healthsystem has many different MS SQL based databases we use within the Interoperability environment for various reasons.

With the push to moving from on-prem to the Cloud we ran into some difficulties with our SQL Gateway connections and knowing how to config them to use Microsoft Entra for Active Directory Authentication.

0
1 475
Question Peter O'Halloran · Jan 14, 2025

As part of a migration project from a bunch of java classes to IRIS, we need to maintain a few jar files due to some external dependencies.

The problem I am seeing is that I cannot pass a byte array ( byte[] ) from ObjectScript to the Java Class. I have tried a number of different ways

I have reproduced in a java class and Objectscript class:
Java Class:

2
0 139
Question Shashvati Dash · Dec 10, 2024

connection = ##class(%Net.Remote.Java.JavaGateway).%New()
sc = connection.%Connect("127.0.0.1",53274)
classpath="C:\Users\ME9Y1PM\Downloads\wrapper_jar\wrapper-drools-1.0.0-20241127.071529-1.jar"
if (sc=$$$OK) {
SCJavaDroolsObj.connection=connection
sc = SCJavaDroolsObj.connection.%Import("com.lca.smc.drools.DroolsRules")
SCJavaDroolsObj.drools = ##class(com.lca.smc.drools.DroolsRules).%New()
SCJavaDroolsObj.drools.applyRules(patientjson)

0
0 94
Article Iryna Mykhailova · Nov 10, 2024 2m read

If you like Java and have a thriving Java ecosystem at work into which you need to incorporate IRIS, it's not a problem. Java External Language Gateway will do it seamlessly, almost. This gateway serves as a bridge between Java and Object Script in IRIS. You can create objects of Java classes in IRIS and call their methods. You just need a jar file to do this.

Connection diagram: proxy object <-> Gateway object <-> TCP/IP <-> External server <-> target object

0
4 335
Article Andrii Mishchenko · Sep 22, 2024 5m read

Introduction

Managing databases and performing CRUD operations are fundamental tasks for developers building data-driven applications. While many database management systems (DBMS) exist, they can be complex and cumbersome to interact with, especially when it comes to creating databases and tables, handling constraints, and performing real-time data operations through an API.

4
0 355
Article Andrii Mishchenko · Sep 27, 2024 4m read

In this article, we’ll dive into the inner workings of the database management tool, exploring the architecture and technologies that power it. Understanding how the application functions behind the scenes will give you insight into its design, how it manages databases, tables, and how the API interacts with data.

We will discuss the core technologies used, including InterSystems IRIS as the primary database and Redis for caching. Additionally, we’ll break down the structure of the tables used and explain how the system handles data creation, retrieval, and manipulation through the REST API.

0
1 207
Article Keren Skubach · Aug 19, 2024 4m read

Accessing an Azure cloud storage to upload/download blobs is quite easy using the designated %Net.Cloud.Storage.Client class API methods, or using the EnsLib.CloudStorage.* inbound/outbound adaptors.

Note that you'll need to have the %JavaServer External Language Server up and running to use the cloud storage API or adaptors, since they both use the PEX framework using the Java Server.

Here is a quick summary:

Azure Blob Storage is accessed using a connection string that looks similar to this:

0
3 520
Question Alexander Gollings · Jul 31, 2024

Hello,

I'm brand new to InterSystems and their products.

Doing some research for my job, I've found myself going through the learning paths Connection Java Application to InterSystems(https://learning.intersystems.com/course/view.php?id=879).

Working through the proposed demos (https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cl… and https://github.com/intersystems/quickstarts-java) I cannot get the methods deleteExtent, importSchemaFull and getEvent to work on the EventPersistor.

I keep getting this error

I've found that the tag <PROTECT> refers to this :

2
0 116
Question Ugljesa Pupavac · May 14, 2024

Hi,I have a spring-boot Java application which has Quartz Scheduler (spring-boot-quartz-starter) dependency, and uses IRIS DB.There is a problem with making Quartz Scheduler work with IRIS since there is a blob field expected in two tables, but IRIS is using longvarbinary type.Can you provide me with clues on how to resolve this?I am using org.quartz.impl.jdbcjobstore.StdJDBCDelegate driverDelegateClass.This is the error:MisfireHandler: Error handling misfires: Couldn't retrieve trigger: invalid stream header: 41434544org.quartz.JobPersistenceException: Couldn't retrieve trigger: invalid

0
0 135
Question isabella Barnes · Apr 15, 2024

@Vicky Li 
@Thanongsak Chamung 
@Warlin Garcia 
@Eduard Lebedyuk 
@Enrico Parisi 
@Luis Angel Pérez Ramos 
We are getting this error. All the drivers, URL and credential are tested and existed. it works fine sometime but also getting this error more often. Please advise the root cause and its respective solution. The business service that is using out of the box Java service (classname: EnsLib.JavaGateway.Service adapter classname: EnsLib.JavaGateway.ServiceAdapter) is throwing this error.
The configured "SOMEDSN" has passed the JDBC Connection test successfully with the external database (ORACLE)
Type: Error

3
0 324
Question Parameshwaran Muthaiyan · Apr 4, 2024

For example, I have two timestamp values ('2024-04-01 10:00:00', '2024-04-01 11:30:30'). I would like to find the difference between these two timestamps, and I need the result in hours:minutes:seconds (hh:mm:ss) format.

Expected Output: 01:30:30


Note: I need an SQL query command. I should not use ClassMethod, Function, or Stored Procedure.


Could anyone please provide me with an SQL query for my question?

4
0 335