5.2. Creating Bundles

A bundle is made of two elements:
  • A recipe file, which can either be an Ant recipe or a simple text file
  • Associated bundle files, which can include archive files (JAR or ZIP files) or raw text configuration files
The bundle type is determined by its recipe type because the recipe file is the one interpreted by JBoss ON when the bundle is provisioned.
When a bundle is created, then either the recipe and all associated files can be loaded manually to the JBoss ON server, or the recipe and all associated files can be zipped into a single distribution zip file which can be uploaded or accessed through a URL. If there is a single distribution file, then the recipe file must be in the top directory and all files should be available in the locations they are referenced in in the recipe. This is illustrated in Figure 5.2, “Bundle Layout”, which has a recipe and associated files in a flat directory, packaged in distribution.zip (although the name doesn't matter).
Bundle Layout

Figure 5.2. Bundle Layout


5.2.1. Creating an Associated Archive File

The application that is being deployed itself has to be built into an archive file of some kind. JBoss ON allows JAR and ZIP formats. The bundle archive file can also include raw files that are used to configuration the application, such as XML, .conf, and text files. These can be templatized to supply user- and system-specific information (as described in Section 5.2.2, “Using Template Configuration Files in Bundles”).
Any required archive or file must be referenced in the recipe so that the server knows to copy it during deployment.
The bundle files can be uploaded and stored in the JBoss ON server or they can be zipped up, with the recipe files, into a single distribution file.

5.2.2. Using Template Configuration Files in Bundles

A bundle can contain configuration files for an application. These configuration files can use hard-coded values or they can use tokens that are automatically realized when the bundle is actually deployed.
A token value can be supplied by a user or derived from the specific host system.

NOTE

For a user-defined token to be realized, it must be referenced in the recipe so that the bundle deployment wizard will prompt for the value. For an Ant recipe, this requires the <rhq:input-property> key.
User-defined tokens can be anything; the values are supplied through the provisioning UI and inserted into the templatized configuration file. The only restriction is that user-defined tokens must contain only alphanumeric characters, an underscore (_), or a period (.); no other characters are allowed. For example, to set a port number in a configuration file:
port=@@listener.port@@
The user-defined token then must be noted in the recipe, so that the provisioning process knows to realize the phrase. The provisioning wizard will prompt for a value for all of the user-defined tokens referenced in the recipe. To configure a property in an Ant recipe, add a <rhq:input-property> key in the Ant XML file.
For example:
<rhq:input-property
    name="listener.port"
    ... />
Along with user-defined variables that can be specified in the recipe file, there are variables that are made implicitly available to each recipe type. These tokens can be used in a templatized file as a user-defined variable without having to define the token template in the recipe itself.

Table 5.1. Variables Defined by JBoss ON

Token Description
rhq.deploy.dir The directory location where the bundle will be installed.
rhq.deploy.id A unique ID assigned to the specific bundle deployment.
rhq.deploy.name The name of the bundle deployment.

Additionally, some tokens can be realized by the provisioning process pulling information from the local system. These values, listed in Table 5.2, “System-Defined Tokens”, are taken either from the Java API or from Java system properties. They can be inserted directly in the templatized configuration file without having to put a corresponding entry in the recipe. For example:
@@rhq.system.hostname@@

Table 5.2. System-Defined Tokens

Token Name Taken From... Java API
rhq.system.hostname Java API SystemInfo.getHostname()
rhq.system.os.name Java API SystemInfo.getOperatingSystemName()
rhq.system.os.version Java API SystemInfo.getOperatingSystemVersion()
rhq.system.os.type Java API SystemInfo.getOperatingSystemType().toString()
rhq.system.architecture Java API SystemInfo.getSystemArchitecture()
rhq.system.cpu.count Java API SystemInfo.getNumberOfCpus()
rhq.system.interfaces.java.address Java API InetAddress.getByName(SystemInfo.getHostname()).getHostAddress()
rhq.system.interfaces.network_adapter_name.mac Java API NetworkAdapterInfo.getMacAddress()
rhq.system.interfaces.network_adapter_name.type Java API NetworkAdapterInfo.getType()
rhq.system.interfaces.network_adapter_name.flags Java API NetworkAdapterInfo.getAllFlags()
rhq.system.interfaces.network_adapter_name.address Java API NetworkAdapterInfo.getUnicastAddresses().get(0).getHostAddress()
rhq.system.interfaces.network_adapter_name.multicast.address Java API NetworkAdapterInfo.getMulticastAddresses().get(0).getHostAddress()
rhq.system.sysprop.java.io.tmpdir Java system property
rhq.system.sysprop.file.separator Java system property
rhq.system.sysprop.line.separator Java system property
rhq.system.sysprop.path.separator Java system property
rhq.system.sysprop.java.home Java system property
rhq.system.sysprop.java.version Java system property
rhq.system.sysprop.user.timezone Java system property
rhq.system.sysprop.user.region Java system property
rhq.system.sysprop.user.country Java system property
rhq.system.sysprop.user.language Java system property

5.2.3. Creating Ant Bundles

Most bundle deployments will use an Ant recipe bundle because of the inherent flexibility and extensibility of using the Ant build system to deploy bundles.
Section 5.2.3.1, “Requirements for an Ant Bundle” and Section 5.2.3.2, “A Reference of JBoss ON Ant Recipe Elements” both cover the details of creating an Ant recipe. The Ant recipe and bundle can be deployed using the JBoss ON server UI. There is also an additional tool that allows developers to test-deploy Ant bundles from the command line; using the tool can help automate building and testing custom software. This tool (described in Section 5.3, “Testing Bundle Deployment Using the Command Line”) is only intended for testing Ant bundles, which can be very complex.

5.2.3.1. Requirements for an Ant Bundle

The Ant recipe for JBoss ON bundles is the same basic file as a standard Apache Ant file and is processed by an integrated Ant build system in JBoss ON. This Ant recipe file must be bundled in the top directory of the distribution ZIP file and be named deploy.xml.
The JBoss ON Ant recipes allows all of the standard tasks that are available for Ant builds, which provides flexibility in scripting a deployment for a complex application. The JBoss ON Ant recipe must also provide additional information about the deployment that will be used by the provisioning process; this includes information about the destination and, essentially, metadata about the application itself.
Example 5.1, “Example Ant Recipe” shows a simplified recipe with several basic characteristics:
  • A version number of 2.4
  • Two required application files, an archive file called MyApp.zip and a configuration file called test-v2.properties (in the bundle)
  • One user-defined token, listener.port
  • An application log directory to be created in appRoot/logs
As with other Ant scripts, the JBoss ON Ant recipe uses a standard XML file with a <project> root element and defined targets and tasks. The elements defined in the <rhq:bundle> area pass metadata to the JBoss ON provisioning system when the project is built. For provisioning, the Ant recipe is more of a definition file than a true script file.

Example 5.1. Example Ant Recipe

<?xml version="1.0"?>
<project name="test-bundle" default="main" 
    xmlns:rhq="antlib:org.rhq.bundle">

    <rhq:bundle name="Example App" version="2.4" description="an example bundle">
        <rhq:input-property
            name="listener.port"
            description="This is where the product will listen for incoming messages"
            required="true"
            defaultValue="8080"
            type="integer"/>

        <rhq:deployment-unit name="appserver" preinstallTarget="preinstall" postinstallTarget="postinstall">
            <rhq:file name="test-v2.properties" destinationFile="subdir/test.properties" replace="true"/>
            <rhq:archive name="MyApp.zip">
                <rhq:replace>
                    <rhq:fileset>
                        <include name="**/*.properties"/>
                    </rhq:fileset>
                </rhq:replace>
            </rhq:archive>
            <rhq:ignore>
                <rhq:fileset>
                    <include name="logs/*.log"/>
                </rhq:fileset>
            </rhq:ignore>
        </rhq:deployment-unit>
    </rhq:bundle>

    <target name="main" />

    <target name="preinstall">
        <echo>Deploying Test Bundle v2.4 to ${rhq.deploy.dir}...</echo>
        <property name="preinstallTargetExecuted" value="true"/>
    </target>

    <target name="postinstall">
        <echo>Done deploying Test Bundle v2.4 to ${rhq.deploy.dir}.</echo>
        <property name="postinstallTargetExecuted" value="true"/>
    </target>
</project>

Section 5.2.3.2, “A Reference of JBoss ON Ant Recipe Elements” explores the different JBoss ON elements in the Ant recipe file. For information on standard Ant tasks, see the Apache Ant documentation.

5.2.3.2. A Reference of JBoss ON Ant Recipe Elements

5.2.3.2.1. rhq:bundle
Contains the definition for the main JBoss ON-related Ant task that is required for any Ant bundle recipe. This element defines basic information about the bundle and is the parent element for all of the specific details about what is in the bundle and how it should be provisioned.
Element Attributes
Attribute Description Optional or Required
name The name given to the bundle. Required
version The version string for this specific bundle. Bundles can have the same name, but each bundle of that name must have a unique version string. These version strings normally conform to an OSGi style of versioning, such as 1.0 or 1.2.FINAL. Required
description A readable description of this specific bundle version. Optional
Example
<rhq:bundle name="example" version="1.0" description="an example bundle">
5.2.3.2.2. rhq:input-property
Adds a property to the bundle task that defines a template token that must have its value supplied by a user at the time the bundle is deployed. This is similar to standard Ant properties.

NOTE

All of the system properties listed in Table 5.2, “System-Defined Tokens” and the Ant-specific tokens in Table 5.1, “Variables Defined by JBoss ON” are available to be used as templatized tokens in bundle configuration without having to set a <rhq:input-property> definition.
All input properties set some parameter that must have its value defined by a user when the bundle is provisioned on a platform, and the fields to enter those values are automatically generated in the JBoss ON UI bundle deployment wizard.
Element Attributes
Attribute Description Optional or Required
name The name of the user-defined property. Within the recipe, this property can be referred to by this name, in the format ${property_name}. Required
description A readable description of the property. This is the text string displayed in the JBoss ON bundle UI when the bundle is deployed. Required
type Sets the syntax accepted for the user-defined value. There are several different options:
  • string
  • longString
  • long
  • password
  • file
  • directory
  • boolean
  • integer
  • float
  • double
Required
required Sets whether the property is required or optional for configuration. The default value is false, which means the property is optional. If this argument isn't given, then it is assumed that the property is optional. Optional
defaultValue Gives a value for the property to use if the user does not define a value when the bundle is deployed. Optional
Example
<rhq:input-property
    name="listener.port"
    description="This is where the product will listen for incoming messages"
    required="true"
    defaultValue="8080"
    type="integer"/>
5.2.3.2.3. rhq:deployment-unit
Defines the application being deployed by the bundle. A deployment unit is a software product, in any form, including an application server, web server, or database. A deployment unit (application) can have multiple archive and configuration files associated with it.
Only a single deployment unit is provisioned at a time by the provisioning process, so there can be only one <rhq:deployment-unit> element in a bundle recipe.
Element Attributes
Attribute Description Optional or Required
name The name of the application. Required
preinstallTarget An Ant target that is invoked before the deployment unit is installed. Optional
postinstallTarget An Ant target that is invoked after the deployment unit is installed. Optional
Example
<rhq:deployment-unit name="appserver" preinstallTarget="preinstall" postinstallTarget="postinstall">
5.2.3.2.4. rhq:archive
Defines any archive file that is associated with deploying the application. An archive can be a ZIP or JAR file. A bundle doesn't require an archive file, so this element is optional.
Element Attributes
Attribute Description Optional or Required
name The filename of the archive file to include in the bundle.

IMPORTANT

If the archive file is packaged with the Ant recipe file inside the bundle distribution ZIP file, then the name must contain the relative path to the location of the archive file in the ZIP file.
Required
Example
<rhq:archive name="file.zip">
    <rhq:replace>
         <rhq:fileset>
               <include name="**/*.properties"/>
         </rhq:fileset>
    </rhq:replace>
</rhq:archive>
5.2.3.2.5. rhq:file
Contains the information to identify and process configuration files for the application which have token values that must be realized. Normally, configuration files are copied directly from the bundle package into the destination directory. The <rhq:file> element calls out files that require processing before they should be copied to the destination. The attributes on the <rhq:file> element set the name of the raw file in the bundle distribution ZIP file and the name of the target file that it should be copied to.
Raw files can be included with the archive files that contain properties or configuration for the application. These configuration files can be templatized with user-defined or system-defined tokens, like those listed in Section 5.2.2, “Using Template Configuration Files in Bundles”. Any templatized files that are included in the bundle distribution file that are templatized must be listed in the Ant recipe so that they are processed and the tokens are realized.
Element Attributes
Attribute Description Optional or Required
name The name of the raw configuration file.

IMPORTANT

If the configuration file is packaged with the Ant recipe file inside the bundle distribution ZIP file, then the name must contain the relative path to the location of the file within the ZIP file.
Required
destinationFile The full path and filename for the file on the destination platform. Relative paths must be relative to the final destination directory (defined in the rhq.deploy.dir parameter when the bundle is deployed). It is also possible to use absolute paths, as long as both the directory and the filename are specified. Required
replace Indicates whether the file is templatized and requires additional processing to realize the token values. Required
Example
<rhq:file name="test-v2.properties" destinationFile="subdir/test.properties" replace="true"/>
5.2.3.2.6. rhq:replace
Lists templatized files, in children <rhq:fileset> elements, contained in the archive which need to have token values realized when the archive is deployed.
Any file which uses a token that must be replaced with a real value is a templatized file. When the provisioning process runs, the token value is substituted with the defined value. This element lists all of the files which are templatized; the only files which are processed by the provisioning system for token substitution are the ones listed in the <rhq:replace> element.
Example
<rhq:archive name="file.zip">
    <rhq:replace>
        <rhq:fileset>
            <include name="**/*.properties"/>
        </rhq:fileset>
    </rhq:replace>
</rhq:archive>
5.2.3.2.7. rhq:ignore
Lists files from a previous bundle deployment that should be ignored when the bundle is deployed.
Once an application is deployed, instance-specific files — like data files or logs — can be created and should be retained if the application is ever upgraded. This element, much like <rhq:replace>, contains a list of files or directories in the instance to save.

NOTE

If a file is ignored in the recipe, then the file is left unchanged. Never ignore files packaged in the bundle. Only files generated by the applications, such as log and data files, should be ignored by the provisioning process since they should be preserved for the upgraded instance.
Example
<rhq:ignore>
    <rhq:fileset>
        <include name="logs/*.log"/>
    </rhq:fileset>
</rhq:ignore>
5.2.3.2.8. rhq:fileset
Provides a list of files.
Two JBoss ON elements — <rhq:replace> and <rhq:ignore> — define file lists in either the archive file or the destination directory. This element contains the list of files.
Child Element
Child Element Description
<include name=filename /> The filename of the file. For <rhq:replace>, this is a file within the archive (JAR or ZIP) file which is templatized and must have its token values realized. For <rhq:ignore>, this is a file in the application's deployment directory which should be ignored and preserved when the bundle is upgraded.
Example
<rhq:replace>
     <rhq:fileset>
         <include name="**/*.properties"/>
     </rhq:fileset>
</rhq:replace>
5.2.3.2.9. rhq:system-service
Points to a script file to launch as part of the provisioning process. This is usually an init file or similar file that can be used by the deployed application to set the application up as a system service.
Element Attributes
Attribute Description Optional or Required
name The name of the script. Required
scriptFile The filename of the script. If the script file is packaged with the Ant recipe file inside the bundle distribution ZIP file, then the scriptFile must contain the relative path to the location of the file in the ZIP file. Required
configFile The name of any configuration or properties file used by the script. If the configuration file is packaged with the Ant recipe file inside the bundle distribution ZIP file, then the configFile must contain the relative path to the location of the file in the ZIP file. Optional
overwriteScript Sets whether to overwrite any existing init file to configure the application as a system service. Optional
startLevels Sets the run level for the application service. Optional
startPriority Sets the start order or priority for the application service. Optional
stopPriority Sets the stop order or priority for the application service. Optional
Example
<rhq:system-service name="example-bundle-init" scriptFile="example-init-script"
      configFile="example-init-config" overwriteScript="true"
      startLevels="3,4,5" startPriority="80" stopPriority="20"/>
5.2.3.2.10. Default Target
As with other Ant tasks, the <project> allows a default target, which is required by the provisioning system. This target can be used to do something for the application or can be a no-op. The most common thing is for the default target to be a no-op because the Ant recipe mainly defines the metadata for and identifies files used by the provisioning process. Other operations aren't necessary.
<target name="main" />
5.2.3.2.11. Pre-Install and Post-Install Targets
JBoss ON provisioning tasks, like other Ant tasks, can define both pre- and post-install targets. This allows custom tasks, like simple progress messages or setting properties.

5.2.3.3. Upgrading Ant Bundles

The bundle upgrade process decides whether to upgrade (meaning, overwrite) files within the application's deployment directory by comparing the MD5 hash codes on the files. There are several different upgrade scenarios:
  • If the hash code on the new file is different than the original file and there are no local modifications, then JBoss ON installs the new file over the existing file.
  • If the hash code on the new file is different than the original file and there are local modifications, then JBoss ON backs up the original file and installs the new file.
  • If the hash code on the new file and the original file is the same and there are local modifications on the original file, then the provisioning process preserves the original file, in place.
  • If there was no file in the previous bundle but there is one in the new bundle, then the new file is used and any file that was added manually is backed up.
Backed up files are saved to a backup/ directory within the deployment's destination directory. If the original file was located outside the application's directory (like, it was stored according to an absolute location rather than a relative location), then it is saved in an ext-backup/ directory within the deployment's destination directory.

NOTE

If a file is ignored in the recipe, then the file is left unchanged. Never ignore files packaged in the bundle. Only files generated by the applications, such as log and data files, should be ignored by the provisioning process since they should be preserved for the upgraded instance.
If a completely fresh installation is required, then it is possible to run a clean deployment. This is described in Section 5.8, “Deploying a Bundle to a Clean Destination”.