Skip to content

JMS Application Container Swiftlet

Overview

The JMS Application Container Swiftlet (sys$jac) provides a managed environment for running custom Java applications within the SwiftMQ router. It supports both statically configured applications and dynamic hot deployment via bundles, offering lifecycle management, classpath isolation, and optional scheduling for application execution.

Features

Static JMS Application Containers

Static JMS Application Containers are defined directly in the router's configuration and represent Java applications that are started and managed by the Swiftlet. Each static container specifies the main class to invoke, optional arguments, classpath entries, system properties, and lifecycle settings. The application is started by invoking its static main method and can be stopped via an optional static shutdown method. Applications can be enabled or disabled at runtime, and a startup delay can be configured to defer their launch after the router starts. The container ensures classpath isolation for each application and applies configured system properties before startup. If the main-return-is-stop property is enabled, the application is automatically stopped when its main method returns.

Classpath Management

Each static container can define its own set of classpath entries, allowing applications to load specific libraries without interfering with other applications or the router itself. Changes to the classpath require the application to be disabled first, ensuring classloader consistency.

System Properties Injection

System properties can be defined for each application and are set in the JVM before the application is started. These properties are managed dynamically and can be added or removed while the application is not running.

Lifecycle and Threading

Applications can be started and stopped via the enabled property. The use-virtual-thread property determines whether the application runs on a virtual thread or a platform thread. The startup delay allows for staged application initialization.

Configuration Example:

<swiftlet name="sys$jac">
  <static-containers>
    <static-container name="myapp" enabled="true" main-class="com.example.MyApp" main-class-arguments="arg1 arg2" startup-delay="1000" main-return-is-stop="true" use-virtual-thread="false">
      <system-properties>
        <system-property name="ENV" value="production"/>
      </system-properties>
      <classpath>
        <path-entry name="lib1" value="/opt/myapp/lib/myapp.jar"/>
      </classpath>
    </static-container>
  </static-containers>
</swiftlet>

Hot Deployment of JMS Applications

The Swiftlet supports dynamic deployment of JMS applications through hot deploy bundles. These bundles contain a deployment descriptor specifying the main class, shutdown method, arguments, system properties, and optional scheduling information. Upon deployment, the Swiftlet creates an isolated classloader, applies system properties, and manages the application lifecycle. Hot deployed applications can be started immediately or according to a defined schedule. The Swiftlet tracks running hot deploy applications and ensures proper cleanup on undeploy or router shutdown.

Deployment Descriptor Parsing

Each bundle must provide a descriptor XML specifying the required main class, shutdown method, and optional arguments, startup delay, system properties, and schedule. The Swiftlet validates and parses this descriptor during deployment.

Scheduling Support

If a schedule is defined in the deployment descriptor, the application is started and stopped according to the schedule using the router's scheduler. Schedule attributes include time expressions, calendar, date range, maximum runtime, and logging options.

Job Scheduling Integration

The Swiftlet integrates with the router's scheduler to allow both static and hot deployed applications to be started and stopped according to defined schedules. For static containers, a job factory is registered that can invoke the application by name. For hot deploys, each application with a schedule is registered as a temporary job with its own schedule parameters. This enables automated, time-based control of application lifecycles.

Job Factories and Job Groups

The Swiftlet registers job factories for static and hot deployed applications under the JAC job group. These factories create job instances that manage application start and stop operations, and handle job termination events if the application's main method returns.

Configuration Guide

Defining a Static JMS Application with Custom Classpath and System Properties

Use this scenario to configure a Java application that should be started automatically with specific system properties and additional libraries.

  1. Add a new static-container entry under the static-containers list.
  2. Specify the main-class and set enabled to true.
  3. Add required system properties and classpath entries.
  4. Optionally configure main-class-arguments, startup-delay, and use-virtual-thread.
<swiftlet name="sys$jac">
  <static-containers>
    <static-container name="analytics" enabled="true" main-class="com.company.AnalyticsMain" startup-delay="5000">
      <system-properties>
        <system-property name="LOG_LEVEL" value="DEBUG"/>
      </system-properties>
      <classpath>
        <path-entry name="analytics-lib" value="/opt/analytics/analytics.jar"/>
        <path-entry name="dep-lib" value="/opt/analytics/dep.jar"/>
      </classpath>
    </static-container>
  </static-containers>
</swiftlet>

Hot Deploying an Application with a Schedule

Use this scenario to deploy a Java application as a bundle and have it started and stopped automatically according to a schedule.

  1. Prepare a bundle with the application JARs and a deployment descriptor XML specifying main class, shutdown method, and schedule.
  2. Deploy the bundle to the jms-app deploy space.
  3. The application will be started and stopped according to the schedule defined in the descriptor.

Scheduler Jobs

Application Invoker

Description: Invokes a static Application

Hot Deploy Containers

Hot Deploy Containers enable automatic deployment of JMS applications without stopping the router.

The Deployment Bundle

A deployment bundle is a directory containing:

  • config.xml — the deployment descriptor
  • One or more .jar files with the application classes
  • Optional native libraries (if JNI is used)

Deployment Descriptor

The descriptor (config.xml) defines how the application is started and stopped:

<deployment-descriptor>
  <main-class>com.example.MyApp</main-class>
  <main-class-arguments>
    smqp://intravm/timeout=10000 IVMTopicConnectionFactory testtopic
  </main-class-arguments>
  <shutdown-method-name>stop</shutdown-method-name>
  <main-return-is-stop>true</main-return-is-stop>
  <startup-delay>2000</startup-delay>
  <system-properties>
    <system-property name="someprop" value="someval"/>
  </system-properties>
</deployment-descriptor>
Element Required Description
main-class Yes Fully qualified class name with a public static void main(String[]) method
main-class-arguments No Arguments to main, delimited by spaces
shutdown-method-name Yes Name of a public static void method in the main class that stops the application
main-return-is-stop No If true, returning from main marks the application as stopped
startup-delay No Milliseconds to delay startup after deployment
system-properties No System properties set before the application starts
schedule No Scheduler integration (see below)

Scheduled Applications

Add a schedule element to run the application on a schedule managed by the Scheduler Swiftlet:

<deployment-descriptor>
  <main-class>com.example.MyApp</main-class>
  <shutdown-method-name>stop</shutdown-method-name>
  <main-return-is-stop>true</main-return-is-stop>
  <schedule time-expression="start 10:00 stop 17:00 delay 10m"
      date-to="2025-12-31"
      logging-enabled="true"/>
</deployment-descriptor>

Schedule attributes: time-expression (mandatory), calendar, date-from, date-to, max-runtime, logging-enabled.

Application Skeleton

A hot deploy application must not return from main until shutdown is called:

public class MyApp {
    static final Object lock = new Object();
    static boolean shutdownCalled = false;

    public static void main(String[] args) {
        // Start your JMS application here

        // Wait until shutdown is called
        synchronized (lock) {
            while (!shutdownCalled) {
                try { lock.wait(); } catch (InterruptedException ignored) {}
            }
        }

        // Close all resources
    }

    public static void stop() {
        synchronized (lock) {
            shutdownCalled = true;
            lock.notify();
        }
    }
}

Deploy Space Configuration

The deploy space for hot deploy bundles is configured in the Deploy Swiftlet:

<swiftlet name="sys$deploy">
  <deploy-spaces>
    <deploy-space name="jms-app" path="../data/jmsapp"/>
  </deploy-spaces>
</swiftlet>

Deploy / Undeploy / Redeploy

Deploy: Create a bundle directory (e.g., data/jmsapp/myapp/), place config.xml and jar files in it. The application deploys within the next check-interval (default: 1 minute).

Undeploy: Remove config.xml and jar files from the bundle directory. The application undeploys within the next check-interval.

Redeploy: Update config.xml or any jar files. The application redeploys automatically within the next check-interval.

Each hot deployed application uses its own classloader, isolated from other applications and the router core. Deployment errors are reported to the router's error log and cause an automatic undeploy.

Configuration Reference

The top-level entity in routerconfig.xml is <swiftlet name="sys$jac">.

<static-containers> in <swiftlet name="sys$jac">

Static Containers

Each <static-container> entry is identified by its name attribute (the Static Container).

Parameter Type Default Mandatory Reboot Required Description
startup-delay Long 0 No No Delay (ms) to wait before start
enabled Boolean false No No Enables/Disables this Container
main-class String Yes No The class name with the main method
main-class-arguments String No No The Arguments of the Main Class (blank is Delimiter)
main-return-is-stop Boolean false No No Is the return from the main method is equal to stop?
shutdown-method-name String No No Optional static Shutdown Method Name
use-virtual-thread Boolean true No No Uses a virtual thread to run this app, otherwise a platform thread
<swiftlet name="sys$jac">
  <static-containers>
    <static-container name="..." main-class="..."/>
  </static-containers>
</swiftlet>

<system-properties> in <static-containers>

System Properties

Each <system-property> entry is identified by its name attribute (the System Property).

Parameter Type Default Mandatory Reboot Required Description
value String Yes No Property Value
<swiftlet name="sys$jac">
  <static-containers>
    <static-container name="...">
      <system-properties>
        <system-property name="..." value="..."/>
      </system-properties>
    </static-container>
  </static-containers>
</swiftlet>

<classpath> in <static-containers>

Classpath

Each <path-entry> entry is identified by its name attribute (the Path Entry).

Parameter Type Default Mandatory Reboot Required Description
value String Yes No Path Entry
<swiftlet name="sys$jac">
  <static-containers>
    <static-container name="...">
      <classpath>
        <path-entry name="..." value="..."/>
      </classpath>
    </static-container>
  </static-containers>
</swiftlet>

Changelog

13.1.2 (2025-04-15)

  • Modified JACSwiftlet
  • Modified configuration; Modified Descriptor