On the previous post I mentioned some pros for decoupling programs. One way of doing this is by using messages and message queues. One program puts a message on a queue and another program receives that message and thus informing the program that it has to do something. There are many middleware software packages which support this.
One of those packages is Apache Artemis. It
supports one-to-one connections (queues) but also one-to-many (topics). The good thing about Apache
Artemis is that it is written in Java and thus can run on IBM i. Just download the archive to your
IBM i and extract the content of the archive (f. e. with unzip apache-artemis-2.31.0-bin.zip
or
jar -xf apache-artemis-2.31.0-bin.zip
).
I like to place the software I manually install on the IFS on IBM i in the /opt
folder. In
addition I like to create a symlink (ln -s ...
) so that it is easier to navigate the folders
(but that is just a personal habit ;-) ). So my folder structure looks like this:
1 | /opt/apache-artemis-2.27.1 |
Apache Artemis has a very good documentation and they explain everything in detail. Thus here an excerpt from it explaining how to install a new Apache Artemis broker instance.
The ActiveMQ Artemis broker follows a different paradigm where the project distribution serves as the broker “home” and one or more broker “instances” are created which reference the “home” for resources (e.g. jar files) which can be safely shared between broker instances. Therefore, an instance of the broker must be created before it can be run. This may seem like an overhead at first glance, but it becomes very practical when updating to a new Artemis version for example.
To create an Artemis broker instance navigate into the Artemis home folder and run:
./bin/artemis create /path/to/myBrokerInstance
on the command line.
Let us place the Artemis broker instances at /var/local/lib/artemis/<broker>
. The broker will manage
auction messages so my command line looks like
1 | ./bin/artemis create /var/local/lib/artemis/auction |
Now I could run this Artemis instance by executing /var/local/lib/artemis/auction/bin/artemis run
.
But first I need to configure some things. All configuration files of an Artemis instance can be
found at the instance location in the folder etc
.
1 | mihael@ibmi:~/auction-broker/etc> ls -1 |
Acceptors
Acceptors are the things that make the network connections to the clients and receive/distribute messages. Artemis supports many protocols. But the protocol we are interested in is STOMP. Artemis can be configured to have many acceptors listening on different ports but also having one acceptor accepting multiple protocols listening on one port.
Note: As I need some “special” connection attributes for the local STOMP acceptor I go for one acceptor for local STOMP connections and one acceptor for everything else.
Here is the acceptor configuration in broker.xml
.
1 | <acceptors> |
Note: The connection TTL attribute is set because the RPG STOMP service program does not support sending heart beats at the moment and Apache Artemis does not accept having no heart beat (and I wouldn’t either ;-) ) so we are setting a very high connection TTL so that it is guaranteed that some event will be sent in this time frame (f. e. a day or a week).
Topic
Queues and topics can be automatically created but I also can specify a persistent topic in the configuration.
1 | <addresses> |
Here we have a topic auction-events
and even if there is no subscriber to that topic all
messages will at least be distributed to the queue sink
which is really convenient in the
development phase. So even if nobody subscribed to auction-events
we will still see the incoming
messages in the queue sink
.
Logging
From the documentation:
Apache ActiveMQ Artemis uses the SLF4J logging facade for logging, with the broker assembly providing Log4J2 as the logging implementation. This is configurable via the
log4j2.properties
file found in the broker instance etc directory, which is configured by default to log to both the console and to a file.
I couldn’t have written it better.
For logging everything related to the STOMP acceptor just raise the log level of the
StompConnection
logger.
1 | logger.org.apache.activemq.artemis.core.protocol.stomp.StompConnection.level=DEBUG |
Note: You may need to also raise the level of the corresponding appender to DEBUG
.
1 | appender.console.filter.threshold.type = ThresholdFilter |
Web Console
Apache Artemis comes out-of-the-box with a web console based on Hawtio. The only problem with this is that it is only available on the local machine. But just for giving this a try it would be easier if we could access it from outside localhost. For this we need to change two configuration entries.
1 | <web ... > |
1 | <cors> |
Now we can access the Apache Artemis web console running on IBM i from our computer by accessing
the URL http://my_ibmi:40000
.
Large Text Messages
By default the web console will show you only the first 256 characters from a message. Depending
on the project messages might be much larger (several thousand characters). The max. number of
characters shown in the web console can be set in the broker.xml
file.
1 | <address-settings> |
Here the max. number of displayed characters is set to 50.000.
Starting Artemis
Now I can run this Artemis instance by executing /var/local/lib/artemis/auction/bin/artemis run
and have the log output in /var/local/lib/artemis/auction/log/artemis.log
.
But there are other ways to start Artemis, f. e. via Service Commander.
SocketException on Startup
Depending on the network configuration of the IBM i server we may encounter the following error on startup:
1 | java.net.SocketException: Protocol driver not attached |
This error may occur on any product/project which utilizes Jetty. But we can work around this
problem by specifying a Java system property. The startup script of Artemis supports adding Java
system properties without having to modify the script by using the environment variable
JAVA_ARGS_APPEND
.
1 | export JAVA_ARGS_APPEND="-Djava.net.preferIPv4Stack=true" |
Now we can start Artemis as usual.
Service Commander
Service Commander is a tool for managing services and applications on IBM i. But in contrast
to other tools Service Commander can manage services and applications of both worlds, PASE and
native IBM i, and has a very nice integration with the native CLI by utilizing STRTCPSVR
.
Service Commander stores the necessary data for each managed service in a stream file on the IFS,
see folder .sc/services
in the home folder. I placed the following configuration at
/home/myuser/.sc/services/artemis.yaml
:
1 | name: Artemis |
Now we have a whole bunch of possibilities for starting our Apache Artemis instance.
- From a SSH session:
nohup /var/local/lib/artemis/auction/bin/artemis run > /dev/null 2> /dev/null &
- From a SSH session:
sc start artemis
- From 5250 session:
STRTCPSVR SERVICE(*SC) INSTANCE('artemis')
And now we can start it equally well from the PASE and the 5250 environment. And also no problems with having it autostarted after an IPL. Just add it to the autostart group in the Service Commander job definition YAML file.
Kudos to Jesse Gorzinski for this great project!
Happy integrating!
Mihael
PS: I mentioned “… written in Java … thus can run on IBM i.”. That is not totally correct. Because it is written in Java it can run in the Java VM on IBM i. But that does not guarantee that it will run correctly on IBM i. Many Java projects are done in mind with x86 as their target platform (or even only Windows) and thus it does not always work on IBM i. But so far I had luck with all of the Java projects I tried on IBM i. :-)