Java / .Net Gateways in InterSystems IRIS Integration Products

Gateways in InterSystems IRIS are the communication mechanism between the InterSystems IRIS core and the Java / .Net application code. With the help of gateways, you can work with both Java / .NET objects from ObjectScript and ObjectScript objects and globals from Java / .NET. Gateways can be run anywhere – locally, on a remote server, in docker.

In this article, I’ll show you how you can easily develop and containerize integration products with .Net / Java code. And to interact with code in Java / .Net languages ​​we will use PEX, which provides an opportunity to implement any element of integration products in Java / .Net languages.

For our example, we will develop an integration with Apache Kafka

Architecture

Apache Kafka is a popular message broker. Kafka has topic (topic) messages to which publishers (publisher) write messages and eat subscribers (consumer) to the topics that read these posts.

First, we will write a Java business operation that will post messages to Apache Kafka. Then we will add a business service in C # that will read, save and transmit messages for further processing in InterSystems IRIS.

Our solution will work in docker and looks like this:

Java Gateway

First of all, we will develop a Business Operation in Java for sending messages to Apache Kafka. The code can be written in any Java IDE and look like this:

  • To develop a new PEX business operation, you need to implement an abstract class com.intersystems.enslib.pex.BusinessOperation

  • The public properties of the class are the settings of our business host

  • Method OnInit used to establish a connection with Apache Kafka and get a pointer to InterSystems IRIS

  • OnTearDown used to disconnect from Apache Kafka (when the process stops).

  • OnMessage receives message dc.KafkaRequest and sends it to Apache Kafka.

Now let’s pack our business operation into a Docker container.

Here is our docker file:

FROM openjdk:8 AS builder

ARG APP_HOME=/tmp/app

COPY src $APP_HOME/src

COPY --from=intersystemscommunity/jgw:latest /jgw/*.jar $APP_HOME/jgw/

WORKDIR $APP_HOME/jar/
ADD https://repo1.maven.org/maven2/org/apache/kafka/kafka-clients/2.5.0/kafka-clients-2.5.0.jar .
ADD https://repo1.maven.org/maven2/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar .
ADD https://repo1.maven.org/maven2/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar .
ADD https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar .

WORKDIR $APP_HOME/src

RUN javac -classpath $APP_HOME/jar/*:$APP_HOME/jgw/* dc/rmq/KafkaOperation.java && 
    jar -cvf $APP_HOME/jar/KafkaOperation.jar dc/rmq/KafkaOperation.class

FROM intersystemscommunity/jgw:latest

COPY --from=builder /tmp/app/jar/*.jar $GWDIR/

Let’s see what’s going on here (I’m assuming you’re familiar with multistage docker builds):

FROM openjdk:8 AS builder

JDK8 is the base image in which we will compile our application.

ARG APP_HOME=/tmp/app
COPY src $APP_HOME/src

Copy the source code from the folder /src at /tmp/app

COPY --from=intersystemscommunity/jgw:latest /jgw/*.jar $APP_HOME/jgw/

Copy the Java Gateway libraries to the folder /tmp/app/jgw

WORKDIR $APP_HOME/jar/
ADD https://repo1.maven.org/maven2/org/apache/kafka/kafka-clients/2.5.0/kafka-clients-2.5.0.jar .
ADD https://repo1.maven.org/maven2/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar .
ADD https://repo1.maven.org/maven2/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar .
ADD https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar .

WORKDIR $APP_HOME/src

RUN javac -classpath $APP_HOME/jar/*:$APP_HOME/jgw/* dc/rmq/KafkaOperation.java && 
    jar -cvf $APP_HOME/jar/KafkaOperation.jar dc/rmq/KafkaOperation.class

All dependencies are downloaded – we call javac/jar to compile the jar file. For real projects it is recommended to use a full maven or gradle build system.

FROM intersystemscommunity/jgw:latest

COPY --from=builder /tmp/app/jar/*.jar $GWDIR/

Finally, the jar files are copied into the base Java gateway image, which contains all the required dependencies and enables the Java gateway to run.

.Net Gateway

Next, we will develop a .Net service that will receive messages from Apache Kafka. The code can be written in any .Net IDE and look like this

Features:

  • To develop a new PEX business service, you need to implement an abstract class InterSystems.EnsLib.PEX.BusinessService

  • The public properties of the class are the settings of our business host

  • Method OnInit used to establish a connection to Apache Kafka, subscribe to Apache Kafka topics, and get a pointer to InterSystems IRIS

  • OnTearDown used to disconnect from Apache Kafka (when the process stops)

  • OnMessage receives messages from Apache Kafka and sends message to class Ens.StringContainer to target business hosts of products

Now let’s pack our business operation into a Docker container.

Here is our docker file:

FROM mcr.microsoft.com/dotnet/core/sdk:2.1 AS build

ENV ISC_PACKAGE_INSTALLDIR /usr/irissys
ENV GWLIBDIR lib
ENV ISC_LIBDIR ${ISC_PACKAGE_INSTALLDIR}/dev/dotnet/bin/Core21

WORKDIR /source
COPY --from=store/intersystems/iris-community:2020.2.0.211.0 $ISC_LIBDIR/*.nupkg $GWLIBDIR/

# copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# copy and publish app and libraries
COPY . .
RUN dotnet publish -c release -o /app

# final stage/image
FROM mcr.microsoft.com/dotnet/core/runtime:2.1
WORKDIR /app
COPY --from=build /app ./

# Configs to start the Gateway Server
RUN cp KafkaConsumer.runtimeconfig.json IRISGatewayCore21.runtimeconfig.json && 
    cp KafkaConsumer.deps.json IRISGatewayCore21.deps.json

ENV PORT 55556

CMD dotnet IRISGatewayCore21.dll $PORT 0.0.0.0

Let’s see what’s going on here:

FROM mcr.microsoft.com/dotnet/core/sdk:2.1 AS build

We use the .Net Core 2.1 SDK image to build our application.

ENV ISC_PACKAGE_INSTALLDIR /usr/irissys
ENV GWLIBDIR lib
ENV ISC_LIBDIR ${ISC_PACKAGE_INSTALLDIR}/dev/dotnet/bin/Core21

WORKDIR /source
COPY --from=store/intersystems/iris-community:2020.2.0.211.0 $ISC_LIBDIR/*.nupkg $GWLIBDIR/

We copy the .Net Gateway libraries from the official InterSystems IRIS image:

# copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# copy and publish app and libraries
COPY . .
RUN dotnet publish -c release -o /app

We compile our business operation.

FROM mcr.microsoft.com/dotnet/core/runtime:2.1
WORKDIR /app
COPY --from=build /app ./

Copy the libraries into the final container.

RUN cp KafkaConsumer.runtimeconfig.json IRISGatewayCore21.runtimeconfig.json && 
    cp KafkaConsumer.deps.json IRISGatewayCore21.deps.json

Net gateway currently has to load all dependencies at startup, so we inform it about all possible dependencies.

ENV PORT 55556

CMD dotnet IRISGatewayCore21.dll $PORT 0.0.0.0

We start the gateway on the port 55556, we listen to all network interfaces.

Done!

Here is the complete configuration docker-composeto run the whole demo (including the UI for Apache Kafka, to view messages).

Demo launch

To run the demo locally:

Install:

Run:

git clone https://github.com/intersystems-community/pex-demo.git
cd pex-demo
docker-compose pull
docker-compose up -d

conclusions

  • InterSystems IRIS integration products now have the ability to create any product elements in Java / .Net languages

  • Java / .Net code can be called from InterSystems ObjectScript and vice versa, InterSystems ObjectScript code from Java / .Net

  • Proxy class generation is no longer required

  • Both classic delivery of the solution and delivery in Docker are possible

Links

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *