High Quality JMS Messaging.

Hot Deploy Containers

JMS applications can be hot deployed. In contrast to static JMS application containers, hot deploy JMS application containers are not configurable via SwiftMQ Explorer/CLI or the router's configuration file. Rather, they are configured via their deployment descriptor which is part of the deployment bundle.

Hot deployment enables you to upgrade a JMS application automatically without stopping the router, e.g. deploying a new version of a JMS application with totally different classes into a production system during runtime.

A deployment descriptor can optionally contain a schedule to run the application as a job from the Scheduler Swiftlet, thus, enables you to run any Java application as a hot deployable job.

The Deployment Bundle

The collection of all necessary files to hot deploy a JMS application is called a deployment bundle. It consists of:

The Deployment Descriptor

The deployment descriptor is a small XML file with the name "config.xml". It contains similar configuration information as for static JMS application containers:

A shutdown method is mandatory for hot deploy JMS applications, because it must be stopped during an undeployment. A class path isn't specified, because the class path consists of the jar files etc contained in the bundle. Further, a hot deploy JMS application will be automatically started during deployment and stopped before it is undeployed.

The following example deployment descriptor contains the configuration of the TestPublisher example:

      <deployment-descriptor>
        <main-class>TestPublisher</main-class>
        <main-class-arguments>
          smqp://intravm/timeout=10000 IVMTopicConnectionFactory testtopic 1000000
        </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>

main-class

Contains the fully qualified class name of the class with the "main" method.

main-class-arguments

This is optional. Contains the arguments to the "main" class, delimited by blanks.

shutdown-method-name

Contains the name of the shutdown method. It has to be "public static" with a return type of "void" and has to be part of the "main" class. The shutdown method must close all resources of the JMS application and must stop all threads, started from the application.

Example:

        public static void stop()
        {
          // do whatever to stop this app!
          try
          {
            connection.close();
          } catch (JMSException e)
          {
          }
        }

main-return-is-stop

This is optional. Specifies whether a return from the "main" method marks the application as stopped.

startup-delay

Contains a millisecond value which is used to delay the start of the application after it has been deployed. This is useful to create a start sequence of hot deploy JMS applications, because when the router starts, all hot deployed JMS applications are started asynchronously in different threads.

system-properties

This is optional. Contains "system-property" elements to define necessary system properties for the application. These system properties are visible to all JMS applications, because they use the same virtual machine.

schedule

Starting with SwiftMQ 5.0.0, a deployment descriptor can contain an optional "schedule" element. If specified, the application will be invoked on the schedule from the Scheduler Swiftlet. The management of job registration etc. at the Scheduler Swiftlet takes place automatically. A "schedule" element can contain the following attributes:

A schedule is created dynamically at the Scheduler Swiftlet during the deployment and deleted during the undeployment so the elements of the schedule are the same as you have to specify for schedules of the Scheduler Swiftlet. For further infos please take a look there.

The following shows an example of the above deployment descriptor for the "TestPublisher". However, now it is scheduled as a job:

        <deployment-descriptor>
          <main-class>TestPublisher</main-class>
          <main-class-arguments>
            smqp://intravm/timeout=10000 IVMTopicConnectionFactory testtopic 1000000
          </main-class-arguments>
          <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="2003-11-20"
              logging-enabled="true"/>
          <system-properties>
            <system-property name="someprop" value="someval"/>
          </system-properties>
        </deployment-descriptor>

The Deployment Classes

There has to be at least 1 jar file in the bundle, containing the necessary classes of the application. Of course, it can be more than 1 jar file, however, it is not possible to use plain .classes. You have to jar it. You also cannot use .zip files. If your application needs native libraries, they have to be part of the bundle.

A dedicated class loader is created during deployment, referencing all jar files and native libraries in the bundle. The parent classloader is that one which loaded the SwiftletManager class, hence, all SwiftMQ jar files are already present in the classpath.

Skeleton of a Hot Deploy JMS Application

This is a skeleton of a hot deploy JMS application:

    public class JacSkeleton
    {
      static final Object obj = new Object();
      static final boolean shutdownCalled = false;

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

        // Then wait here until shutdown is called
        try
        {
          synchronized (obj)
          {
            if (!shutdownCalled)
             obj.wait();
          }
        } catch (InterruptedException ignored)
        {
        }

        // Now close all resources and terminate
      }

      public static void shutdown()
      {
        // Trigger main to stop
        synchronized (obj)
        {
          shutdownCalled = true;
          obj.notify();
        }
      }
    }

It ensures that the "main" method doesn't terminate until "shutdown" is being called.

How To Deploy

The JMS Application Container Swiftlet listens on a deploy space named "jms-app", defined in the Deploy Swiftlet configuration:

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

The path defined in the deploy space is the directory where you create your bundles.

Directory Structure

The following picture shows an example of a deployed JMS application:

The directory "jmsapp/router1" is the path of the deploy space "jms-app". There is 1 JMS application deployed. The name is "testpub". This directory is called the "bundle directory". Directly within this directory are stored the deployment descriptor ("config.xml") and 1 jar file ("test.jar"). The sub-directory "_deployed_..." contains the actual deployment. It is created and managed by the Deploy Swiftlet. It contains copies of the deployment descriptor and the bundle jar files.

Creating a Bundle (Deploy)

Create a bundle directory, e.g. "jmsapp/router1/testpub". Copy the deployment descriptor "config.xml" and your jar files and/or native libs into this directory. Your application will be deployed within the next check-interval (default 1 minute).

Removing a Bundle (Undeploy)

Remove the deployment descriptor "config.xml" and your jar files / native libs out of the bundle directory. Don't touch the actual deployment ("_deployed_..." directories)! Your application will be undeployed within the next check-interval (default 1 minute).

Changing a Bundle (Redeploy)

Change either the deployment descriptor "config.xml" or change any of the jar files / native libs. Your application will be redeployed within the next check-interval (default 1 minute).

Errors during Deployment

Any error during deployment leads to an undeploy of the bundle. An attempt is made on every check-interval of the deploy space to deploy it again. So in case of an error within your application, you can simply overwrite your jar files with a new version. All errors during deployment are reported to the router's error log file.