Requirements

SwiftMQ requires Java 11 or later.

The Streams Swiftlet requires a JavaScript scripting engine which is part of the JDK up to Java 14 (Nashorn scripting engine). From Java 15 onwards the Nashorn scripting engine has been removed from the JDK. SwiftMQ detects that during startup and disables the Streams Swiftlet automatically. So, all functionality provided from this Swiftlet, like the message scheduler, will be unavailable.

To use Java 15 or later with Streams Swiftlet, you need to run SwiftMQ with GraalVM CE which is a next-generation polyglot JVM, based on the standard OpenJDK and provided from Oracle. SwiftMQ has been highly optimized for GraalVM and we recommend using it instead of the standard OpenJDK.

GraalVM CE is free and can be obtained from https://graalvm.org.

Installation from an Archive

Distribution Content

After you have unpacked the archive, you will find the following directory structure below the distribution's top-level directory:

Directory

Content

certs

Self signed TLS certificates and server/client key stores.

data

All dynamic data of the router like configuration, logs, persistent store

jars

jar files

kernel

jar files and config meta data of all Kernel Swiftlets

optional-swiftlets/extension

Directory for Extension Swiftlets.

samples

SwiftMQ samples

scripts

Shell scripts to start the router and cli

streams

SwiftMQ system streams

Starting the Router

Go to the scripts directory and start the router as follows:

    ./router [<preconfig>]
CODE

If you are starting it under Windows and use preconfig files, please set it in quotes!

Running SwiftMQ as Docker Container

Preparation

A SwiftMQ Router running in a Docker container has a standard configuration and is stateless. That is, changes in the configuration and persistent data are lost when the container stops. To avoid this, the following preparations need to be done per container.

Recommended Directory Structure per Container on the local Machine

Create the following directory structure somewhere on the machine on which the container is started:

  <routername>/
            preconfig/
            data/
CODE

Preconfig

Preconfig is a way to modify an existing router configuration before the router is started. A preconfig is stored in an XML file and contains modifications so that the resulting router configuration exactly matches your router node's configuration.

In the case of a Docker container, the routerconfig.xml on the first startup of the container is always the standard routerconfig.xml.

Have a look here at how to create preconfig files.

If you want to connect via JNDI/JMS, the router returns a connectaddress in the connection factory that points to the internal container hostname, so you can't connect. In your preconfig you should add this JMS listener:

  <listener name="internal" port="5001" connectaddress="localhost"/>
XML

If you want to connect with NAT translation from outside a firewall to your Docker host you need to add this JMS listener too:

  <listener name="external" port="5002" connectaddress="publichost"/>
XML

Starting the Docker Container

Getting the latest SwiftMQ CE Docker image takes place with:

docker pull iitsoftware/swiftmq-ce:latest
CODE

JMS required Hosts

If you have added the external JMS listener to the preconfig as described before, you need to specify the IP addresses of the host.

Put

--add-host publichost:<public-ip>
CODE

to the command line of the Docker container.

Mounts

To ensure that dynamic data such as configuration, logs, persistent data etc survive a container stop, you need to map internal container directory data/ to a directory on your local machine. This is called mount and is done via the -v option at the command line:

-v <local-directory>:<container-directory>
CODE

The internal data directory is under /swiftmq/data. To map it to a local directory, use (example):

-v /opt/edge1/data:/swiftmq/data
CODE

Setting Environment Variables

If you want to apply preconfig files to the container, specify this environment variable:

-e SWIFTMQ_PRECONFIG="/swiftmq/preconfig/preconfig.xml,/swiftmq/preconfig/queues.xml,/swiftmq/preconfig/topics.xml"
CODE

The files are applied in the order of definition. Note: The preconfig directory is the directory inside the container (/swiftmq/preconfig).

To overwrite the default JVM parameters, set environment variable SWIFTMQ_JVMPARAM accordingly:

-e SWIFTMQ_JVMPARAM="-Xmx4G"
CODE

The default setting is -Xmx2G. Since SwiftMQ runs on GraalVM inside the Docker container, you must use the settings for GraalVM.

Port Mapping

The various ports specified in the router's configuration file needs to be mapped to a port at the local machine by using the -p option:

-p <local-port>:<container-port>
CODE

For example, to map the ports 4001 and 4100 of the above preconfig we use these options:

-p 4001:4001 -p 4100:4100
CODE

Start

To start a docker container as a daemon with SwiftMQ CE use this command:

docker run -d <mount-options> <port-mapping-options> <environment-var-options> iitsoftware/swiftmq-ce:<release>
CODE

Stop

Stopping a Docker container must always be done with

docker stop <docker-pid>
CODE

to ensure a graceful shutdown of the router.

Do not use

docker kill <docker-pid>
CODE

as it will hard kill the router which might lead to inconsistencies of the persistent store.

Using Docker Compose

Docker Compose is a docker tool that composes and manages multiple docker container services. It can also be used to manage a single container service. It is very convenient to use.

A yaml file called docker-compose.yml must be used to specify the service properties:

version: '3'
services:
  swiftmq:
    image: "iitsoftware/swiftmq-ce:latest"
    ports:
      - "4001:4001" # JMS
      - "5672:5672" # AMQP
      - "1883:1883" # MQTT
      - "4100:4100" # Routing Listener
    environment:
      - SWIFTMQ_PRECONFIG=/swiftmq/preconfig/mynode.xml
    volumes:
        - ${PWD}/router/preconfig:/swiftmq/preconfig
        - ${PWD}/router/data:/swiftmq/data
    extra_hosts:
        - "dockerhost:${myIP}"
YAML

Then create a small shell script that gathers the dockerhost's IP addess:

#!/bin/bash
  
export myIP=`ifconfig $(netstat -rn | grep -E "^default|^0.0.0.0" | head -1 | awk '{print $NF}') | grep 'inet ' | awk '{print $2}' | grep -Eo '([0-9]*\.){3}[0-9]*'`
export PWD=`pwd`

case "$1" in
  start)
        docker-compose pull swiftmq
        docker-compose up -d
    ;;
  stop)
        docker-compose down
    ;;
  status)
        docker ps
    ;;
  *)
    echo "Usage: $N {start|stop|status}"
    exit 1
    ;;
esac
exit 0
BASH

Running a SwiftMQ Router Network on the Same Host

A SwiftMQ Router Network consists of single SwiftMQ Routers that connect and build a network. Some preparations are necessary if these routers run in Docker containers on the same host.

Determine the local IP Address of the Docker Host

The docker host is the machine where all Docker containers are started. To determine the IP address of the host, use ifconfig. Say it results of a local IP address of 192.168.1.3.

Publish the Ports of the Routing Listeners

One or more routers of the network will have a routing listener. Say we have 1 router which has a listener on port 4001. This needs to be exposed by the -p option:

-p 4100:4100
CODE

Use the local IP Address in the Routing Connectors

Other routers in the network will connect to one or more routing listeners of other routers. Use the IP address of the Docker host in your preconfig file (example for `edge2``:

<router name="edge2">
    <swiftlet name="sys$routing">
        <connectors _op="clear">
            <connector _op="add" name="edge1" hostname="192.168.1.3" port="4100"/>
        </connectors>
    <swiftlet>
</router>
XML

Another alternative is to use:

<router name="edge2">
    <swiftlet name="sys$routing">
        <connectors _op="clear">
            <connector _op="add" name="edge1" hostname="dockerhost" port="4100"/>
        </connectors>
    <swiftlet>
</router>
XML

and use the option:

--add-host dockerhost:192.168.1.3
CODE

at the command line of the connecting routers.

This will connect to the Docker host on port 4100 on which the router with the routing listener (done with -p) is listening. Both containers can now connect.

Recommended Directory Structure for Router Networks

Create a folder somewhere. For each router in the network create a subfolder with the router name. Each of these folders should be structured as described at the beginning of this page (Recommended Directory Structure...).

network/
       <routername1>
             preconfig/
             data/
       <routername2>/
             preconfig/
             data/
CODE

Create a new shell script file in this folder (network/ in this example) called rundocker. It should have this content for SwiftMQ CE:

P=`pwd`
docker run -v "$P/$1/preconfig:/swiftmq/preconfig" \
           -v "$P/$1/data:/swiftmq/data" \
           $2 \
           -e SWIFTMQ_PRECONFIG=/swiftmq/preconfig/preconfig.xml iitsoftware/swiftmq-ce:12.0.0
CODE

Say, we have 4 routers, edge1 to edge4. edge1 has a JMS listener on port 4001 and a routing listener on port 4100. All others have only a routing connector to edge1.

To start all 4 nodes, use:

./rundocker edge1 "-p 4001:4001 -p 4100:4100" &
./rundocker edge2 "--add-host dockerhost:192.168.1.3" &
./rundocker edge3 "--add-host dockerhost:192.168.1.3" &
./rundocker edge4 "--add-host dockerhost:192.168.1.3" &
CODE

All nodes should now be up, running and connected.

Running the Router Network with Docker Compose

The following docker-compose.yml runs the same above containers:

version: '3'
services:
  edge1:
    image: "iitsoftware/swiftmq-ce:latest"
    ports:
      - "4001:4001"
      - "4100:4100"
    environment:
      - SWIFTMQ_PRECONFIG=/swiftmq/preconfig/preconfig.xml
    volumes:
        - ${PWD}/edge1/preconfig:/swiftmq/preconfig
        - ${PWD}/edge1/data:/swiftmq/data
    extra_hosts:
        - "dockerhost:${myIP}"
  edge2:
    image: "iitsoftware/swiftmq-ce:12.0.0"
    environment:
      - SWIFTMQ_PRECONFIG=/swiftmq/preconfig/preconfig.xml
    volumes:
        - ${PWD}/edge2/preconfig:/swiftmq/preconfig
        - ${PWD}/edge2/data:/swiftmq/data
    extra_hosts:
        - "dockerhost:${myIP}"
  edge3:
    image: "iitsoftware/swiftmq-ce:12.0.0"
    environment:
      - SWIFTMQ_PRECONFIG=/swiftmq/preconfig/preconfig.xml
    volumes:
        - ${PWD}/edge3/preconfig:/swiftmq/preconfig
        - ${PWD}/edge3/data:/swiftmq/data
    extra_hosts:
        - "dockerhost:${myIP}"
  edge4:
    image: "iitsoftware/swiftmq-ce:12.0.0"
    environment:
      - SWIFTMQ_PRECONFIG=/swiftmq/preconfig/preconfig.xml
    volumes:
        - ${PWD}/edge4/preconfig:/swiftmq/preconfig
        - ${PWD}/edge4/data:/swiftmq/data
    extra_hosts:
        - "dockerhost:${myIP}"
YAML

With this shell script:

#!/bin/bash

export myIP=`ifconfig $(netstat -rn | grep -E "^default|^0.0.0.0" | head -1 | awk '{print $NF}') | grep 'inet ' | awk '{print $2}' | grep -Eo '([0-9]*\.){3}[0-9]*'`
export PWD=`pwd`

case "$1" in
  start)
        docker-compose up -d
    ;;
  stop)
        docker-compose down
    ;;
  status)
        docker ps
    ;;
  *)
    echo "Usage: $N {start|stop|status}"
    exit 1
    ;;
esac
exit 0
BASH

Starting CLI

To start CLI, SwiftMQ's command-line interface, perform a

    ./cli
CODE

from the scripts directory. As username/password press the return key (anonymous) or use admin, password secret.

Standard Configuration

This distribution contains a standard configuration of a single SwiftMQ router with the name router.

Authentication

Authentication is disabled, so you can use all resources without defining special grants. To log in, use either the anonymous user (no username, no password) or the administrator account (username admin, password secret).

JMS

A JMS listener is configured on port 4001. The JMS listener uses thecom.swiftmq.net.PlainSocketFactory. A connection factory can be looked up under plainsocket@router, ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory.

AMQP

An AMQP listener is configured on port 5672 (non-TLS).

MQTT

An MQTT listener is configured on port 1883 (non-TLS).

Routing

A Routing listener is configured on port 4100 (non-TLS).

Point-to-Point Resources

The router has a predefined queue testqueue which can be looked up via JNDI on testqueue@router.

Pub/Sub Resources

There is one predefined topic testtopic that can be looked up via JNDI under this name.

Examples

There are several JMS, AMQP, CLI, and router network examples included in the samples directory. There is also a Readme.txt in the samples directory which you may consult before using it.