© 2018 The original authors.

1. Overview

Galleon is a provisioning tool designed to create and maintain software distributions that consist of one or more products (or components). The tool supports:

  • adding products to a distribution;

    • their default and customized configurations;

  • removing products from a distribution;

  • integration of the products in the distribution;

  • resolution and validation of the resulting configuration and runtime dependencies;

  • patching and version updates;

  • product-specific provisioning plugins;

  • detection of the changes in the provisioned distribution (its filesystem content and/or its configuration) applied by the user manually or by means of other management tools

    • to be able to preserve them after a version upgrade (having made sure the changes are compatible in the new version)

    • or create a provisioning configuration that could be used to reproduce the state of the distribution including the user changes;

  • exporting the provisioning configuration of the current state of the distribution with the goal to reproduce it later at another location.

The tool includes a command-line interface and a public API. There is also a Maven plugin that allows provisioning a distribution according to the provided configuration.

Releases of the command line tool are available on the Galleon releases page.

Download and unzip the release zip and add the bin dir to your system path. Use galleon.sh or galleon.bat to launch the tool.

2. Feature-packs

Feature-pack represents a released unit of software (project, product, component, etc) that can be installed or uninstalled using Galleon tools. Feature-packs are ZIP archives that are normally deployed by the feature-pack producers to artifact repositories (such as Maven) where they can be discovered and consumed by users using Galleon tools.

Feature-pack contains:

  • metadata describing

    • dependencies on other feature-packs;

    • the default configuration(s) of the product the feature-pack represents;

    • the package set that should be installed by default;

  • (optional) a set of packages (that represent various filesystem content);

  • (optional) a set of configuration feature specs (used to define and/or tune parts of the product configuration);

  • (optional) various resources required to properly assemble and configure the product;

  • (optional) product-specific provisioning plug-ins.

Feature-pack may declare dependencies on other feature-packs. Before a feature-pack is installed the tool will make sure its dependencies are satisifed (by installing the missing ones).

2.1. Feature-pack archive structure

Feature-packs are distributed as ZIP archives with the following root entries:

feature-pack.zip
|- configs/
|- feature_groups/
|- features/
|- layers/
|- packages/
|- plugins/
|- resources/
`- feature-pack.xml

Where

  • configs - optional directory containing predefined installation configurations;

  • feature_groups - optional directory containing feature group descriptions;

  • features - optional directory containing feature specs (units of configuration);

  • layers - optional directory containing predefined configuration layers that can be used to create custom installation configurations;

  • packages - optional directory containing packages (units of filesystem content);

  • resources - optional directory containing various resources needed to properly assemble and configure the product;

  • plugins - optional directory containing product-specific provisioning plug-ins (note, that alternatively plugin artifacts can also be referenced from feature-pack.xml using their repository coordinates);

  • feature-pack.xml - metadata describing the feature-pack and the default product configuration.

2.2. Feature-pack metadata (feature-pack.xml)

Generally, feature-pack metadata contains the following information:

  • Feature-pack location - string expression that indicates how to resolve the feature-pack artifact from a remote repository and how it can be identified among other feature-packs;

  • (optional) dependencies - dependencies on other feature-packs.

  • (optional) configuration - the default configurations of the product (there could be more than one default configuration);

  • (optional) default packages - names of the packages that are installed by default.

  • (optional) plugins - various provisioning plugins.

  • (optional) system-paths - paths to files that should be protected during upgrades.

Here is an illustration of how it may look like in a feature-pack.xml file:

<feature-pack xmlns="urn:jboss:galleon:feature-pack:3.0"
    location="wildfly-servlet@maven(org.jboss.universe:community-universe):current#14.0.0.Beta2"> (1)
    <dependencies>
        <dependency location="wildfly-core@maven(org.jboss.universe:community-universe):current#6.0.0.Beta1"/> (2)
    </dependencies>
    <config model="standalone" name="standalone.xml"> (3)
        <feature-group name="standalone"/>
        <feature spec="another-feature">
            <param name="p1" value="v1" />
            <param name="p2" value="v2" />
        </feature>
    </config>
    <config model="domain" name="domain.xml">
        <feature-group name="domain"/>
    </config>
    <config model="host" name="host.xml">
        <feature-group name="host"/>
    </config>
    <default-packages> (4)
        <package name="docs"/>
        <package name="modules.all"/>
    </default-packages>
    <plugins> (5)
        <plugin location="org.jboss.galleon.example:galleon-example-plugin:1.0.0.Final"/>
    </plugins>
    <system-paths> (6)
        <system-path path="modules/system/layers/base"/>
    </system-paths>
</feature-pack>
1 Feature-pack location and build info
2 Dependency on another feature-pack
3 Description of the default standalone.xml configuration
4 List of packages that should be installed by default
5 List of provisioning plugins
6 List of protected system paths

2.3. Feature-pack location

Feature-pack location is an expression that is used to resolve the feature-pack artifact from the remote repository and also identify the feature-pack among other feature-packs.

The general and complete feature-pack location format is producer@universe:channel/frequency#build

  • producer - simple name of a feature-pack producer, normally a product or a component name;

  • universe - the universe the producer belongs to (universe is basically a named set of feature-pack producers);

  • channel - source of backward compatible feature-pack builds;

  • frequency - denotes the lowest accepted build quality (e.g. alpha, beta, final, etc) for the feature-pack builds pulled from the channel;

  • build - feature-pack build number or version.

Some of the parts above are or could be optional. For example, a user could add a specific universe as the default one for the distribution (in its provisioning configuration) and then not include it explicitly into feature-pack locations for the feature-packs coming from that universe.

Frequency is, generally, also optional and could be omitted.

Feature-pack producer may configure a default channel, which makes the channel part optional for the feature-packs of that producer.

With the universe and frequency omitted the location becomes producer:channel#build

Here is an example of a full feature-pack location:

wildfly@maven(org.jboss.universe:community-universe):current/beta#17.0.0.Beta1

And a shortened version:

wildfly:current#17.0.0.Beta1

And assuming current is the default channel it becomes

wildfly#17.0.0.Beta1

Galleon CLI tool comes pre-configured with maven(org.jboss.universe:community-universe) as the default universe, which means Galleon CLI users can omit the universe part for wildfly and other feature-pack producers from that universe and also, in general, rely on TAB-completion for feature-pack locations.

Using Galleon CLI

install wildfly@maven(org.jboss.universe:community-universe):current/beta#17.0.0.Beta1

and

install wildfly#17.0.0.Beta1

will result in the exact same distribution. And to install the latest (final) version of wildfly a user can simply type

install wildfly

2.3.1. Channel

Channel represents a source of backward compatible releases. Channels are defined and configured by feature-pack producers.

As an example, a channel could be mapped to a major version of a product. Suppose, there is product productA with development branches 1.x and 2.x and 2.x branch is not backward compatible with 1.x branch. In this case, the producer of productA could define two channels 1 for branch 1.x and 2 for branch 2.x. Then, to install the latest available (final) release of 1.x branch the user would request the tool to install productA:1 and productA:2 for the latest available (final) release on 2.x branch.

2.3.2. Frequency

Frequency is a channel option that indicates the lowest acceptable build quality when the tool is looking for the latest build of the product. Supported frequencies are defined and configured by feature-pack producers. If the user has not provided any frequency, the default is assumed to be the final (or GA) release.

Frequency is used by the provisioning mechanism only when looking for the latest build. I.e. when installing a product for which the user has not specified the version or when looking for updates for the already installed products.

The following is a valid feature-pack location expression: productA:1#1.0.0.Beta2.

Although the frequency is missing, which means it’s equivalent to productA:1/final#1.0.0.Beta2. Installing productA:1#1.0.0.Beta2 will still install 1.0.0.Beta2, because the user has provided the desired version explicitly.

But if the user requests an update to the latest version, the tool will check the frequency and will look for the latest available release that satisfies the frequency. In the example above, the tool will not update the distribution until 1.0.0.Final becomes available, even if 1.0.0.Beta3 becomes available before that.

However, if the user installed the same feature-pack as productA:1/beta#1.0.0.Beta2 and requested an update to the latest version, the tool would also look for the available beta releases and propose 1.0.0.Beta3 if it’s available.

frequency specifies the lowest quality, which mean installing productA:1/beta may actually install 1.0.0.Final if the final release is available.

2.3.3. Feature-pack Maven Artifact Location

It is also possible to use the feature-pack’s Maven artifact coordinates in place of the feature-pack location expression described above. In that case, after the feature-pack artifact has been resolved, its actual Galleon feature-pack location will be used during provisioning and state persistence. E.g.

install org.wildfly:wildfly-galleon-pack:17.0.0.Final

will be equivalent to

install wildfly#17.0.0.Final

3. General provisioning workflow

This is not a precise description of how it happens but a high level overview of the workflow.

  1. The provisioning mechanism determines a set of feature-packs that need to be resolved for the installation

  2. Feature-pack version compatibility is checked

  3. The feature-packs are downloaded from their respective repositories and unpacked in a temporary location

  4. Feature-packs are processed in the order they are specified in the installation provisioning description

    • configuration models and the packages set to be installed is determined for every feature-pack

    • configuration models are merged on-the-fly as soon as they are processed

  5. A staged directory is created

  6. Content from all the feature-pack packages is copied to the staged directory (in the order the feature-packs should be installed)

  7. Feature-pack plugins are invoked

    • The plugins are assumed to generate the configuration files from the provided resolved configuration models and perform other necessary tasks to complete the installation

  8. The provisioned state of the installation is recoded

  9. The installation created in the staged directory is moved to the target installation directory (fully replacing the current one, if it exists)

  10. The temporary directories are deleted

4. Feature-pack packages

A package is a minimal atomic unit of filesystem content that can be included into or excluded from the installation. It could be a set of files and/or provisioning-related resources attached to the package used by the mechanism to provision a piece of filesystem content.

Essentially, a software release (filesystem content-wise) is represented as a set of packages released under a common version.

Package contains:

  • metadata describing the package;

  • (optional) FS content which is copied into the installation when the package is installed;

  • (optional) other provisioning resources that are used during provisioning to generate and/or integrate the content (or what the package represents) properly into the target installation.

Package may declare dependencies on other packages that belong to the same or another feature-pack. Before a package is installed, the tool will make sure all its dependencies are satisifed (which includes automatic installation of the ones that are missing from the installation).

Package is identified by its name. The name must be unique in the scope of the feature-pack the package belongs to.

Packages are not versioned. Only the feature-pack has a version.

4.1. Package directory structure

Packages are stored in the directories (named after the packages) under the feature-pack packages directory.

Package directory contains the following entries:

  • package.xml - the metadata describing the package;

  • (optional) content - directory containing the content of the package which will be copied to the installation when the package is installed;

  • (optional) pm - directory containing various resources needed to properly provision the content of the package.

Here is an illustration of packages entry from a feature-pack archive containing packages p1, p2, p3 and p4:

packages/
|-p1/
| |-content/
| | `-...
| |-pm/
| | `-...
| `-package.xml
|-p2/
| |-content/
| | `-...
| `-package.xml
|-p3/
| |-pm/
| | `-...
| `-package.xml
`-p4/
  `-package.xml

4.2. Package metadata (package.xml)

Package metadata contains the following information:

  • package name;

  • (optional) dependencies - dependencies on other packages from the same and/or other feature-packs;

Here is an illustration of how package.xml might look like:

 <package-spec xmlns="urn:jboss:galleon:package:2.0" name="p1">
    <dependencies>
        <package name="p2"/>
        <package name="p3" optional="true"/>
        <origin name="another-feature-pack">
            <package name="p1"/>
            <package name="p11" optional="true"/>
        </origin>
    </dependencies>
 </package-spec>

Here package p1 declares dependencies on packages p2 and p3 that belong to the same feature-pack as p1 and packages p1 and p11 that belong to another feature-pack referenced by alias another-feature-pack.

4.3. Package dependencies

Package dependency may be required or optional.

Required dependency means that a package cannot be installed unless all its required dependencies are satisfied, i.e. installed. If any required dependency cannot be satisfied (perhaps because a package that happens to be a required dependency has been explicitly excluded from the installation), the provisioning process will fail with an error.

Optional dependency means that the dependency does not have to be satisfied for the package to be installed. For example if package p1 declares an optional dependency on package p2 and p2 is explicitly excluded by the user, p1 will still be installed. An example of an optional dependency could be a package called documentation which declares an optional dependency on package examples. If a user is not interested in examples, the rest of documentation could still be installed.

Package dependencies are also used to determine the effective package set of a feature-pack to be installed described later.

Here is an example of how dependencies are expressed in the XML metadata:

 <package-spec xmlns="urn:jboss:galleon:package:2.0" name="p1">
    <dependencies>
        <package name="p2"/> (1)
        <package name="p3" optional=”true”/> (2)
    </dependencies>
 </package-spec>
1 required dependency on package p2
2 optional dependency on package p3

A package may declare dependency on a package from the same or another feature-pack. During the dependency resolution, at first, the mechanism is trying to resolve the package dependency locally, i.e. in the current feature-pack. If the dependency could not be resolved locally, the mechanism will look for the package dependency in the feature-packs the current feature-pack depends on (in the order the feature-pack dependencies are listed in feature-pack.xml of the current feature-pack). The first found matching package will be used as the resolved dependency. If the package dependency could not be resolved, the mechanism will report an error.

Although a package may declare a dependency on a package from another feature-pack, it cannot specify the version of the feature-pack in the package dependency declaration.

4.3.1. Passive dependencies

An optional dependency may be also marked as passive, e.g.

 <package-spec xmlns="urn:jboss:galleon:package:2.0" name="p1">
    <dependencies>
        <package name="p2" optional=”true” passive="true"/>
    </dependencies>
 </package-spec>

Or, in fact, the example above can be re-written without optional="true" since only optional dependencies can be passive, i.e.

 <package-spec xmlns="urn:jboss:galleon:package:2.0" name="p1">
    <dependencies>
        <package name="p2" passive="true"/>
    </dependencies>
 </package-spec>
A passive dependency on a package is satisified only if all the required dependencies of that package are included into the installation (as the default packages or direct or required dependencies (possibly transitive) of the provisioned configs, layers, feature groups or features).

Passive dependencies affect how the effective package set of a feature-pack is resolved.

4.3.2. Explicit package dependency origin

Feature-pack containing a package with an external dependency must declare an explicit dependency on the feature-pack (specifying its version) the target package of the external dependency belongs to. This feature-pack dependency may also be assigned a name which can later be used as a reference to that feature-pack dependency when declaring dependencies in package.xml file on packages that belong to that feature-pack.

For example, suppose feature-pack fp1 depends on feature-pack fp2 and package fp1:p1 depends on packages fp2:p1 and fp2:p10. The feature-pack.xml of fp1 might look like this:

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
    <dependencies>
        <dependency location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0">
            <origin>fp2-dep</origin>
        </dependency>
    </dependencies>
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>

And the package.xml file of fp1:p1 might look like this:

 <package-spec xmlns="urn:jboss:galleon:package:2.0" name="p1">
    <dependencies>
        <package name="p2" />
        <origin name=”fp2-dep”>
            <package name=”p1” />
            <package name=”p10” />
        </origin>
        <package name="p3" />
    </dependencies>
 </package-spec>

In general, the origin element is optional, but in some cases it helps to specify explicitly the origin of package dependencies.

4.4. Feature-pack default packages

Feature-pack may define a set of default packages. This set of default packages is installed when the user does not provide explicit instructions about which packages from the feature-pack to install.

Default packages are explicitly listed in feature-pack.xml file which is a part of the feature-pack archive. For example:

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <default-packages>
        <package name="package1" />
        <package name="package2" />
    </default-packages>
 </feature-pack>

If this feature-pack is installed without further customizations, package1 and package2 will be installed by default, although the feature-pack above may still contain other packages (not listed as default) that may not get installed.

4.5. Feature-pack non-default packages

Feature-pack may contain packages that are not marked as default in its feature-pack.xml. Non-default packages can be installed either:

  • implicitly, in case a non-default package appears to be a transitive dependency of a default package;

  • explicitly, in case a user explicitly selected a non-default package to be installed.

4.6. Effective package set

This chapter is dedicated to the effective package set of a feature-pack (without dependencies) that is going to be installed, how it is resolved by the mechanism and how it can be adjusted by a user.

4.6.1. Feature-pack original effective package set

Original in the title means not explicitly modified. I.e. the set of packages which is going to be installed when the feature-pack is installed as-is without any customizations from a user.

Generally speaking, the original effective package set of a feature-pack consists of all the default packages of the feature-pack plus all the packages that appear to be direct or transitive dependencies of the default packages, the default configs and layers, feature groups and features those configs consist of.

While the required package dependencies are always included into the effective package set, the inclusion of optional packages can be controlled with one of the policies specified as the value of provisioning option optional-packages: all, none, passive and passive+.

Here is the table illustrating which dependency types are automatically included and which are filtered out form the effective package set under each policy:

Table 1. Optional package inclusion policies

all

passive+

passive

none

required

+

+

+

+

passive (satisfied)

+

+

+

-

passive (unsatisfied)

+

-

-

-

optional

+

+

-

-

4.6.2. Explicit package exclusion

A package may be explicitly excluded from the feature-pack’s effective package set. For example, given the following feature-pack definition (feature-pack.xml):

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <default-packages>
        <package name="p1" />
        <package name="p2" />
    </default-packages>
 </feature-pack>

and assuming that

  • package p1 has an optional dependency on non-default package p11,

  • package p2 has an optional dependency on non-default package p22.

The original effective package set of fp1 includes p1, p11, p2 and p22.

If a user is interested in a subset of the effective package set, in fact, only in package p1, for example, it can be expressed in the provisioning XML configuration file as

 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
         <packages>
             <exclude name="p11"/>
             <exclude name="p2"/>
         </packages>
     </feature-pack>
 </installation>

Packages p11 and p2 are explicitly excluded and package p22 is a non-default package which is not a direct or transitive dependency of the packages to be installed, i.e. p1.

4.6.3. Explicit package inclusion

A package may be explicitly included into the feature-pack’s effective package set. For example, given the following feature-pack definition (feature-pack.xml):

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe:1#1.0.0" >
    <default-packages>
        <package name="p1" />
        <package name="p2" />
    </default-packages>
 </feature-pack>

and assuming that

  • p2 has an optional dependency on non-default package p21,

  • fp1 also contains non-default package p3,

  • p3 has an optional dependency on non-default package p31.

The effective package set of fp1 includes p1, p2 and p21.

A user may explicitly add package p3, exclude p2 and still leave p21 in the effective package set using the following configuration:

 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
         <packages>
             <include name="p3"/>
             <exclude name="p2"/>
             <include name="p21"/>
         </packages>
     </feature-pack>
 </installation>

The effective package set now will consist of p1 (default package), p21 (explicitly included non-default), p3 (explicitly included non-default) and p31 (brought in as a dependency of p3).

If, for example, the user wanted to further cut down the effective set to p21 and p3, the configuration would change to

 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
         <packages>
             <exclude name="p1"/>
             <exclude name="p2"/>
             <include name="p21"/>
             <include name="p3"/>
             <exclude name="p31"/>
         </packages>
     </feature-pack>
 </installation>

5. Feature-pack dependencies

Feature-pack may depend on one or more other feature-packs. Feature-pack dependencies are expressed in feature-pack.xml file. For example:

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <dependencies>
        <dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.1"/>
        <dependency location="fp3@maven(org.jboss.universe:community-universe):1#1.0.2"/>
    </dependencies>
    <default-packages>
        <package name="package1"/>
        <package name="package2"/>
    </default-packages>
 </feature-pack>

In this case feature-pack fp1 depends on feature-packs fp2 and fp3. And if a user requests to install fp1, feature-packs fp2 and fp3 will be installed by the mechanism implicitly as dependencies of fp1.

If we further assume that fp3 depends on feature-pack fp4 and fp2 and fp4 don’t have any further dependencies. The effective package set of the distribution provisioned from fp1 will consist of:

  • the effective package set of fp1;

  • the effective package set of fp2;

  • the effective package set of fp3;

  • the effective package set of fp4.

fp2 and fp3 are called direct dependencies of fp1, while fp4 is called a transitive dependency of fp1 and a direct dependency of fp3.

5.1. Customizing the effective package set of a dependency

As illustrated in the example above, the effective package set of the dependency contributes to the effective package set of the distribution. The feature-pack declaring the dependency, though, is allowed to customize the effective package set of the dependency (the package set it inherits) using the already mentioned in previous chapters include and exclude XML elements in its feature-pack.xml. For example:

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <dependencies>
        <dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0">
            <packages>
                <exclude name="p1"/>
                <exclude name="p2"/>
                <include name="p3"/>
                <include name="p4"/>
            </packages>
        </dependency>
    </dependencies>
    <default-packages>
        <package name="p1"/>
        <package name="p2"/>
    </default-packages>
 </feature-pack>

Element packages under dependency in feature-pack.xml has exactly the same structure as element packages in the provisioning XML configuration file, mentioned earlier in the chaper describing the effective package set of a feature-pack.

Now the effective package set of a distribution provisioned from fp1 becomes:

  • fp1 packages p1 and p2;

    • plus their dependencies on non-default packages (if any);

  • the effective package set of fp2;

    • minus packages p1 and p2 from fp2 and their dependencies on other packages;

    • plus packages p3 and p4 from fp2 and their dependencies on other packages.

in case fp2 in its turn depended on other feature-packs then the effective package sets of those feature-packs (possibly customized using include/exclude in the corresponding dependency declaration in the feature-pack.xml of fp2).

5.2. Disabling package inheritance from a dependency

The effective package set of a dependency is inherited by the feature-pack declaring the dependency. However, it is possible to declare the dependency without inheriting its default effective package set and simply pick the desired packages explicitly under dependency element (in other words, explicitly define the desired effective package set of the dependency).

Optional boolean attribute inherit of element packages controls whether package inheritance is enabled or disabled. In case the attribute is not explicitly specified, its value is assumed to be true. Here is an example of a dependency with disabled package inheritance:

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <dependencies>
        <dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0">
            <packages inherit=”false”>
                <exclude name="p1"/>
                <exclude name="p2"/>
                <include name="p3"/>
                <include name="p4"/>
            </packages>
        </dependency>
    </dependencies>
    <default-packages>
        <package name="p1"/>
        <package name="p2"/>
    </default-packages>
 </feature-pack>
The exclude elements may at first look redundant, given that package inheritance was disabled in the first place. However, it’s important to keep in mind that when a package is included, by default, all its dependencies are also included. exclude elements can be used to exclude certain transitive dependencies of the included dependencies.

Now the effective package set of the distribution provisioned from fp1 becomes:

  • fp1 packages p1 and p2;

    • plus their dependencies on non-default packages (if any);

  • fp2 packages p3 and p4;

    • plus their dependencies on non-default packages minus packages p1 and p2 from fp2 and their dependencies on other packages.

5.3. Merging package sets of dependencies

Suppose feature-pack fp1 depends on feature-packs fp2 and fp3. Both fp2 and fp3 depend on their own custom package sets of feature-pack fp4. When fp1 is installed, the effective package set of fp4 will be a merge of the custom package sets of fp4 defined in fp2 and fp3 as their dependencies.

For example:

Feature-pack fp1
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <dependencies>
        <dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0"/>
        <dependency location="fp3@maven(org.jboss.universe:community-universe):2#2.0.0"/>
    </dependencies>
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>
Feature-pack fp2
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0" >
    <dependencies>
        <dependency location="fp4@maven(org.jboss.universe:community-universe):2#2.0.0">
            <packages>
                <exclude name="p1"/>
                <exclude name="p3"/>
            </packages>
        </dependency>
    </dependencies>
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>
Feature-pack fp3
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp3@maven(org.jboss.universe:community-universe):2#2.0.0" >
    <dependencies>
        <dependency location="fp4@maven(org.jboss.universe:community-universe):2#2.0.0">
            <packages inherit=”false”>
                <!-- assume fp4 also contains non-default package p4 -->
                <include name="p4"/>
            </packages>
        </dependency>
    </dependencies>
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>
Feature-pack fp4
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp4@maven(org.jboss.universe:community-universe):2#2.0.0" >
    <default-packages>
        <package name="p1"/>
        <package name="p2"/>
        <package name="p3"/>
    </default-packages>
 </feature-pack>

A distribution provisioned from fp1 without further customizations will include:

  • fp1:p1 and its dependencies;

  • fp2:p1 and its dependencies;

  • fp3:p1 and its dependencies;

  • fp4:p2, fp4:p4 and their dependencies.

6. Feature-pack transitive dependencies

Suppose there is feature-pack fp1 that depends on fp2 and fp2 in its turn depends on fp3. In this case, fp2 is a direct dependency of fp1 while fp3 is a transitive dependency of fp1 and a direct dependency of fp2.

Transitive dependencies are the dependencies of the dependencies.

6.1. Customizing package set of a transitive dependency

Let’s suppose we have the following two feature-packs:

Feature-pack fp1
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
     <dependencies>
         <dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0">
             <packages inherit="false"> (1)
                 <include name="p3"/>
                 <include name="p4"/>
                 <exclude name="p5"/>
             </packages>
         </dependency>
     </dependencies>
     <default-packages>
         <package name="p1"/>
     </default-packages>
 </feature-pack>
1 Let’s assume fp2 also contains packages p4, p5 among others.
Feature-pack fp2
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0" >
     <default-packages>
         <package name="p1"/>
         <package name="p2"/>
         <package name="p3"/>
     </default-packages>
 </feature-pack>

If we provision a distribution from fp1 like this

Distribution provisioning configuration
 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>

its effective package set will include:

  • fp1:p1 plus its dependencies;

  • p3 and p4 from fp2 plus their dependencies excluding p5.

The provisioning mechanism will not install the default configuration of fp2 but its customized version defined by fp1, in other words a subset of fp2 that fp1 needs.

Now if we provision our distribution as

 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <feature-pack location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0"/>
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>

its effective package set will become:

  • fp1:p1 plus its dependencies;

  • p1, p2, p3 and p4 from fp2 plus their dependencies (not excluding p5).

The provisioning mechanism will install the default configuration of fp2 plus what fp1 needs on top of it.
feature-pack element appearing in the provisioning configuration under installation always points to the default configuration of the feature-pack.

Now let’s suppose we want to add another package from fp2 to our distribution but we want to start from the customized fp2 configuration defined by fp1. One way of achieving that would be

 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <feature-pack location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0">
         <packages inherit="false">
             <include name="p3"/>
             <include name="p4"/>
             <exclude name="p5"/>
             <include name="p6"/> (1)
         </packages>
     </feature-pack>
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>
1 the package we want to add to our distribution

That works but is not very practical. We basically copied the customizations of fp2 from fp1 to our provisioning configuration. If the configuration was more sophisticated it wouldn’t be that easy. Here is an easier alternative:

 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <transitive>
         <feature-pack location="fp2@maven(org.jboss.universe:community-universe)"> (1)
             <packages>
                 <include name="p6"/>
             </packages>
         </feature-pack>
     </transitive>
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>
1 Note, although we could provide the full version of fp2 here, we chose not to, the mechanism will resolve it to the version specified in feature-pack.xml of fp1
By including feature-pack element under transitive we indicate to the provisioning mechanism that the feature-pack we are about to customize appears on a dependency branch of another feature-pack installed in this configuration directly and that we want to adjust the configuration defined by the feature-pack that depends on it instead of the configuration defined in its feature-pack.xml.

7. Dependency version convergence

This chapter describes how Galleon picks the version of a dependency to install when multiple versions of that dependency appear on the installation’s dependency tree.

The first rule is: versions specified in the provisioning configuration of the installation, e.g. provisioning.xml, for direct or transitive feature-pack dependencies, represent the user’s choice and are always installed, even if the dependency hierarchy of the installation includes other versions of those feature-packs.

Suppose we have these feature-packs

Feature-pack fp1
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <dependencies>
        <dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0"/>
    </dependencies>
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>
Feature-pack fp2
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0" >
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>

Feature-pack fp1 declares a dependency on version 2.0.0 of fp2. Even if later backward compatible versions of fp2 are available, provisioning a distribution from fp1 will get fp2 version 2.0.0 installed. If we still want to upgrade fp2 there are two ways to do that

1) install the desired version of fp2 directly as

 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <feature-pack location="fp2@maven(org.jboss.universe:community-universe):2#2.0.1"/>
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>

2) use transitive element to override the version of fp2 specified in feature-pack.xml of fp1

 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <transitive>
         <feature-pack location="fp2@maven(org.jboss.universe:community-universe):2#2.0.1"/>
     </transitive>
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>

The advantage of specifying the version in the transitive dependency is that it will override only the version of fp2 w/o affecting its customizations (if any) applied to fp2 by fp1. While installing the new version directly will install the default configuration of fp2.

Feature-pack versions that appear higher in the feature-pack dependency hierarchy (i.e. closer to the root in the provisioning configuration) override the versions that appear further down in the dependency hierarchy, no matter whether they are higher or lower in comparison.

7.1. Version convergence of dependency branches

It is possible to run into a version conflict when feature-packs on different dependency branches delcare dependencies on different versions of the same feature-pack. Here is an example

Feature-pack fp1
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <dependencies>
        <dependency location="fp3@maven(org.jboss.universe:community-universe):1#1.2.0"/>
    </dependencies>
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>
Feature-pack fp2
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0" >
    <dependencies>
        <dependency location="fp3@maven(org.jboss.universe:community-universe):1#1.3.0"/>
    </dependencies>
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>
Provisioning configuration
 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
     <feature-pack location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>

In this case, Galleon will pick version 1.2.0 of fp3 simply because it was processed first as the dependency of fp1.

By default Galleon will pick the first processed feature-pack version even if other feature-packs of the installation depend on a newer compatible version of the feature-pack from the same channel.
This behaviour may change in the future in favor of picking the latest compatible version of the feature-pack.
In the example above both fp1 and fp2 depend on the same channel of fp3. If they depended on different channels of fp3, the provisioning would fail because different channels represent different compatibilty streams.

The user can also resolve this kind of version conflict by either installing fp3 directly or specifying its desired version in the transitive element of the installation. E.g.

 <installation xmlns="urn:jboss:galleon:provisioning:2.0">
     <transitive>
         <feature-pack location="fp3@maven(org.jboss.universe:community-universe):1#1.4.0"/>
     </transitive>
     <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
     <feature-pack location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0"/>
 </installation>

7.2. Disabling version convergence

There is a provisioning property called version-convergence which can be set to fail to disable the dependency version convergence that happens when merging dependency branches.

Even if version-convergence is set to fail, feature-pack versions that appear higher in the feature-pack dependency hierarchy (i.e. closer to the root in the provisioning configuration) will still override the versions that appear further down in the dependency hierarchy, no matter whether they are higher or lower in comparison.

8. Generic configuration model

In addition to provisioning various filesystem content as packages, the mechanism also allows generation of the configuration files for the target installation taking into account the customizations applied by the user to the feature-pack defaults.

Feature-pack may include predefined configurations for the installation. They are stored in feature-pack’s configs directory. Every configuration is described in an XML file and in a simple (and perhaps the most common) case, every configuration will represent a specific configuration file in the provisioned installation.

Feature-pack metadata (feature-pack.xml) may define which of the predefined configurations should be provisioned by default by referencing them using config elements .

Installation configuration is described using a generic configuration model. The generic configuration model is based on an abstract schema that describes configurable units and relationships between them. The model allows a user to manipulate the confguration in a generic way by adding to and/or removing parts from it, and/or overwriting some parameter values. The responsibilities of the core provisioning mechanism with regards to the configuration are:

  • resolve the final installation configuration model taking into account the customizations applied to the pre-defined in feature-pack.xml default configuration;

  • make sure the resolved configuration model is valid by:

    • verifying that all the required parameter values are set;

    • checking the referential integrity of the resolved configuration model (i.e. in case certain configuration units imply presence of certain other configuration units);

    • making sure that the capability requirements in the resolved configuration are satisfied;

    • and that packages required by the configuration model are included into the installation;

  • present the units of the resolved configuration to the provisioning plugins in the order the configuration model was populated but also respecting the dependencies of those units.

The generic provisioning mechanism itself does not generate the final configuration files. As indicated above, it only resolves the effective generic configuration model for the provisioned installation and makes sure it does not violate various constraints it might have. It is the responsibility of product-specific provisioning plugins to generate the final configuration file(s) from the already resolved and validated generic configuration model.

8.1. Features

Minimal configurable unit of the generic configuration model is called a feature. A feature is described by a feature specification (or feature spec further in the text). A feature spec describes how a feature can be configured, while a feature is a specific configuration of a feature spec.

Feature specs are identified by their names that must be unique in the scope of the feature-pack.

A feature spec describes

Feature specs are stored in spec.xml files in the directories named after the feature spec names under feature-pack’s features directory. For example

features/
|-feature1/
| `-spec.xml
`-feature2/
  `-spec.xml

8.1.1. Feature ID

A feature may have an identifier (feature id further in the text) which is used to locate a specific feature in the configuration model. Whether a feature has an ID or not is specified in the feature spec.

A feature ID is essential to be able to customize the configuration of a specific feature.

Feature ID consists of a feature spec name plus one or more feature parameters. Feature parameters that are a part of the feature ID include feature-id="true" attribute in their descriptions (and cannot be nillable). For example

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature1">
   <params>
     <param name="name" feature-id="true"/>
     <param name="b" default="bb"/>
     <param name="c" nillable="true"/>
   </params>
 </feature-spec>

Now if a config includes multiple features of feature spec feature1, they could be refered to by feature1:name=unique_name expression, where unique_name is the value of parameter name of the target feature.

Feature ID parameters cannot change values during config customizations. If a user wants to have a different value for an ID parameter of a certain feature, the existing feature has to be excluded from the config and a new feature with the desired ID parameter value has to be added in.

Here is an example of a feature spec with multiple feature ID parameters:

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature2">
   <params>
     <param name="p1" feature-id="true"/>
     <param name="p2" feature-id="true"/>
     <param name="p3" nillable="true"/>
   </params>
 </feature-spec>

An ID of a feature of this spec will look like feature2:p1=p1_value,p2=p2_value.

The order of the ID parameters in the feature ID string is not significant.

8.1.2. Feature parameters

Feature parameters are described in feature specs. A parameter is identified by its name (which must be unique in the scope of the feature spec) and may have the following attributes:

  • required string name - the name of the parameter;

  • optional boolean feature-id - indicating whether the parameter is a part of the feature ID (if not present, the default is assumed to be false);

  • optional boolean nillable - indicating whether the parameter allows null as the value in the resolved config (if not present, the default is assumed to be false);

  • optional string default - indicates which value should be used for the parameter, if the parameter was not explicitly initialized in the configuration (if not present, the default is assumed to be null);

  • optional string type - type of the parameter (if not present, the default is assumed to be String).

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature1">
   <params>
     <param name="a" feature-id="true"/> (1)
     <param name="b" default="bb"/> (2)
     <param name="c" nillable="true"/> (3)
     <param name="d"/> (4)
   </params>
 </feature-spec>
1 feature ID parameter, cannot be null and must be explicitly initialized in the configuration
2 parameter will be initialized to bb unless explicitly set to a different value by the user;
3 has no default and may be left uninitialized in the configuration;
4 parameter must be explicitly initialized by the user.

8.1.3. Features in configuration

Here is an example of how features can be used in a configuration.

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
   <config name="main">
     <feature spec="feature1">
       <param name="a" value="a1"/>
       <param name="b" value="b1"/>
       <param name="d" value="d1"/>
     </feature>
     <feature spec="feature1">
       <param name="a" value="a2"/>
       <param name="d" value="d2"/>
     </feature>
     <feature spec="feature1">
       <param name="a" value="a3"/>
       <param name="c" value="c3"/>
       <param name="d" value="d3"/>
     </feature>
   </config>
 </feature-pack>

In this example, the config element describes the default configuration which will be generated when fp1 is installed (unless it is explicitly customized by the user), which includes three features of the same spec. When the final configuration is generated, the features will be processed in the order they appear in the config element.

8.1.4. Feature references

There are cases when a value range of a parameter of one feature spec is defined by a set of existing in the configuration model values of an ID parameter of another feature spec. In other words, a feature spec may declare certain parameters as references to ID parameters of another feature spec. (In a relational database, this would be a foreign key reference).

In a feature spec a simple feature reference would look like this

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP"/>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p"/>
   </params>
 </feature-spec>

Attribute feature of element ref contains the name of the referenced feature-spec. Note that we have not provided which parameter of featureC references the ID parameter of featureP. This example also demonstrates the default (implicit) reference parameter mapping.

The default reference parameter mapping rule is based on the expectation that the feature spec declaring the reference includes parameters with the names matching the ID parameter names of the referenced feature spec.

So the example above will work if one of the following statements is true:

  1. featureP declares parameter p and it is its only feature-id parameter;

  2. featureP declares parameter name and it is its only feature-id parameter;

  3. featureP declares parameters name and p as its feature-id parameters and has not other feature-id parameters.

Table 2. The complete set of a feature reference declaration attributes
Attribute name Required Default Description

dependency

false

null (current feature-pack or its dependencies)

The feature-pack dependency name the referenced feature spec belongs to.

feature

true

null

The name of the referenced feature spec.

name

false

The value of the feature attribute

Unique feature reference name.

nillable

false

false

Whether a reference is nillable or not.

include

false

false

Whether the referenced feature should automatically be included into the config model if it was not explicitly configured.

Non-default reference parameter mapping

Instead of relying on the default reference parameter mapping rule, it is also possible to map the parameters in the reference declaration explicitly. The example below will correspond to the statement 1. from the example above.

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP">
       <param name="p" maps-to="p"/>
     </ref>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p"/>
   </params>
 </feature-spec>

Now let’s suppose that featureP ID parameter is in fact name but we still want to use parameter p as the reference to featureP.

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP">
       <param name="p" maps-to="name"/>
     </ref>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p"/>
   </params>
 </feature-spec>

If featureP had more than one ID parameter, e.g.

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
   <params>
     <param name="id1" feature-id="true"/>
     <param name="id2" feature-id="true"/>
   </params>
 </feature-spec>

Then the reference parameter mapping in featureC could look like:

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP">
       <param name="p1" maps-to="id1"/>
       <param name="p2" maps-to="id2"/>
     </ref>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p1"/>
     <param name="p2"/>
   </params>
 </feature-spec>
Nillable feature references
Feature reference resolves to null if one of the feature reference parameters is null.
If a reference resolves to null and its not marked as nillable in the feature spec, the provisioning will fail with an error. Here is an example of a nillable reference declaration:
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP" nillable="true">
       <param name="p1" maps-to="id1"/>
       <param name="p2" maps-to="id2"/>
     </ref>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p1" nillable="true"/>
     <param name="p2"/>
   </params>
 </feature-spec>
External feature references

A feature may reference a feature from another feature-pack. The other feature-pack must be a (direct or transitive) dependency of the feature-pack the referencing feature belongs to.

Unless the feature-pack of the referenced feature has not been explicitly specified, the mechanism will navigate the dependency tree of the feature-pack of the referencing feature and the first feature-pack containing a feature spec with the referenced feature spec name will be selected as the target.

Otherwise, the target feature-pack can be specified using dependency attribute of the feature reference declaration. The value of dependency attribute must match the value of origin element of the feature-pack dependency (the referenced feature spec belongs to) declaration in the feature-pack.xml file of the referencing feature spec.

For example, suppose, feature-pack fp1 depends on feature-pack fp2.

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
    <dependencies>
        <dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0">
            <origin>fp2-dep</origin>
        </dependency>
    </dependencies>
 </feature-pack>

fp2 includes feature spec featureP.

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
   <params>
     <param name="p" feature-id="true"/>
   </params>
 </feature-spec>

And fp1 includes feature spec featureC which declares a reference to featureP

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref dependency="fp2-dep" feature="featureP"/>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p"/>
   </params>
 </feature-spec>
It is expected that in most cases dependency attribute of element ref will not have to be used.
Implicit feature reference parameter initialization

Let’s suppose we have a parent-child relationship between two feature specs, e.g.

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
   <params>
     <param name="parentId" feature-id="true"/>
   </params>
 </feature-spec>
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP"/>
   </refs>
   <params>
     <param name="childId" feature-id="true"/>
     <param name="parentId"/>
   </params>
 </feature-spec>

If we were to add features of these specs to a config, it could look like this

 <config name="main">
   <feature spec="featureP">
     <param name="parentId" value="parent1"/>
   </feature>
   <feature spec="featureC">
     <param name="childId" value="child1"/>
     <param name="parentId" value="parent1"/>
   </feature>
 </config>

This approach is very verbose, the value for parentId parameter is set on every feature. There is a more compact way of expressing the same configuration using nesting, e.g.

 <config name="main">
   <feature spec="featureP">
     <param name="parentId" value="parent1"/>
     <feature spec="featureC">
       <param name="childId" value="child1"/>
     </feature>
   </feature>
 </config>

Here, parentId parameter is initialized only once for the parent feature. parentId of the child feature will be implicitly initialized to the value of parentId of the parent.

When a feature is nested, the tool will look in the feature spec of the nested feature for a reference declaration with the name matching the outer feature spec and, if it is found, the tool will resolve the reference parameter mappings and will initialize the parameters of the child feature referencing the parent.

In case the reference name is different from the referenced feature spec name, i.e. it was explicitly set in the reference spec, e.g.

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP" name="parent"/>
   </refs>
   <params>
     <param name="childId" feature-id="true"/>
     <param name="parentId"/>
   </params>
 </feature-spec>

Then the name of the reference has to be explicitly specified when the child feature is nested using the parent-ref attribute, e.g.

 <config name="main">
   <feature spec="featureP">
     <param name="parentId" value="parent1"/>
     <feature spec="featureC" parent-ref="parent">
       <param name="childId" value="child1"/>
     </feature>
   </feature>
 </config>
Implicit inclusion of referenced features into the configuration

It is possible to configure feature references so that when the resolved referenced feature ID is not found in the configuration model, instead of failing with the referential integrity constraint error, implicitly include the referenced feature into the configuration model initializing it with its default values. This is done by simply setting include attribute of the feature reference declaration to true.

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref dependency="fp2-dep" feature="featureP" include="true"/>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p"/>
   </params>
 </feature-spec>
Multiple references to the same feature spec

Suppose a feature needs to declare more than one reference to the same feature spec. For example let’s model a chain using a feature spec called link. link must have an ID parameter, let’s call it id. Then it has to include a parameter to reference the previous link and another parameter to reference the next link in the chain. The following, although looking right from the parameter mapping perspective, will clearly not work

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="link">
   <refs>
     <ref feature="link">
       <param name="prev-id" maps-to="id"/>
     </ref>
     <ref feature="link">
       <param name="next-id" maps-to="id"/>
     </ref>
   </refs>
   <params>
     <param name="id" feature-id="true"/>
     <param name="prev-id" nillable="true"/>
     <param name="next-id" nillable="true"/>
   </params>
 </feature-spec>

Feature references must have a unique name. In this case, both reference names are set to link and the provisioning tool will fail to process this spec. To workaround the error explicit names have to be assigned to the reference declarations, e.g.

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="link">
   <refs>
     <ref name="prev" feature="link">
       <param name="prev-id" maps-to="id"/>
     </ref>
     <ref name="next" feature="link">
       <param name="next-id" maps-to="id"/>
     </ref>
   </refs>
   <params>
     <param name="id" feature-id="true"/>
     <param name="prev-id" nillable="true"/>
     <param name="next-id" nillable="true"/>
   </params>
 </feature-spec>
Processing of features with references

One of the responsibilities of the provisioning tool is to order the features from the resolved configuration model for processing by the provisioning plugins that generate the final installation configuration files. While the general rule is to preserve the order in which the features where added to the configuration model, when feature A references feature B, feature B will get the priority and will be processed by the provisioning plugins before feature A to not break the referential integrity of the generated model (if it is significant for the consuming plugin).

Circular feature references

The provisioning mechanism is capable of identifying circular references (circular reference graphs). It does not throw an error if a circular reference graphs is detected. The responsibility of the provisioning mechanism is to make sure the configuration model is valid and all the referential integrity constraints are satisfied. From this point of view circular references are not illegal.

The issue with circular references is the ordering of the features when configuration model is processed by the product specific plugins that generate the final configuration files. In some cases the order of the features will not be significant but in some cases it will be. So the rule is

When a circular reference graph is identified, the feature that was added to the configuration model first will be processed by the provisioning plugins first, the rest of the features from the graph will be processed respecting the references as usual.

8.1.5. Feature dependencies

While references are a kind of dependencies, they require parameters in the spec of the feature declaring the reference to identify the target. Unlike references, feature dependencies do not use parameters to specify the target. Instead the dependency is declared by specifying the ID of the target feature directly.

Feature spec dependencies

Feature dependencies can be declared in the feature spec and/or on the feature itself. Here is an example of a dependency declaration in the feature spec:

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature1">
   <deps>
     <dep feature-id="feature2:id=123"/>
   </deps>
   <params>
     <param name="name" feature-id="true"/>
   </params>
 </feature-spec>

Now all the features of spec feature1 will depend on the feature with ID feature2:id=123.

Feature config dependencies

And here is how a feature dependency can be declared on a specific feature:

 <feature spec="feature1">
   <deps>
     <dep feature-id="feature3:id=789"/>
   </deps>
   <param name="name" value="abc"/>
 </feature>

Now feature feature1:name=abc depends on feature feature2:id=123 (inherited dependency from the spec) and feature feature3:id=789.

External feature dependencies

It is allowed to delcalre dependencies on features that come from other feature-packs. If the specs of those features come from feature-packs that appear to be dependencies of the feature-pack the feature dependencies are configured in then those feature specs will most probably be located by the mechanism automatically (by navigating the feature-pack dependency tree). The mechanism might need some help resolving the specs of the dependencies only if they belong to a feature-pack that doesn’t appear to be a dependency of the feature-pack where the dependencies are defined or if there are multiple feature specs with the same name in the feature-pack dependency hierarchy and it’s not obvious which one is targeted by the dependency.

the feature spec resolution mechanism will pick the first feature spec with the matching name met while navigating the feature-pack dependency tree.

There is a way though to specify the origin of the feature spec used in the dependency. If feature3 spec was from another feature-pack than feature1 spec then to be precise we could have added the origin of feature3 spec to the dependency declaration. Assuming that the feature-pack feature1 spec belongs to declared a dependecy named fp2 on the feature-pack feature3 spec belongs to, the dependency declaration would look like this:

 <feature spec="feature1">
   <deps>
     <dep feature-id="feature3:id=789" dependency="fp2"/>
   </deps>
   <param name="name" value="abc"/>
 </feature>
Implicit inclusion of feature dependencies

Like references, dependencies also support include attribute. If the dependency is declared with include=true, the target of the dependency will implicitly be included into the configuration unless it is already present. Here is an example of an implicitly included feature dependency:

 <feature spec="feature1">
   <deps>
     <dep feature-id="feature3:id=789" include="true"/>
   </deps>
   <param name="name" value="abc"/>
 </feature>

8.1.6. Feature capabilities

In the actual provisioned installation, the components that are represented as features in the configuration model may provide certain runtime capabilities that other components, also represented as features in the configuration model, may depend upon. There are two reasons why this may be important when resolving the configuration model for the installation to be provisioned:

  1. to make sure the configuration is consistent in a sense that the runtime requirements of its components are satisfied;

  2. to order the features in the configuration model for processing by the provisioning plugins based on their dependencies and runtime requirements.

Capabilities are represented as strings with a dot serving as a word separator. Here is an example of a feature spec providing a capability:

 <feature-spec name="interface" xmlns="urn:jboss:galleon:feature-spec:1.0">
   <provides>
     <capability name="org.wildfly.network.interface"/>
   </provides>
   <params>
     <param name="name" feature-id="true"/>
     <param name="inet-address"/>
   </params>
 </feature-spec>

And here is a feature spec that requires the capability provided above

 <feature-spec name="socket-binding" xmlns="urn:jboss:galleon:feature-spec:1.0">
   <requires>
     <capability name="org.wildfly.network.interface"/>
   </requires>
   <params>
     <param name="name" feature-id="true"/>
     <param name="port"/>
   </params>
 </feature-spec>
In the examples above the capabilities were configured using constant values. This type of a capability is called a static capability. As a consequence, all the features of spec interface will provide the same capability org.wildfly.network.interface. And all the features of spec socket-binding will require the same capabality org.wildfly.network.interface.
Dynamic capabilities

It is also possible, however, to provide and/or require a capability that depends on the parameters of a specific feature. Dynamic capabilities are following the same dot-separated string format but include feature parameter names prefixed with $ character. The examples above could be enhanced with dynamic capabilities as

 <feature-spec name="interface" xmlns="urn:jboss:galleon:feature-spec:1.0">
   <provides>
     <capability name="org.wildfly.network.interface.$name"/>
   </provides>
   <params>
     <param name="name" feature-id="true"/>
     <param name="inet-address" nillable="true"/>
   </params>
 </feature-spec>
 <feature-spec name="socket-binding" xmlns="urn:jboss:galleon:feature-spec:1.0">
   <requires>
     <capability name="org.wildfly.network.interface.$interface"/>
   </requires>
   <params>
     <param name="name" feature-id="true"/>
     <param name="interface"/>
     <param name="port" nillable="true"/>
   </params>
 </feature-spec>

Let’s see how it will look like in an actual configuration

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
   <config name="main">
     <feature spec="interface">
       <param name="name" value="public"/>
     </feature>
     <feature spec="interface">
       <param name="name" value="secure"/>
     </feature>
     <feature spec="socket-binding">
       <param name="name" value="http"/>
       <param name="interface" value="public"/>
     </feature>
     <feature spec="socket-binding">
       <param name="name" value="https"/>
       <param name="interface" value="secure"/>
     </feature>
   </config>
 </feature-pack>

In the example above feature interface:name=public provides capability org.wildfly.network.interface.public which is required by feature socket-binding:name=http. And feature interface:name=secure provides capability org.wildfly.network.interface.secure which is required by feature socket-binding:name=https.

More than one parameter could be used in a capability name. The parameters may appear in any part of the name, not necessarily at the end as in the example. The only rule is to use dot as a separator for the parameters and the static parts of the name.
Optional capabilities

In the example above, parameter interface in both feature specs is not nillable, which means the capability will always be provided by interface and always be required socket-binding. There could be cases though, when a parameter referenced from the capability name is nillable. In fact, if the parameter is null, the capability name will fail to resolve and provisioning will fail. However, dynamic capabilities can be marked as optional. Optional dynamic capability will be provided (or required) only if its name could be resolved (i.e. all the parameters referenced were not null). Here is the example illustrating optional capabilities in a feature spec:

 <feature-spec name="specA" xmlns="urn:jboss:galleon:feature-spec:1.0">
   <provides>
     <capability name="$b" optional="true"/>
   </provides>
   <requires>
     <capability name="$c" optional="true"/>
   </requires>
   <params>
     <param name="id" feature-id="true"/>
     <param name="b" nillable="true"/>
     <param name="c" nillable="true"/>
   </params>
 </feature-spec>

8.1.7. Feature package dependencies

Feature specs representing configurable components of the installation may include dependencies on feature-pack packages that contain certain binary content (e.g. JAR files) of those installation components. So that, when a feature is included into configuration, the packages the feature will require at runtime will automatically be added to the list of the installed packages.

Package dependencies are configured under packages element of the feature spec which is equivalent to the dependencies element of the package spec metadata. Here is an example

 <feature-spec name="feature1" xmlns="urn:jboss:galleon:feature-spec:1.0">
   <params>
     <param name="id" feature-id="true"/>
   </params>
   <packages>
     <package name="p1"/>
     <package name="p2" optional="true"/>
     <origin name="another-feature-pack">
       <package name="p2"/>
       <package name="p3" optional="true"/>
     </origin>
   </packages>
 </feature-spec>

In this case, any feature of spec feature1 will have:

  • a required dependency on package p1;

  • an optional dependency on package p2;

  • a required dependency on package p2 from the feature-pack dependency refered to as another-feature-pack;

  • an optional dependency on package p3 from the feature-pack dependency refered to as another-feature-pack.

8.1.8. Feature annotations

Feature specs may include a list of annotations. The provisioning mechanism includes a few pre-defined annotations. Product-specific annotations are also supported, they are simply parsed and attached to feature specs and are available to the provisioning plugins for processing. Here is an example of an annotated feature spec:

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature1">
   <annotation name="name1">
     <elem name="elem1" value="value1"/>
   </annotation>
   <annotation name="name2">
     <elem name="elem1" value="value1"/>
     <elem name="elem1" value="value1"/>
   </annotation>
   <params>
     <param name="id" feature-id="true"/>
   </params>
 </feature-spec>

8.2. Feature groups

A feature spec represents a minimal configuration unit. When a configuration model reaches a certain level of complexity though, using and manipulating features to define the final configuration may become impractical. Feature groups allow to group a set of features that represent a certain part of the configuration together and then include them all into the final configuration as a group. For example

 <feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
   <feature spec="feature1">
     <param name="id" value="a1"/>
     <feature spec="feature2">
       <param name="id" value="b1"/>
     </feature>
   </feature>
   <feature spec="feature3">
     <param name="id" value="c1"/>
   </feature>
 </feature-group-spec>
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
   <config name="main">
     <feature-group name="group1"/>
   </config>
 </feature-pack>

First, we defined a feature group named group1 which includes three features.

The name of the group must be unique in the scope of the feature-pack.

Feature groups are saved in the feature-pack’s feature_groups directory in XML files named after the feature groups (group1.xml in this example).

Then in the default configuration of the feature-pack we simply included group1, which is equivalent to including the mentioned three features into the config directly.

Besides features, feature groups may also include other feature groups. Continuing the example above:

 <feature-group-spec name="group2" xmlns="urn:jboss:galleon:feature-group:1.0">
   <feature-group name="group1"/>
   <feature spec="feature4">
     <param name="id" value="d1"/>
   </feature>
 </feature-group-spec>
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
   <config name="main">
     <feature-group name="group2"/>
   </config>
 </feature-pack>

The final configuration will now include all the four features.

The order of the features in the resolved configuration will reflect the order in which the features were included into the configuration but also respecting the feature references and the dependencies, i.e.
  1. feature1:id=a1

  2. feature2:id=b1

  3. feature3:id=c1

  4. feature4:id=d1

8.2.1. Including customized feature groups

When a feature group is included (into another feature group or a config element of a feature-pack configuration) the set of its features can be customized. There are two main kinds of customizations that are allowed when including a feature group:

When a feature group is included into another feature group or a config element, the list of its direct entries (features and feature groups) defined by the feature group spec cannot be extended by applying customizations. There is a way though to extend the feature set of the included feature group indirectly.

All the feature group customizations are expressed in the body of feature-group XML element.

Overwriting parameters of features from a feature group

The configuration of a feature can be customized by adding include element with feature-id attribute targeting its ID to the body of the feature-group element. E.g. suppose this is our feature spec:

<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature1">
  <params>
    <param name="a" feature-id="true"/>
    <param name="b" default="bb"/>
    <param name="c" nillable="true"/>
    <param name="d"/>
  </params>
</feature-spec>

This is our feature group spec:

<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
  <feature spec="feature1">
    <param name="a" value="a1"/>
    <param name="c" value="group1"/>
    <param name="d" value="group1"/>
  </feature>
</feature-group-spec>

And this is our config:

<config name="main">
  <feature-group name="group1">
    <include feature-id="feature1:a=a1">
      <param name="d" value="config"/>
    </include>
  </feature-group>
</config>

The resolved configuration will consist of one feature with the following configuration

Feature spec a b c d

feature1

a1

bb

group1

config

Let’s now suppose that we have two feature specs with a parent-child relationship

<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
  <params>
    <param name="parent" feature-id="true"/>
  </params>
</feature-spec>
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
  <refs>
    <ref feature="featureP">
  </refs>
  <params>
    <param name="parent" feature-id="true"/>
    <param name="child" feature-id="true"/>
    <param name="a"/>
    <param name="b"/>
  </params>
</feature-spec>

The group is defined as

<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
  <feature spec="featureP">
    <param name="parent" value="p1"/>
    <feature spec="featureC">
      <param name="child" value="c1"/>
      <param name="a" value="group1"/>
      <param name="b" value="group1"/>
    </feature>
  </feature>
</feature-group-spec>

And we want to customize the child feature when including group1 into the config.

<config name="main">
  <feature-group name="group1">
    <include feature-id="featureC:parent=p1,child=c1">
      <param name="b" value="config"/>
    </include>
  </feature-group>
</config>

The resolved configuration will contain two features:

Feature spec parent

featureP

p1

Feature spec child a b

featureC

p1

c1

group1

Excluding features from a group by IDs

When a feature group is included into another group or a config, certain features can be excluded from the included feature set by simply specifying their IDs.

Suppose, we have defined the following group:

<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">

  <feature spec="feature1">
    <param name="id" value="a1"/>
  </feature>
  <feature spec="feature1">
    <param name="id" value="a2"/>
  </feature>
  <feature spec="feature2">
    <param name="id" value="b1"/>
  </feature>
  <feature spec="feature2">
    <param name="id" value="b2"/>
  </feature>

</feature-group-spec>

Here is how feature1:id=a1 and feature2:id=b1 can be excluded when group1 is added a configuration:

<config name="main">
  <feature-group name="group1">
    <exclude feature-id="feature1:id=a1"/>
    <exclude feature-id="feature2:id=b1"/>
  </feature-group>
</config>

The config will include feature1:id=a2 and feature2:id=b2.

Excluding features from a group by specs

When a feature group is included into another group or a config, all the features of a specific feature spec can be excluded from the included feature set by simply specifying the feature spec.

Suppose, we have the following group spec:

<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">

  <feature spec="feature1">
    <param name="id" value="a1"/>
  </feature>
  <feature spec="feature1">
    <param name="id" value="a2"/>
  </feature>
  <feature spec="feature2">
    <param name="id" value="b1"/>
  </feature>
  <feature spec="feature2">
    <param name="id" value="b2"/>
  </feature>

</feature-group-spec>

Here is how all the feature of spec feature1 can be excluded:

<config name="main">
  <feature-group name="group1">
    <exclude spec="feature1"/>
  </feature-group>
</config>

The config will include feature2:id=b1 and feature2:id=b2.

Picking features from a group by IDs

When a feature group is included into another feature group or a config, by default all the features it contains are included into the configuration. It is possible though to pick which ones exactly should be included.

Suppose, we have the following group spec:

<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">

  <feature spec="feature1">
    <param name="id" value="a1"/>
  </feature>
  <feature spec="feature1">
    <param name="id" value="a2"/>
  </feature>
  <feature spec="feature2">
    <param name="id" value="b1"/>
  </feature>
  <feature spec="feature2">
    <param name="id" value="b2"/>
  </feature>

</feature-group-spec>

Here is how feature1:id=a1 and feature2:id=b1 can be picked into the configuration:

<config name="main">
  <feature-group name="group1" inherit-features="false">
    <include feature-id="feature1:id=a1"/>
    <include feature-id="feature2:id=b1"/>
  </feature-group>
</config>
inherit-features attribute indicates whether the whole feature set of the group should be included into the config or not. If this attribute is not specified, its value is assumed to be true.

Then include elements are picking the features that need to be included into the configuration.

The config will include feature1:id=a1 and feature2:id=b1.

include elements can also be used to pick features from the excluded feature specs. The config below is equivalent to the config above.
<config name="main">
  <feature-group name="group1" inherit-features="true">
    <exclude spec="feature1"/>
    <exclude spec="feature2"/>
    <include feature-id="feature1:id=a1"/>
    <include feature-id="feature2:id=b1"/>
  </feature-group>
</config>
Including features of specific feature specs from a group

When a feature group is included into another group or a config, by default all the features it contains are added to the configuration. There is a way though to pick features of which feature specs should be included.

Suppose, we have the following group spec:

<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">

  <feature spec="feature1">
    <param name="id" value="a1"/>
  </feature>
  <feature spec="feature1">
    <param name="id" value="a2"/>
  </feature>
  <feature spec="feature2">
    <param name="id" value="b1"/>
  </feature>
  <feature spec="feature2">
    <param name="id" value="b2"/>
  </feature>

</feature-group-spec>

Here is how all the features of spec feature1 can be included into the config:

<config name="main">
  <feature-group name="group1" inherit-features="false">
    <include spec="feature1"/>
  </feature-group>
</config>
inherit-features attribute indicates whether the whole feature set of the group should be included into the config or not. If this attribute is not specified, its value is assumed to be true.

Then include element is specifying the feature spec features of which should be included into the config.

The config will include feature1:id=a1 and feature1:id=a2.

<exclude feature-id="xxx"/> elements can be used to exclude certain features from the feature set of the included feature spec.
Extending feature groups by including features indirectly

While the list of the feature group spec enrties (features and feature groups) is fixed and cannot be extended, new features and feature groups can be added as children of the features that have already been included into the feature group. Let’s edit the example from the previous paragraph to demonstrate that. The feature specs will remain the same.

<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
  <params>
    <param name="parent" feature-id="true"/>
  </params>
</feature-spec>
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
  <refs>
    <ref feature="featureP">
  </refs>
  <params>
    <param name="parent" feature-id="true"/>
    <param name="child" feature-id="true"/>
    <param name="a"/>
    <param name="b"/>
  </params>
</feature-spec>

The group definition will now include only parent feature

<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
  <feature spec="featureP">
    <param name="parent" value="p1"/>
  </feature>
</feature-group-spec>

And now we will include the child feature as a configuration customization of the parent feature.

<config name="main">
  <feature-group name="group1">
    <include feature-id="featureP:parent=p1">
      <feature spec="featureC">
        <param name="child" value="c1"/>
        <param name="a" value="config"/>
        <param name="b" value="config"/>
      </feature>
    </include>
  </feature-group>
</config>

The resolved configuration will contain both features:

Feature spec parent

featureP

p1

Feature spec parent child a b

featureC

p1

c1

config

config

8.2.2. Including features and feature groups from other feature-packs

Feature groups, as well as config elements in feature-pack.xml, may include features and feature groups from other feature-packs. If those feature-packs appear to be dependencies (direct or transitive) of the feature-pack that uses their feature specs and groups in its configuration, the mechanism will most probably be able to resolve the origins of those feature specs and groups by navigating the feature-pack dependency tree.

However, if there are multiple feature specs or feature groups with the same name in the feature-pack dependency hierarchy, it may become confusing which feature spec or feature group was meant as the target. In this case, the origin of those feature specs and feature groups can be specified with element origin and its attribute 'name' referencing the corresponding feature-pack dependency declared in the feature-pack.xml. For example

<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">

  <feature spec="feature1">
    <param name="id" value="a1"/>
  </feature>

  <origin name="another-feature-pack">
    <feature-group name="group2"/>
    <feature spec="feature2">
      <param name="id" value="b1"/>
    </feature>
  </origin>

  <feature-group name="group3"/>

  <origin name="another-feature-pack">
    <feature-group name="group3"/>
  </origin>

</feature-group-spec>

In this case, the order of the features in the resolved feature group will be

  1. feature1:id=a1 from the local feature-pack;

  2. features from group2 from another-feature-pack;

  3. feature2:id=b1 from another-feature-pack;

  4. features from group3 from the local feature-pack;

  5. features from group3 from another-feature-pack.

8.2.3. Nesting feature groups under features

It was mentioned in an earlier chapter that a feature may nest other features that reference it. It is also possible to nest a feature group under a feature with the condition that all the features included directly into the definition of the feature group reference the same parent feature.

For example, suppose we have a parent feature spec featureP and child feature specs featureA and featureB:

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
   <params>
     <param name="parent" feature-id="true"/>
   </params>
 </feature-spec>
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureA">
   <refs>
     <ref feature="featureP"/>
   </refs>
   <params>
     <param name="parent" feature-id="true"/>
     <param name="a" feature-id="true"/>
   </params>
 </feature-spec>
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureB">
   <refs>
     <ref feature="featureP"/>
   </refs>
   <params>
     <param name="parent" feature-id="true"/>
     <param name="b" feature-id="true"/>
   </params>
 </feature-spec>

Now let’s suppose that there is a group which includes features of featureA and featureB specs.

<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">

  <feature spec="featureA">
    <param name="a" value="a1"/>
  </feature>
  <feature spec="featureB">
    <param name="id" value="b1"/>
  </feature>

</feature-group-spec>

This group can be nested under any instance of featureP and parameter parent of the features in the group will implicitly be initialized to the value of parameter parent of the outer featureP instance.

<config name="main">
  <feature spec="featureP">
    <param name="parent" value="p1"/>
    <feature-group name="group1"/>
  </feature>
  <feature spec="featureP">
    <param name="parent" value="p2"/>
    <feature-group name="group1"/>
  </feature>
</config>

The resulting config will include:

  1. featureP:parent=p1;

  2. featureP:parent=p2;

  3. featureA:parent=p1,a=a1;

  4. featureA:parent=p2,a=a1;

  5. featureB:parent=p1,b=b1;

  6. featureB:parent=p2,b=b1.

8.2.4. Merging feature groups

There could be a situation when the same feature group is brought into the config as a dependency of a few other feature groups. Which means its basic feature set is included into the final configuration multiple times but, taking into account possible customizations, each time it might be slightly different.

In that case the feature configurations will be merged. The features that are included later in the config will overwrite the common parameters of the corresponding features included earlier. But they will not completely replace the feature configurations that were added earlier.

For example, suppose we have these feature specs:

 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureA">
   <params>
     <param name="name" feature-id="true"/>
     <param name="p1" default="feature-spec"/>
     <param name="p2" default="feature-spec"/>
     <param name="p3" default="feature-spec"/>
   </params>
 </feature-spec>
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureB">
   <params>
     <param name="name" feature-id="true"/>
     <param name="p1" default="feature-spec"/>
     <param name="p2" default="feature-spec"/>
     <param name="p3" default="feature-spec"/>
   </params>
 </feature-spec>

and these feature groups

<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">

  <feature spec="featureA">
    <param name="name" value="a1"/>
    <param name="p1" value="group1"/>
    <param name="p2" value="group1"/>
    <param name="p3" value="group1"/>
  </feature>
  <feature spec="featureA">
    <param name="name" value="a2"/>
  </feature>
  <feature spec="featureA">
    <param name="name" value="a3"/>
  </feature>
  <feature spec="featureB">
    <param name="name" value="b1"/>
    <param name="p1" value="gorup1"/>
    <param name="p2" value="group1"/>
    <param name="p3" value="group1"/>
  </feature>
  <feature spec="featureB">
    <param name="name" value="b2"/>
  </feature>

</feature-group-spec>
<feature-group-spec name="group2" xmlns="urn:jboss:galleon:feature-group:1.0">

  <feature-group name="group1">
    <include feature-id="featureA:name="a1">
      <param name="p1" value="group2"/>
      <param name="p2" value="group2"/>
    </feature>
    <exclude feature-id="featureA:name=a3"/>
    <include feature-id="featureB:name="b1">
      <param name="p2" value="group2"/>
    </feature>
    <exclude feature-id="featureB:name=b2"/>
  </feature-group>

</feature-group-spec>
<feature-group-spec name="group3" xmlns="urn:jboss:galleon:feature-group:1.0">

  <feature-group name="group1">
    <include feature-id="featureA:name="a1">
      <param name="p1" value="group3"/>
    </feature>
    <exclude feature-id="featureA:name=a2"/>
    <include feature-id="featureB:name="b1">
      <param name="p3" value="group3"/>
    </feature>
    <exclude feature-id="featureB:name=b2"/>
  </feature-group>

</feature-group-spec>

Now this configuration

<config name="main">
  <feature-group name="group2"/>
  <feature-group name="group3"/>
</config>

will contain

Feature spec name p1 p2 p3

featureA

a1

group3

group2

group1

featureA

a2

feature-spec

feature-spec

feature-spec

featureA

a3

feature-spec

feature-spec

feature-spec

featureB

b1

group1

group2

group3

8.3. Layers

A layer is meant to represent a certain configuration flavor that can be used on its own or in combination with other layers to produce the final configuration.

The idea behind layers is to predefine certain technology or some other purpose specific complete configurations (that can be used individually or in combination) and expose them as a multichoice to users composing their desired configuration.

For example, let’s suppose we are provisioning an application server that supports multiple technologies such as EJB, Servlet, Messaging, etc. Those technologies could be viewed as components that make up the complete server but also, possibly, as a user’s choice at installation time, in case the user is actually interested only in a subset of those or perhaps simply one, or something that is not included into the default set.

Layers are defined in feature-pack archive’s layers directory. A layer is associated with a name but also, as configuration models, can be associated with a model. If a layer is associated with a model, its definition in the feature-pack archive will appear in layers/config_model/layer_name/layer-spec.xml file, otherwise it will end up in layers/layer_name/layer-spec.xml.

Layers may depend on other layers. If a configuration includes a layer that depends on another layer, that other layer will be included (unless explicitly excluded by the user) into the configuration as well (prior to the layer declaring the dependency on it).

While layers may be associated with both configuration model and a name, they are always referenced in configuration by simple name. The reason for that is that a layer can be referenced only from a configuration model or another layer and, ultimately, it still goes down to the configuration model that includes the layers. So it is the configuration model that determines which model to use for the layers it includes.

8.3.1. Layers vs feature groups

Layers and feature groups have the following in common:

  • both are meant to define a certain (specialized) part of the final configuration;

  • both may define package dependencies.

But they also have quite a few significant differences.

Origin

The content of a feature group (including its package dependencies, if any) is fully defined in a single file - the feature group spec XML. And so, a feature group has a specific origin - the feature-pack containing the definition of the feature group.

Layers, on the other hand, are a product of merging layer specs with the same identity (configuration model + layer name combination) from all the feature-packs that make up the installation. From this perspective, layers are closer to configuration models than feature groups. And so, a layer might not have a single origin.

Dependencies

Feature groups don’t really have the notion of dependencies on other feature groups. A feature group may include other feature groups (their content) into its body.

A layer may define dependencies on other layers, which is not the same as including content of those layers into the layer declaring the dependency. The content of layers is merged directly into the configuration model which includes the layers.

Exclusion from configuration

There is no way to exclude feature groups that have been earlier included into the configuration. When a feature group is added to a configuration, its content (features) is merged immediately into the configuration model. In a way, feature groups dissolve in the configuration and there is no way to identify the set of features previously forming the group with the goal to exclude them altogether from the configuration.

Layers, on the other hand, can be excluded from the configuration. When a configuration is resolved, the complete set of layers it includes is determined and then merged into the configuration. A user may provide instructions though to filter certain (or all the) layers out of the configuration.

Nesting

Feature groups can be nested under a feature which would serve as a parent feature for all the features included into the nested group directly and initialize the corresponding ID parameters of all the features contained in the group.

Layers can’t be nested under a feature. They are meant to define a complete configuration or a part of it starting from the very top of it.

8.3.2. Layer spec

A layer spec is defined in layer-spec.xml file which, for the most part, content-wise is identical to a feature-group spec except it allows to configure dependencies on other layers. Here is an example

<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
    <dependencies>
        <layer name="layerB"/> (1)
        <layer name="layerC" optional="true"/> (2)
    </dependencies>

    <!-- various features and feature groups -->
    <feature spec="specA">
        <param name="id" value="1"/>
        <param name="p1" value="value"/>
    </feature>
    <feature-group name="groupA"/>

    <packages>
        <package name="packageA"/> (3)
        <package name="packageB" optional="true"/> (4)
    </packages>
</layer-spec>
1 required dependency on layerB (layerA can’t be installed unless layerB has been installed)
2 optional dependency on layerC (layerC will be installed when layerA is installed but if layerC has been excluded by the user, layerA will still be installed)
3 required dependency on packageA (layerA can’t be installed unless packageA has been installed)
4 optional dependency on packageB (packageB will be installed when layerA is installed but if packageB has been excluded by the user, layerA will still be installed)

8.3.3. Effective layer spec

In the simplest case, when only one feature-pack among all of the feature-packs that make up the installation defines a layer with a specific identity in the corresponding layer-spec.xml, whatever is defined in that layer-spec.xml is the effective layer spec in the installation.

However, in case an installation includes multiple feature-packs that happen to define a layer with the same identity (model and layer name combination) then the effective layer spec with that identity will be the result of merging all the layer specs from all the feature-packs that make up the installation into one. Merging happens in the order the feature-packs are installed and follow the same principle used for merging configuration models.

For example, let’s supposed we have three feature-packs: fpA, fpB and fpC and fpB depends on fpA. Every one of those feature-packs defines layer1.

fpA layer1
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
    <feature spec="specA">
        <param name="id" value="1"/>
        <param name="p1" value="fpA"/>
        <param name="p2" value="fpA"/>
        <param name="p3" value="fpA"/>
    </feature>
    <packages>
        <package name="package-fpA"/>
    </packages>
</layer-spec>
fpB layer1
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
    <feature spec="specA">
        <param name="id" value="1"/>
        <param name="p2" value="fpB"/>
        <param name="p3" value="fpB"/>
    </feature>
    <packages>
        <package name="package-fpB"/>
    </packages>
</layer-spec>
fpC layer1
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
    <feature spec="specA">
        <param name="id" value="1"/>
        <param name="p3" value="fpC"/>
    </feature>
    <packages>
        <package name="package-fpC"/>
    </packages>
</layer-spec>

Now if we provision an installation using the feature-packs above as

Provisioning configuration
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
    <feature-pack location="fpB@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/> (1)
    <feature-pack location="fpC@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
</installation>
1 fpB installs fpA as its transitive dependency

The effective layer spec of layerA will be resolved as

Effective layer1 spec
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
    <feature spec="specA">
        <param name="id" value="1"/>
        <param name="p1" value="fpA"/>
        <param name="p2" value="fpB"/>
        <param name="p3" value="fpC"/>
    </feature>
    <packages>
        <package name="package-fpA"/>
        <package name="package-fpB"/>
        <package name="package-fpC"/>
    </packages>
</layer-spec>
There won’t actually be an XML file generated for the effective layer spec. The XML above is used only for illustration of the effective layer content and its dependencies.

As in case of configuration model merging, feature-packs that appear higher in the feature-pack dependency hierarchy are allowed to use include and/or exclude elements in their layer specs to include and/or exclude features from the corresponding layers inherited from their feature-pack dependencies. In our example above, include and/or exclude elements could be used in layer1 of fpB to manipulate the content of layer1 inherited from fpA. E.g.

fpB layer1
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
    <exclude spec="specA"/>
    <feature spec="specA">
        <param name="id" value="1"/>
        <param name="p2" value="fpB"/>
        <param name="p3" value="fpB"/>
    </feature>
    <packages>
        <package name="package-fpB"/>
    </packages>
</layer-spec>

With the rest of the configs unchanged the effective layer1 spec will become

Effective layer1 spec
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
    <feature spec="specA">
        <param name="id" value="1"/>
        <param name="p2" value="fpB"/>
        <param name="p3" value="fpC"/>
    </feature>
    <packages>
        <package name="package-fpA"/>
        <package name="package-fpB"/>
        <package name="package-fpC"/>
    </packages>
</layer-spec>

In case of fpC which doesn’t declare any dependency on neither fpA nor fpB, using include and/or exclude in its layer1 spec won’t make any sense because other layer1 specs are not 'visible' from fpC.

8.3.4. Including layers into configuration models

Layers are included into configuration defined using config element under element layers, e.g.

<config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
    <layers>
        <include name="layer1"/>
        <include name="layer2"/>
    </layers>
    <!-- the rest of the configuration -->
</config>

Let’s suppose the configuration above belongs to a feature-pack prod1. And prod1 also predefined another layer - layer3, which is not included into the default configuration model1:name1. Here is how layer3 can be added to the final configuration by a user:

<installation xmlns="urn:jboss:galleon:provisioning:2.0">
    <feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
    <config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
        <layers>
            <include name="layer3"/>
        </layers>
        <!-- the rest of the configuration -->
    </config>
</installation>

The resulting model1:name1 configuration now will include layer1, layer2 and layer3 and they will be included into the configuration in exactly that order.

The statement above is valid only if the mentioned layers don’t depend on each other and/or other layers.

8.3.5. Excluding layers from configuration models

Layers that have been included into the configuration can later be excluded from it. The example above demonstrated how to include a layer into the configuration, here is an example of how a layer can be excluded:

<installation xmlns="urn:jboss:galleon:provisioning:2.0">
    <feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
    <config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
        <layers>
            <exclude name="layer2"/>
            <include name="layer3"/>
        </layers>
        <!-- the rest of the configuration -->
    </config>
</installation>

Assuming feature-pack prod1 included layer1 and layer2 into its model1:name1 configuration (as in the previous example), the resulting model1:name1 configuration will include only layer1 and layer3 (and their dependencies if any).

An attempt to exclude a layer that would not have otherwise been installed will result in a provisioning error. The error, however, can be suppressed by adding provisioning option ignore-not-excluded-layers.

8.3.6. Disabling inheritance of layers

If at some point it is necessary to reset the configuration in terms of layers it consists of and possibly re-define the configuration explicitly, it can be done like this

<installation xmlns="urn:jboss:galleon:provisioning:2.0">
    <feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
    <config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
        <layers inherit="false">
            <include name="layer3"/>
        </layers>
        <!-- the rest of the configuration -->
    </config>
</installation>

inherit="false" attribute indicates to the provisioning mechanism to not inherit any layers for the configuration from any of the feature-packs included up to that point. The resulting model1:name1 configuration will include only layer3 (plus its dependencies) even if prod1 included more layers into model1:name1.

8.3.7. Adjusting layer configuration

Once layers have been included into the configuration, the set of features, as well as packages, they brought in can be manipulated, i.e. configuration of some or all of those features can be modified or completely excluded.

Here is an example. Let’s suppose prod1 feature-pack defines layer1 as

<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layer1">
    <feature spec="specA">
        <param name="id" value="1"/>
    </feature>
    <feature spec="specA">
        <param name="id" value="2"/>
    </feature>
    <feature spec="specB">
        <param name="id" value="1"/>
    </feature>
    <feature spec="specB">
        <param name="id" value="2"/>
    </feature>
    <packages>
        <package name="package1"/>
        <package name="package2" optional="true"/>
        <package name="package3"/>
    </packages>
</layer-spec>

The user wants to include this layer into its installation but also adjust its configuration. It could look like this

<installation xmlns="urn:jboss:galleon:provisioning:2.0">
    <feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
        <packages>
            <exclude name="package2"/> (1)
        </packages>
    </feature-pack>
    <config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
        <layers>
            <include name="layer1"/>
        </layers>
        <exclude feature-id="specA:id=2"/> (2)
        <exclude spec="specB"/> (3)
        <feature spec="specB">
            <param name="id" value="3"/>
        </feature>
    </config>
</installation>
1 package2 layer1 depends on is excluded from the installation
2 specA:id=2 inherited from layer1 is excluded from the configuration
3 All the features of specB inherited from layer1 are excluded from the configuration

The resulting installation will consist of:

  • model1:name1 configuration including features:

    • specA:id=1

    • specB:id=3

  • package1 plus its dependencies, if any;

  • package3 plus its dependencies, if any.

8.3.8. Merging configurations with layers

Layers are merged into configuration at the point where they are included into it with include element. It is important to keep that in mind.

Let’s consider the following example. Suppose prod1 feature-pack defines this configuration:

<config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
    <layers>
        <include name="layer1"/>
        <include name="layer2"/>
    </layers>
    <!-- the rest of the configuration -->
</config>

prod2 feature-pack depends on prod1 and defines this configuration:

<config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
    <layers>
        <include name="layer2"/>
        <include name="layer3"/>
    </layers>
    <!-- the rest of the configuration -->
</config>

When prod2 is installed, layer2 will be included into model1:name1 twice. Which may or may not create a confusion. First of all, in the given example, all the features added to model1:name in prod1 are inherited by model1:name1 in prod2, meaning model1:name1 in prod2 does not start empty. layer1 and layer2 have already been added to model1:name1 in prod1. Including layer2 into model1:name1 in prod2 does not make sense any more unless model1:name1 in prod1 has excluded and/or modified some feature configurations inherited from layer2 and in prod2 we want the original version of layer2 configuration.

Whether including the same layer more than once into the same configuration creates a problem or not depends on the case. It’s important to keep in mind that every include means another merge of the layer.

If the content of the layer has not been adjusted in the configuration, the subsequent merge of the same layer will not result in any visible difference unless the layer includes features that have no identity. If a layer includes features that have no identity, there will be as many copies of those features in the configuration as the number of times the layer has been included into the configuration.

While the example above can easily be adjusted in case the inclusion of layer2 actually is redundant by simply removing it from the list of layers in prod2, there could be situations where it’s more difficult to avoid multiple inclusions of the same layer. For example building up the example above, let’s assume that every one of layer1, layer2 and layer3 depends on layer called base.

In that case, base will be included once into model1:name1 in prod1 (despite the fact that both layer1 and layer2 depend on base, the provisioning mechanism will recognize that base is a common dependency of those layers and include it only once into model1:name1 in prod1). But later, processing model1:name in prod2, it will include base again as a dependency of layer3.

THIS CAN CHANGE. The mechanism can recognize that base has already been included and avoid including it again. The only possible issue is that if layer3 really expects the original base configuration and the already included base has been somehow modified in between.

9. Provisioned installation configuration

9.1. Configuration model attributes

Every configuration must be associated with at least one of the following attributes:

  • name - name of the configuration;

  • model - name of the configuration model.

name and model attributes serve as the identity of the configuration. They are essential when customizing and merging configurations.

If a configuration is associated only with a name (and no model) then only the name will be used as the identity of the configuration.

If a configuration is associated with a name and a model then the combination of the name and the model will be used as the identity of the configuration.

Feature-pack may include predefined configurations in its configs directory whose structure can be described as

configs/
|- model1/
| |- name1/
| |  `- config.xml
| | ...
| |- nameN/
| |  `- config.xml
| `- model.xml
| ...
|- modelM/
| |- name1/
| |  `- config.xml
| | ...
| |- nameN/
| |  `- config.xml
| `- model.xml
|- name1/
|  `-config.xml
| ...
`- nameN/
   `-config.xml

If a configuration is associated with a name but not a model then its definition will be located in configs/config_name/config.xml and start with the following root element:

<config xmlns="urn:jboss:galleon:config:1.0" name="config_name">
    <!-- skipped content -->
</config>

If a configuration is associated only with a model then its definition will located in configs/config_model/model.xml and start with the following root element:

<config xmlns="urn:jboss:galleon:config:1.0" model="config_model">
    <!-- skipped content -->
</config>

If a configuration is associated with both model and a name its definition will be located in configs/model_name/config_name/config.xml and start with the following root element:

<config xmlns="urn:jboss:galleon:config:1.0" model="model_name" name="config_name">
    <!-- skipped content -->
</config>

Predefined configuration models can be referenced from feature-pack.xml file and customized (manipulated) in the provisioning configuration of the installation (which is also an XML file) using config elements. Every config element will include the corresponding name and possibly model attributes to specify the identity of the configuration it is targeting.

Every config element in feature-pack.xml or installation provisioning configuration triggers installation of the configuration it is targeting.

That means, when a feature-pack is installed, by default all the configurations referenced from its feature-pack.xml are installed. Users may explicitly specify though which configurations should the final distribution include and customize those and/or provide their own custom configurations in the provisioning configuration of the installation.

Here is an example of feature-pack.xml with config elements:

<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0">

  <config name="config1">
    <!-- named configuration -->
  </config>

  <config model="model1" name="config1">
    <!-- named configuration of model1 -->
  </config>

</feature-pack>

9.2. Excluding default configs from the installation

The simplest way to exclude configs from the installation is

<installation xmlns="urn:jboss:galleon:provisioning:1.0">
    <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">

        <default-configs inherit="false"/>

    </feature-pack>
</installation>

inherit="false" attribute indicates that none of the configs should be included into the distribution by default. If the attribute is not present, its value is assumed to be true.

feature-pack element in the example above could as well appear under dependecies element of feature-pack.xml. Meaning the XML type of these elements are equivalent - they both describe a customized feature-pack. The examples below will be showing only feature-pack element.

The example above excludes all the configs, if the goal however is to exclude onyl a specific one, it can be done by providing the identity of the config using exclude element. For example, if a configuration was associated with a name but not any model then it would look like this:

<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
    <default-configs>
        <exclude name="config1"/>
    </default-configs>
</feature-pack>

And if the configuration was associated with a name and a model, both of them will have to be specified, e.g.

<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
    <default-configs>
        <exclude name="config1" model="model1"/>
    </default-configs>
</feature-pack>

In case there are multiple named configs that are associated with the same model, e.g.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">

  <config model="model1" name="config1">
    <!-- config body -->
  </config>
  <config model="model1" name="config2">
    <!-- config body -->
  </config>

  <config model="model2" name="config1">
    <!-- config body -->
  </config>
  <config model="model2" name="config2">
    <!-- config body -->
  </config>

</feature-pack>

They can be excluded altogether by specifying the model name, e.g.

<installation xmlns="urn:jboss:galleon:provisioning:1.0">
    <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
        <default-configs>
            <exclude model="model1"/>
        </default-configs>
    </feature-pack>
</installation>

This installation will include configs model2:config1 and model2:config2.

9.3. Picking default configs into the installation

There are two scenarios when including a configuration could be necessary:

  1. when the configuration was excluded with <exclude model="model_name"/>;

  2. when inhertance of the default configurations was disabled with <default-configs inherit="false">.

The first one of course assumes that the configuration is associated with both name and model. It could look like this:

<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
    <default-configs>
        <exclude model="model1"/>
        <include name="config1" model="model1"/>
    </default-configs>
</feature-pack>

The example above excludes all the model1 configurations except config1.

Here is an example for the second scenario

<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
    <default-configs inherit="false">
        <include name="config1"/>
        <include name="config1" model="model1"/>
    </default-configs>
</feature-pack>

The example above picks only config1 and model1:config1 from all the default configurations to be included into the distribution.

It is also possible to include configurations of a specific model, e.g.

<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
    <default-configs inherit="false">
        <include model="model1"/>
    </default-configs>
</feature-pack>

In this case, all the default configurations of model1 will be included into the distribution.

9.4. Configuration model merges

Configuration model merging is a way to integrate various products in the same installation. Lets suppose we want to add new product to an existing installation. Besides adding its filesystem content to the installation, normally, the configuration files of the existing installation will have to be adjusted to include the configuration of the product to be added.

In the provisioning terms, this scenarios can be described as:

  • there is a feature-pack (or a few) of the main installation (defining its FS content as well as the configurations);

  • there is the other product’s feature-pack defining its filesystem content and its default configuration that should be added to the main installation as part of its integration.

How exactly the configuration of the new product is integrated into the existing installation will depend on every specific case but there are a few basic ways it can happen:

  1. the product comes with its own standalone configuration which will not affect the existing installation configuration in any way;

  2. the product configuration will have to be added to the existing configuration of the installation;

  3. a combination of the two above: the standalone configuration and a piece of the configuration that needs to be added to the existing configuration of the installation.

The first one is simple: we just need to create two separate configurations: one for the main installation and one for the product we integrate.

In the second case, we need to actually merge the configurations from the existing installation and the feature-pack which represents the new product into a single confguration.

The third one effectively means that we’ve got multiple configuration models some of which should be merged and some should remain standalone. The tricky part is to identify which one is which. This is where the configuration name and model attributes are useful.

The provisioned installation may contain only one configuration model of a specific identity (which is the product of config name and model attribute values).

When the provisioning mechanism analysing the installation being provisioned discovers multiple configuration models with the same identity, it does not throw an error but merges the configuration models into a single one (which may still result in an error, of course, if the resulting model contains unsatisfied requirements).

9.4.1. Named (name-only) configurations

The simplest way to provide an identity for a configuration is to give it a name. E.g.

fp1: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <config name="config1"/>
</feature-pack>
fp1: configs/config1/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="config1">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="a" value="fp1"/>
    <param name="b" value="fp1"/>
  </feature>
  <feature spec="feature2">
    <param name="id" value="1"/>
  </feature>
</config>

Now if another feature-pack provides a configuration with the same name, e.g.

fp2: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <config name="config1"/>
</feature-pack>
fp2: configs/config1/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="config1">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="b" value="fp2"/>
  </feature>
  <feature spec="feature3">
    <param name="id" value="1"/>
  </feature>
</config>

And we include both of these feature-packs into the same installation

Installation provisioning configuration
<installation xmlns="urn:jboss:galleon:provisioning:1.0">
  <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
  <feature-pack location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
</installation>

The provisioned config1 will be the result of merging config1 from fp2 into config1 from fp1.

Which config overwrites which (assuming they contain common parts) depends on the order in which the feature-packs are listed under installation element.

Here is the content of the provisioned config1:

Feature spec origin Feature spec id a b

fp1@maven(org.jboss.universe:community-universe)1#1.0.0.Final

feature1

1

fp1

fp1

Feature spec origin Feature spec id

fp1@maven(org.jboss.universe:community-universe)1#1.0.0.Final

feature2

1

Feature spec origin Feature spec id b

fp2@maven(org.jboss.universe:community-universe)1#1.0.0.Final

feature1

1

fp2

Feature spec origin Feature spec id

fp2@maven(org.jboss.universe:community-universe)1#1.0.0.Final

feature3

1

The features of feature1 spec are not merged although they appear to have the same ID. The reason is that fp2 does not declare the dependency on fp1 and its feature specs are not available in fp2 configurations. So this example assumes that both fp1 and fp2 include feature spec feature1.

Here is how feature-pack.xml of fp2 had to be written so that feature1 spec could be re-used in fp2 configuration:

fp2: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp2@maven(org.jboss.universe:community-universe)1#1.0.0.Final">
  <dependencies>
    <dependency location="fp1@maven(org.jboss.universe:community-universe)1#1.0.0.Final"/>
  </dependencies>
  <config name="config1"/>
</feature-pack>

With this feature-pack configuration the resulting config1 will include the following features:

Feature spec origin Feature spec id a b

fp1@maven(org.jboss.universe:community-universe)1#1.0.0.Final

feature1

1

fp1

fp2

Feature spec origin Feature spec id

fp1@maven(org.jboss.universe:community-universe)1#1.0.0.Final

feature2

1

Feature spec origin Feature spec id

fp2@maven(org.jboss.universe:community-universe)1#1.0.0.Final

feature3

1

9.4.2. Named model configurations

There are a couple of reasons for adding model attribute to the configuration identity. One of them is to define the scope for values of attribute name. In this sense, a model could be thought of as a namespace. E.g.

fp1: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <config name="main" model="modelA"/>
  <config name="main" model="modelB"/>
</feature-pack>
fp1: configs/modelA/main/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="a" value="fp1-modelA"/>
     <param name="b" value="fp1-modelA"/>
  </feature>
</config>
fp1: configs/modelB/main/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelB">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="a" value="fp1-modelB"/>
    <param name="b" value="fp1-modelB"/>
  </feature>
</config>
fp2: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <dependencies>
    <dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
  </dependencies>
  <config name="main" model="modelA"/>
  <config name="main" model="modelB"/>
</feature-pack>
fp2: configs/modelA/main/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="b" value="fp2-modelA"/>
  </feature>
</config>
fp2: configs/modelB/main/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelB">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="b" value="fp2-modelB"/>
  </feature>
</config>

Installing these two feature-packs (fp2 following fp1) will result in the following two configurations:

Table 3. modelA:main
Feature spec origin Feature spec id a b

fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final

feature1

1

fp1-modelA

fp2-modelA

Table 4. modelB:main
Feature spec origin Feature spec id a b

fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final

feature1

1

fp1-modelB

fp2-modelB

9.4.3. Model-only configurations

Model-only configurations are associated only with a model by means of model attribute of config element but are not associated with any name specific name.

The idea behind the model-only configurations is to be able to define the base for a configuration of a specific model that every final configuration of that model should include. Model-only configurations are always added into the configuration before the named configurations, i.e. named configurations will be added on top of the model-only ones and will overwrite them.

At the end, a provisioned installation will only contain the named configurations but not the model-only ones. Model-only configurations are always merged into the named configurations.
A model-only configuration is merged into all the named configurations of the installation associated with the same model as the model-only configuration.

Let’s look at an example. Suppose we have two feature-packs: fp1 and fp2.

fp1 is defined as

fp1: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <config name="main" model="modelB"/>
</feature-pack>

And includes the following configurations

fp1: configs/modelA/model.xml
<config xmlns="urn:jboss:galleon:config:1.0" model="modelA">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="a" value="fp1-modelA"/>
    <param name="b" value="fp1-modelA"/>
  </feature>
</config>
fp1: configs/modelB/main/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelB">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="b" value="fp1-modelB"/>
  </feature>
</config>

fp2 is defined as

fp2: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <dependencies>
    <dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
  </dependencies>
  <config name="main" model="modelA"/>
  <config name="test" model="modelA"/>
  <config name="test" model="modelB"/>
</feature-pack>

And includes the following configurations

fp2: configs/modelA/main/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="b" value="fp2-modelA"/>
  </feature>
</config>
fp2: configs/modelA/test/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="test" model="modelA">
  <feature spec="feature2">
    <param name="id" value="1"/>
    <param name="a" value="fp2-modelA"/>
    <param name="b" value="fp2-modelA"/>
  </feature>
</config>
fp2: configs/modelB/model.xml
<config xmlns="urn:jboss:galleon:config:1.0" model="modelB">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="a" value="fp2-modelB"/>
    <param name="b" value="fp2-modelB"/>
  </feature>
</config>
fp2: configs/modelB/test/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="test" model="modelB">
  <feature spec="feature2">
    <param name="id" value="1"/>
    <param name="a" value="fp2-modelB"/>
    <param name="b" value="fp2-modelB"/>
  </feature>
</config>

Installing these two feature-packs will result in the following configurations:

Table 5. modelA:main
Feature spec origin Feature spec id a b

fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final

feature1

1

fp1-modelA

fp2-modelA

Table 6. modelA:test
Feature spec origin Feature spec id a b

fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final

feature1

1

fp1-modelA

fp1-modelA

fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final

feature2

1

fp2-modelA

fp2-modelA

Table 7. modelB:main
Feature spec origin Feature spec id a b

fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final

feature1

1

fp2-modelB

fp1-modelB

Table 8. modelB:test
Feature spec origin Feature spec id a b

fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final

feature1

1

fp2-modelB

fp2-modelB

fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final

feature2

1

fp2-modelB

fp2-modelB

Excluding model-only configurations with exclude element

Normally, model-only configurations are not supposed to be explicitly excluded. If a user excludes all the named configs of a specific model, the model-only configs of that model will simply be ignored by the provisioning mechanism.

Configuration model designers are encouraged to model configurations in a way that model-only configurations represent an essential part of any configuration of that model and its runtime dependencies and don’t need to be excluded explicitly by users or should be excluded in exceptional cases.

In a previous chapter it was described how the default configurations could be excluded from the provisioned installation by specifying their model name. Here is the relevant part of the configuration:

<installation xmlns="urn:jboss:galleon:provisioning:1.0">
    <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
        <default-configs>
            <exclude model="model1"/>
        </default-configs>
    </feature-pack>
</installation>

exclude element above does not affect the model-only configurations. It affects only the named configurations associated with the specified model.

Let’s imagine we have the following feature-pack fp1

fp1: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <config name="main" model="modelA"/>
</feature-pack>

with the following configurations

fp1: configs/modelA/model.xml
<config xmlns="urn:jboss:galleon:config:1.0" model="modelA">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="a" value="fp1-modelA"/>
    <param name="b" value="fp1-modelA"/>
    <param name="c" value="fp1-modelA"/>
  </feature>
</config>
fp1: configs/modelA/main/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="b" value="fp1-modelA-main"/>
  </feature>
</config>

And feature-pack fp2

fp2: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <dependencies>
    <dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
  </dependencies>
  <config name="main" model="modelA"/>
</feature-pack>

With the following configuration

fp2: configs/modelA/main/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="c" value="fp2-modelA-main"/>
  </feature>
</config>

If we install these feature-packs the resulting configuration will contain

Table 9. modelA:main
Feature spec origin Feature spec id a b c

fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final

feature1

1

fp1-modelA

fp1-modelA-main

fp2-modelA-main

If we exclude modelA like it was shown in the previous example in the declaration of the dependency on fp1, i.e.

fp2: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <dependencies>
    <dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
      <default-configs>
        <exclude model="modelA"/>
      </default-configs>
    </dependency>
  </dependencies>
  <config name="main" model="modelA"/>
</feature-pack>

If we install fp2 now, the provisioned configuration will contain

Table 10. modelA:main
Feature spec origin Feature spec id a b c

fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final

feature1

1

fp1-modelA

fp1-modelA

fp2-modelA-main

The model-only configuration from fp1 is still effective because fp1 is installed as a dependency of fp2 and its modelA configuration is considered being essential for any named configuration of the model. In case it still has to be excluded from the provisioned configuration it can be done by adding named-only-models="false" attribute to exclude element, e.g.

fp2: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <dependencies>
    <dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
      <default-configs>
        <exclude model="modelA" named-only-models="false"/>
      </default-configs>
    </dependency>
  </dependencies>
  <config name="main" model="modelA"/>
</feature-pack>

exclude element above affects both named and model-only configurations of modelA from feature-pack fp1.

named-only-models attribute is optional and if abscent its value is assumed to be true.

The provisioned configuration of fp2 will now contain

Table 11. modelA:main
Feature spec origin Feature spec id c

org.jboss.pm.test:fp1:1.0.0.Final

feature1

1

fp2-modelA-main

Disabling inheritance of model-only configurations

In an earlier chapter it was shown how the default configurations of a feature-pack could be suppressed. Let’s now include a model-only configuration in the example.

fp1: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <config name="main" model="modelA"/>
</feature-pack>
fp1: configs/modelA/model.xml
<config xmlns="urn:jboss:galleon:config:1.0" model="modelA">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="a" value="fp1-modelA"/>
    <param name="b" value="fp1-modelA"/>
    <param name="c" value="fp1-modelA"/>
  </feature>
</config>
fp1: configs/modelA/main/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="b" value="fp1-modelA-main"/>
  </feature>
</config>
fp2: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <dependencies>
    <dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
      <default-configs inherit="false"/> (1)
    </dependency>
  </dependencies>
  <config name="main" model="modelA"/>
</feature-pack>
1 the default configurations from fp1 are going to be ignored
fp2: configs/modelA/main/config.xml
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
  <feature spec="feature1">
    <param name="id" value="1"/>
    <param name="c" value="fp2-modelA-main"/>
  </feature>
</config>

With inherit="false" attribute of default-configs element we indicated that the default configurations of fp1 should not be included into the distribution provisioned from fp2. But it does not affect the model-only configs. So the model-only modelA configuration will still be effective in fp2.

inherit-unnamed-models attributes of default-configs element controls whether the model-only configs are inherited or not. The attribute is optional and if not present, its value is assumed to be true.

Here is an example that disables the inheritance of all the named and model-only configurations:

fp2: feature-pack.xml
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <dependencies>
    <dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
      <default-configs inherit="false" inherit-unnamed-models="false"/>
    </dependency>
  </dependencies>
  <config name="main" model="modelA"/>
</feature-pack>

The installation provisioned from fp2 will include the following configuration

Table 12. modelA:main
Feature spec origin Feature spec id c

fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final

feature1

1

fp2-modelA-main

9.5. Content of config element

Although this chapter is describing config element as a child of feature-pack element, the same applies to the root config element from config.xml and model.xml files.

config element is basically an extended version of feature-group element. Meaning that everything that is allowed in the body of feature-group (which is feature, feature-group and origin elements for explicit dependency origins) is allowed in config element.

Besides that config element supports already mentioned in an earlier chapter the config attributes and props element.

When a config element appears in a feature-pack.xml file or as a child of installation element in the provisioning configuration of the installation, it represents all the configurations with the matching identity from all the feature-packs dependency hierarchy up to the current point merged into one configuration model.

E.g. if feature-pack fp1 depends on feature-pack fp2 which includes configuration model m1 named n1. Element config with attributes model="m1" name="n1" added to fp1 will represent the corresponding configuration from fp2 (unless the configuration inheritance was explicitly disabled in fp1), i.e. the content of configuration m1:n1 from fp2 may be manipulated in config element in fp1 by excluding certain features or overwriting their parameters.

The same applies to config elements under installation element. If installation includes feature-packs fp3 and fp4, both of which include configs m1:n1, config element with attributes model="m1" name="n1" added under the installation element will represent the result of merging configs m1:n1 from feature-packs fp3 and fp4.

9.5.1. Configuration properties

props element allows to attach various properties to the configuration that can be meaningful to the provisioning plugins processing the configuration. E.g.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <config name="main" model="modelA">
    <props>
      <prop name="save-to-file" value="model-a.xml"/>
      <prop name="other" value="thing"/>
    </props>
    <feature spec="feature1">
      <param name="id" value="1"/>
      <param name="a" value="fp1-modelA"/>
    </feature>
  </config>
</feature-pack>

9.5.2. Overwriting configuration properties during inclusion

When a default configuration is included, its properties can be overwritten, e.g.

<installation xmlns="urn:jboss:galleon:provisioning:1.0">
    <feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
        <default-configs>
            <include name="main" model="modelA">
              <props>
                <prop name="save-to-file" value="main-model-a.xml"/>
              </props>
            </include>
        </default-configs>
    </feature-pack>
</installation>

The resolved configuration will include the following properties:

  • save-to-file=main-model-a.xml;

  • other=thing.

9.5.3. Overwriting configuration properties during merging

When the configurations are merged, their properties are also merged. The configuration that is included later into the installation overwrites the properties of the configuration which was added earlier. E.g.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <config model="modelA">
    <props>
      <prop name="save-to-file" value="model-a.xml"/>
      <prop name="other" value="thing"/>
    </props>
    <feature spec="feature1">
      <param name="id" value="1"/>
      <param name="a" value="fp1-modelA"/>
    </feature>
  </config>
</feature-pack>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <dependencies>
    <dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
  </dependencies>
  <config name="main" model="modelA">
    <props>
      <prop name="save-to-file" value="main-model-a.xml"/>
    </props>
    <feature spec="feature1">
      <param name="id" value="1"/>
      <param name="a" value="fp2-modelA"/>
    </feature>
  </config>
</feature-pack>

The resolved configuration modelA:main will contain the following properties:

  • save-to-file=main-model-a.xml;

  • other=thing.

9.6. Configuration package dependencies

config elements may include feature-pack package dependencies. So that when a configuration is included into the installation, the relevant packages required by the configuration are automatically included as well. Package dependencies are configured using the same elements described in the feature-package dependencies. E.g.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
              location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
  <config model="modelA">
    <packages>
     <package name="p1"/>
     <package name="p2" optional="true"/>
    </packages>
  </config>
</feature-pack>

Now every configuration of modelA will depend on and bring into the installation the specified packages.

9.7. Configuration dependencies

When all the configuration models have been resolved by the provisioning mechanism, the plugins attached to the installed feature-packs are invoked to generate the final configuration files. The plugins will see the resolved configurations as a list. Certain configuration models though may depend on other configuration models being generated first. To eliminate the trouble of ordering the configurations according to their dependencies in the plugins, configuration dependencies can be expressed in config elements. E.g.

    <config model="host">
        <config-deps>
            <config-dep id="domain-dep" model="domain"/>
        </config-deps>
    </config>

In the example above all the configurations of model host will appear in the resolved config list after all the configurations of model domain. config-dep id is used to identify the configuration dependencies when the configuration models are merged.

The example above illustrates a dependency on a configuration model. But config-dep may also include name attribute.

9.8. Arranging features in configurations

Resolved configuration models are meant to be further processed by the provisioning plugins that actually generate the final configuration files. A resolved configuration is basically a set of features and properties. Plugins simply iterate through the features in the resolved configuration and generate the corresponding configuration fragments for the installation.

The order in which features appear in the resolved configuration may be significant. By default the order of the features in the resolved configuration reflects the order in which the features were added to the configuration, i.e. the order in which the features appeared in the config element. Although, in case there are dependencies between features, the mechanism will re-order the features according to their dependencies, i.e. if feature F1 depends on feature F2, even if F1 was added to the configuration before F2, in the resolved configuration F2 will appear before F1.

9.8.1. Feature branches

Features in the resolved configuration are actually organized into branches. In the simplest case, there is only one branch for all the features of the configuration.

There are cases though, when a certain set of features has to be handled in a different way than the rest of the features in the same configuration. E.g. there could be a few features that form a circular dependency. The mechanism automatically detects those and notifies the plugins in case they need to handle them in a special way. Other examples of branches will be described below.

9.8.2. Batches

Batch is a branch features of which have to be handled atomically. E.g. if processing a feature by a plugin changes a certain state of the model during generation of the final configuration then to avoid a potentionally temporary inconsistent state, batches indicate to the plugins that a specific set of features has to be processed together as a unit and as a single configuration change.

One example could be features that form circular dependencies. Handling them one by one may result in referential integrity (or some other kind of) constraint violation during the final configuration generation.

By default, branches are not flagged as batches. This can be configured though with property config.branch-is-batch. E.g.

    <config model="standalone">
        <props>
            <prop name="config.branch-is-batch" value="true"/>
        </props>
        <!-- the rest is skipped -->

The fragment above makes all the branches of all the standalone configuration models in the installation batches by default.

Batch flag can further be enabled or disabled for a specific branch with feature spec annotations.

<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="core-service.management">
    <annotation name="feature-branch">
        <elem name="id" value="core-service.management"/>
        <elem name="batch" value="true"/>
    </annotation>
        <!-- the rest is skipped -->

This marks branch core-service.management as batch.

9.8.3. Branch per feature spec

In some cases it might be useful to arrange features in the resolved configuration by their specs. Some plugins may find it more optimal to process, e.g., all the features of Spec1 first then all the features of Spec2, etc. The mechanism can be instructed to do that by including property config.branch-per-spec in config element, e.g.

    <config model="standalone">
        <props>
            <prop name="config.branch-per-spec" value="true"/>
        </props>
        <!-- the rest is skipped -->
the resulting branches of the configuration will be ordered according to the feature dependencies. E.g. if features of Spec1 reference features of Spec2, the branch of features Spec2 will appear in the configuration before the branch of features Spec1.

The example above is arranging all the features in the configuration by specs. In some cases though it would be useful to group only features of specific specs together and leave the rest of the features as they are. This can be configured by adding the following feature spec annotation

<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="core-service.management">
    <annotation name="feature-branch">
        <elem name="spec" value="true"/>
    </annotation>
        <!-- the rest is skipped -->

9.8.4. Isolating circular dependencies

The mechanism may identify circular dependencies between features in a configuration and create a separate branch for them. Here is how to enable this

    <config model="standalone">
        <props>
            <prop name="config.isolate-circular-deps" value="true"/>
        </props>
        <!-- the rest is skipped -->

9.8.5. Parent-children branch

Often features in configurations form parent-children relationships. Some plugins may find it useful to receive features arranged as parent-children branches. This can be configured per feature spec. E.g.

<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="SpecP">
    <annotation name="feature-branch">
        <elem name="parent-children"/>
    </annotation>
    <!-- the rest is skipped -->

Which means every feature of spec SpecP will start a branch containing all the features that are children (direct or transitive) of the SpecP feature.

9.8.6. Branches with explicit IDs

When a branch is created, the mechanism assigns an ID to the branch. A user may instruct the mechanism to group features of certain specs on a branch with a given ID. E.g.

<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="Spec1">
    <annotation name="feature-branch">
        <elem name="id" value="Branch1"/>
    </annotation>
    <!-- the rest is skipped -->
</feature-spec>

<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="Spec2">
    <annotation name="feature-branch">
        <elem name="id" value="Branch1"/>
    </annotation>
    <!-- the rest is skipped -->
</feature-spec>

In the example above features of Spec1 and Spec2 will be collected on the same branch Branch1.

9.8.7. Merging independent branches

After a configuration has been resolved, it may appear that some branches share certain common characteristics. E.g. most probably some features in the configuration will depend other features. Which makes the corresponding feature branches depend on other feature branches. There could be a few branches though that don’t depend on other branches (although there could be branches that depend on them). To reduce the total number of branches per configuration, independent branches could be merged into a single independent branch. This can be configured by adding the following property to the config element

    <config model="standalone">
        <props>
            <prop name="config.merge-independent-branches" value="true"/>
        </props>
        <!-- the rest is skipped -->

9.8.8. Merging branches with the same dependencies

While the previous option merges only the independent branches, this one identifies branches with the same dependencies on other branches and merges them into a single branch. It can be enabled by adding the following property

    <config model="standalone">
        <props>
            <prop name="config.config.merge-same-deps-branches" value="true"/>
        </props>
        <!-- the rest is skipped -->

10. Patches

The provisioning mechanism also supports feature-pack patching. Once a feature-pack has been released, the producer of the feature-pack may release patches for it. A patch could overwrite certain content of the feature-pack it applies to (i.e. certain packages or resources) and/or overwrite or re-define a part of the configuration.

A patch itself is also a feature-pack. The only thing that differentiates it from a usual feature-pack is element patch in its feature-pack.xml. Here is an example:

<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
    location="producer1@maven(org.jboss.universe:community-universe):1#1.0.0.Patch1.Final">

    <patch for="prod1@maven(org.jboss.galleon.universe.test:test-universe):1#1.0.0.Final"/> (1)

    <default-packages>
        <package name="p1"/>
    </default-packages>
</feature-pack>
1 indicates that the feature-pack is a patch which applies to the feature-pack specified as the value of for attribute
There is not currently any restriction on the patch feature-pack versioning. 1.0.0.Patch1.Final above is just a random example.
Patches can only be applied to a specific version of the feature-pack. An attempt to apply a patch to an installation that does not include the feature-pack version the patch was built for will result in a failure.

As any other feature-pack, a patch can be installed and uninstalled.

It is possible to apply multiple patches to the same feature-pack in the installation.

10.1. What can be patched

Patch basically provides a new version of certain content and/or redefines some configuration from the feature-pack it targets. Here is what can be patched:

  • packages (including their content and definitions);

  • feature specs (by providing updated feature specs);

  • feature groups (by providing updated feature groups);

  • layers;

  • configs;

  • various feature-pack resources;

  • provisioning plugins (by including new versions of the plugins).

Patches may also include content that is not present in the feature-pack that apply to (i.e. new packages, feature specs, groups, resources, plugins).

10.2. Multiple patches for the same feature-pack

As it was mentioned earlier, it is possible to apply multiple patches for the same feature-pack. In case patches don’t overlap in terms of what they patch, the order in which they are applied is not significant. If patches do overlap, the order in which they are applied most probably becomes significant. Because the patch that is applied last will overwrite patches that were applied before it.

Like any other feature-pack, patches may declare dependencies on other patches. That could be one of the ways to control the order in which the patches will be applied.

10.3. Applying patches

feature-pack element may include element patches which lists patches that should be installed for the feature-pack. E.g.

<installation xmlns="urn:jboss:galleon:provisioning:2.0">
    <feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
        <patches>
            <patch id="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Patch1.Final"/>
            <patch id="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Patch2.Final"/>
        </patches>
    </feature-pack>
</installation>

10.3.1. Patching transitive dependencies

It is also possible to apply patches to transitive dependencies. E.g.

<installation xmlns="urn:jboss:galleon:provisioning:2.0">
    <transitive>
        <feature-pack location="prod2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
            <patches>
                <patch id="prod2@maven(org.jboss.universe:community-universe):1#1.0.0.Patch1.Final"/>
                <patch id="prod2@maven(org.jboss.universe:community-universe):1#1.0.0.Patch2.Final"/>
            </patches>
        </feature-pack>
    </transitive>
    <feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
</installation>

11. Handling user-managed content

Once an installation has been built, a user or a process (on behalf of the user) may apply certain changes to the content of the installation such as add, edit or remove files and/or directories.

Since these kind of changes are not performed by the provisioning mechanism, it is the responsibility of the user to apply them in a safe manner and not break the installation by introducing some sort of unsatisfied dependencies or violating integrity constraints.

Since these kind of changes are usually going to be applied after the installation has been built they don’t interfere with the provisioning process. That is until the next (provisioning state) update.

When a user requests a version update or install/uninstall a patch or a feature-pack, or an undo for the installation that contains user-managed content or changes, the provisioning mechanism detects what exactly has changed since the last provisioned state.

If no user changes have been detected, the updated version of the installation will replace the current one. However, if the provisioning mechanism did detect certain changes to the last provisioned state (in the form of added/remove files and/or directories or editted files), those changes will be respected and re-applied to the updated installation state, i.e.

  • files and/or directories added to the previous installation state will be added to the updated installation state;

  • files and/or directories removed from the previous installation state will be removed from the updated installation state;

  • files editted in the previous installation state will be copied over to the updated installation state.

The provisioning mechanism DOES NOT perform 3-way merges on files that have changed in the updated installation state since the last provisioned state and that have also been modified by the user.

11.1. Application of user changes to the updated installation state

Table 13. User-added file
Target in the updated state Change applied to the updated state

Not found

The user-added file is copied to the updated state

Found and matches the file added by the user

None

Found and is different from the file added by the user

  • A copy of the file from the updated state is created with suffix .glnew

  • The user-added file is copied to the updated state (replacing the existing one)

Table 14. User-modified file
Target in the updated state Change applied to the updated state

Not found

The user-modified file is copied to the updated state and a warning is logged saying that the (equivalent of the) file modified in the previous state is not found in the updated state

Found and matches the resulting file modified by the user

None

Found and is different from the resulting file modified by the user

  • A copy of the file from the updated state is created with suffix .glnew

  • The user-modified file is copied to the updated state (replacing the existing one)

Table 15. User-removed file or directory
Target in the updated state Change applied to the updated state

Not found

None

Found

The target is removed from the updated installation

Table 16. User-created directory
Target in the updated state Change applied to the updated state

Not found

The corresponding directory is created in the updated state

Found

None

11.2. Protected system files

An installation may contain files and directories that are meant to be managed exclusively by feature-packs and the provisioning tools and not by users. For example, core system libraries of the installation. Such paths can be marked as system-paths in the feature-pack.xml.

If during an update a file matching a feature-pack’s system-path was found to be modified by a user, the provisioning mechanism will create a copy of the user-modified file adding the .glold suffix to it and replace the original one with the file provided by the feature-pack.

Table 17. User-added file matching a system-path
Target path in the updated state Change applied to the target path

Not found

The user-added file is copied to the updated state

Found and matches the file added by the user

None

Found and is different from the file added by the user

  • A copy of the user-added file is created with the .glold suffix

  • The file from the updated state replaces the existing one

Table 18. User-modified file matching a system-path
Target path in the updated state Change applied to the target path

Not found

The user-modified file is copied to the updated state and a warning is logged indicating that the (equivalent of the) file modified in the previous state is not found in the updated state

Found and matches the resulting file modified by the user

None

Found and is different from the resulting file modified by the user

  • A copy of the user-added file is created with the .glold suffix

  • The file from the updated state replaces the existing one

Table 19. User-removed file or directory matching a system-path
Target path in the updated state Change applied to the target path

Not found

None

Found

The target is restored to the updated state.

Table 20. User-created directory matching a system-path
Target path in the updated state Change applied to the target path

Not found

The corresponding directory is created in the updated state

Found

None

12. Provisioning options

Every provisioning action (such as provision, install, uninstall, etc) may accept provisioning options. Provisioning options may control various things, e.g. enable debug mode in one of the product-specific provisioning plugins, activate a certain provisioning mode, etc.

12.1. Persistent and non-persistent options

Provisioning options can be persistent and non-persistent.

Persistent options are persisted in the provisioning configuration file when the provisioning process has succesfully finished. E.g. if prod1 is installed with option1, the provisioned configuration will look like this

<installation xmlns="urn:jboss:galleon:provisioning:2.0">
    <feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
    <options>
        <option name="option1" value="true"/>
    </options>
</installation>

Now if the user installs prod2, option1 will still be effective during re-provisioning and the config will change to

<installation xmlns="urn:jboss:galleon:provisioning:2.0">
    <feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
    <feature-pack location="prod2@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
    <options>
        <option name="option1" value="true"/>
    </options>
</installation>
Option values are not necessarily true or false, they may have various values. The only restriction is they must have some value.

Non-persistent options, on the other hand, are not automatically stored in the provisioning configuration. They are used only for the provisioning action they were specified for.

12.2. Built-in and product-specific options

Provisioning options can be provided by the core provisioning mechanism itself and the product-specific provisioning plugins.

12.2.1. Built-in provisioning options

Table 21. Built-in provisioning options

Name

Purpose

Value set

ignore-not-excluded-layers

Suppresses the error when layers configured to be excluded would not have otherwise been installed

false (default), true

optional-packages

Optional package dependencies inclusion policy

all (default), none, passive, passive+

store-input-provisioning-config

Store the provisioning config received as input in the generated .galleon/provisioning.xml file

false (default), true

version-convergence

Disables or enables the dependency version convergence

first-processed (default), fail

export-system-paths

Store the system paths declared by Feature Packs in .galleon/systempaths.txt

false (default), true

12.2.2. Product provisioning options

Product-specific provisioning options are exposed by the product-specific provisioning plugins attached to the feature-packs.

13. Maven plugin

The Maven plugin allows to install a specific feature-pack into a new location or an existing installation or provision an installation the consists of multiple feature-packs.

The coordinates of the Maven plugin are

<dependency>
    <groupId>org.jboss.galleon</groupId>
    <artifactId>galleon-maven-plugin</artifactId>
    <version>5.2.0.Final</version>
</dependency>
Table 22. Goals

install-feature-pack

Installs a feature-pack into an empty directory or into an existing installation

provision

Provisions an installation that consists of one or more feature-packs at a specified location

13.1. install-feature-pack

13.1.1. galleon:install-feature-pack

Full name: org.jboss.galleon:galleon-maven-plugin:5.2.0.Final:install-feature-pack

13.1.2. Description

This maven plugin installs a feature-pack into an empty directory or a directory that already contains an installation, in which case the product the feature-pack represents will be integrated into an existing installation.

13.1.3. Attributes

  • Requires a Maven project to be executed.

  • Requires dependency resolution of artifacts in scope: compile+runtime.

  • Binds by default to the lifecycle phase: process-test-resources.

Table 23. Required Parameters

Name

Type

Since

Description

[installDir]

File

-

The target installation directory.
Alias is: install-dir.

Table 24. Optional Parameters

Name

Type

Since

Description

[customConfig]

File

-

Path to a file containing config that should be installed.
Alias is: custom-config.

[excludedPackages]

List

-

Explicitly excluded packages from the installation.
Alias is: excluded-packages.

[featurePack]

ArtifactItem

-

Legacy Galleon 1.x feature-pack artifact coordinates as (groupId - artifactId - version) if not specified the feature-pack must be a transitive dependency of a feature-pack with the version specified. NOTE: either this parameter or 'location' must be configured.
Alias is: feature-pack.

[includedConfigs]

List

-

Default feature-pack configs that should be included.
Alias is: included-configs.

[includedPackages]

List

-

Explicitly included packages to install.
Alias is: included-packages.

[inheritConfigs]

boolean

-

Whether to inherit the default feature-pack configs.
Default value is: true.
Alias is: inherit-configs.

[inheritPackages]

boolean

-

Whether to install the default package set.
Default value is: true.
Alias is: inherit-packages.

[location]

String

-

Galleon2 feature-pack location NOTE: either this parameter or 'feature-pack' must be configured.

[pluginOptions]

Map

-

Arbitrary plugin options recognized by the plugins attached to the feature-pack being installed.
Alias is: plugin-options.

[recordState]

boolean

-

Whether to record provisioned state in .galleon directory.
Default value is: true.
Alias is: record-state.

[skip]

boolean

4.2.6

Specifies whether installing the feature pack should be skipped.
Default value is: false.
User property is: galleon.skip.

13.1.4. Parameter Details

customConfig
Path to a file containing config that should be installed.

  • Type: java.io.File

  • Required: No

  • Alias: custom-config

excludedPackages
Explicitly excluded packages from the installation.

  • Type: java.util.List

  • Required: No

  • Alias: excluded-packages

featurePack
Legacy Galleon 1.x feature-pack artifact coordinates as (groupId - artifactId - version) if not specified the feature-pack must be a transitive dependency of a feature-pack with the version specified. NOTE: either this parameter or 'location' must be configured.

  • Type: org.jboss.galleon.maven.plugin.util.ArtifactItem

  • Required: No

  • Alias: feature-pack

includedConfigs
Default feature-pack configs that should be included.

  • Type: java.util.List

  • Required: No

  • Alias: included-configs

includedPackages
Explicitly included packages to install.

  • Type: java.util.List

  • Required: No

  • Alias: included-packages

inheritConfigs
Whether to inherit the default feature-pack configs.

  • Type: boolean

  • Required: No

  • Default: true

  • Alias: inherit-configs

inheritPackages
Whether to install the default package set.

  • Type: boolean

  • Required: No

  • Default: true

  • Alias: inherit-packages

installDir
The target installation directory.

  • Type: java.io.File

  • Required: Yes

  • Alias: install-dir

location
Galleon2 feature-pack location NOTE: either this parameter or 'feature-pack' must be configured.

  • Type: java.lang.String

  • Required: No

pluginOptions
Arbitrary plugin options recognized by the plugins attached to the feature-pack being installed.

  • Type: java.util.Map

  • Required: No

  • Alias: plugin-options

recordState
Whether to record provisioned state in .galleon directory.

  • Type: boolean

  • Required: No

  • Default: true

  • Alias: record-state

skip
Specifies whether installing the feature pack should be skipped.

  • Type: boolean

  • Since: 4.2.6

  • Required: No

  • User Property: galleon.skip

  • Default: false

13.2. provision

13.2.1. galleon:provision

Full name: org.jboss.galleon:galleon-maven-plugin:5.2.0.Final:provision

13.2.2. Description

This maven plugin provisions an installation that consists of one or more feature-packs. If the target installation directory already contains an installation, the existing installation will be fully replaced with the newly provisioned one. <p>In other words, the configuration provided for this goal fully describes the state of the final installation.</p>

13.2.3. Attributes

  • Requires a Maven project to be executed.

  • Requires dependency resolution of artifacts in scope: compile+runtime.

  • Binds by default to the lifecycle phase: process-test-resources.

Table 25. Required Parameters

Name

Type

Since

Description

[featurePacks]

List

-

A list of feature-pack configurations to install.
Alias is: feature-packs.

[installDir]

File

-

The target installation directory.
Alias is: install-dir.

Table 26. Optional Parameters

Name

Type

Since

Description

[configs]

List

-

A list of custom configurations to install.
Alias is: configurations.

[customConfig]

File

-

Path to a file containing config that should be installed.
Alias is: custom-config.

[logTime]

boolean

-

Whether to log provisioning time at the end
Default value is: false.
Alias is: log-time.

[offline]

boolean

-

Whether to use offline mode when the plugin resolves an artifact. In offline mode the plugin will only use the local Maven repository for an artifact resolution.
Default value is: false.
Alias is: offline.

[pluginOptions]

Map

-

Arbitrary plugin options.
Alias is: plugin-options.

[recordState]

boolean

-

Whether to record provisioned state in .galleon directory.
Default value is: true.
Alias is: record-state.

[resolveLocals]

List

-

A list of artifacts and paths pointing to feature-pack archives that should be resolved locally without involving the universe-based feature-pack resolver at provisioning time.
Alias is: resolve-locals.

[skip]

boolean

4.2.6

Specifies whether the provisioning should be skipped.
Default value is: false.
User property is: galleon.skip.

13.2.4. Parameter Details

configs
A list of custom configurations to install.

  • Type: java.util.List

  • Required: No

  • Alias: configurations

customConfig
Path to a file containing config that should be installed.

  • Type: java.io.File

  • Required: No

  • Alias: custom-config

featurePacks
A list of feature-pack configurations to install.

  • Type: java.util.List

  • Required: Yes

  • Alias: feature-packs

installDir
The target installation directory.

  • Type: java.io.File

  • Required: Yes

  • Alias: install-dir

logTime
Whether to log provisioning time at the end

  • Type: boolean

  • Required: No

  • Default: false

  • Alias: log-time

offline
Whether to use offline mode when the plugin resolves an artifact. In offline mode the plugin will only use the local Maven repository for an artifact resolution.

  • Type: boolean

  • Required: No

  • Default: false

  • Alias: offline

pluginOptions
Arbitrary plugin options.

  • Type: java.util.Map

  • Required: No

  • Alias: plugin-options

recordState
Whether to record provisioned state in .galleon directory.

  • Type: boolean

  • Required: No

  • Default: true

  • Alias: record-state

resolveLocals
A list of artifacts and paths pointing to feature-pack archives that should be resolved locally without involving the universe-based feature-pack resolver at provisioning time.

  • Type: java.util.List

  • Required: No

  • Alias: resolve-locals

skip
Specifies whether the provisioning should be skipped.

  • Type: boolean

  • Since: 4.2.6

  • Required: No

  • User Property: galleon.skip

  • Default: false

Table 27. Feature-pack parameters

Name

Required

Default value

Description

groupId

yes

-

Feature-pack Maven artifact groupId.

artifactId

yes

-

Feature-pack Maven artifactId.

version

no

-

Feature-pack artifact version (if not specified the feature-pack must be a transitive dependency of a feature-pack with the version specified.

inherit-configs

no

true

Whether to inherit the default feature-pack configs

included-configs

no

-

Default feature-pack configs that should be included.

excluded-configs

no

-

Default feature-pack configs that should be excluded.

inherit-packages

no

true

Whether to inherit the default feature-pack packages.

included-packages

no

-

Default feature-pack packages that should be included.

excluded-packages

no

-

Default feature-pack packages that should be excluded.

Example

<plugin>
    <groupId>org.jboss.galleon</groupId>
    <artifactId>galleon-maven-plugins</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>provision</goal>
            </goals>
            <configuration>
                <install-dir>${project.build.directory}/${project.build.finalName}</install-dir>
                <feature-packs>
                    <feature-pack>
                        <groupId>org.wildfly.core</groupId>
                        <artifactId>wildfly-core-galleon-pack</artifactId>
                        <inherit-configs>false</inherit-configs>
                        <excluded-packages>
                            <name>product.conf</name>
                            <name>docs.schema</name>
                        </excluded-packages>
                    </feature-pack>
                    <feature-pack>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>wildfly-servlet-galleon-pack</artifactId>
                        <version>${project.version}</version>
                            <excluded-packages>
                            <name>product.conf</name>
                            <name>docs.schema</name>
                        </excluded-packages>
                    </feature-pack>
                </feature-packs>
                <plugin-options>
                    <jboss-maven-dist/>
                </plugin-options>
            </configuration>
        </execution>
    </executions>
</plugin>

13.3. provision-file

13.3.1. galleon:provision-file

Full name: org.jboss.galleon:galleon-maven-plugin:5.2.0.Final:provision-file

13.3.2. Description

This maven plugin provisions an installation from a provisioning.xml file. If the target installation directory already contains an installation, the existing installation will be fully replaced with the newly provisioned one.

13.3.3. Attributes

  • Requires a Maven project to be executed.

  • Requires dependency resolution of artifacts in scope: compile+runtime.

  • Binds by default to the lifecycle phase: process-test-resources.

Table 28. Required Parameters

Name

Type

Since

Description

[installDir]

File

-

The target installation directory.
Alias is: install-dir.

[provisioningFile]

File

-

Path to a provisioning file located inside the current maven project used to provision the server.
Alias is: provisioning-file.

Table 29. Optional Parameters

Name

Type

Since

Description

[logTime]

boolean

-

Whether to log provisioning time at the end
Default value is: false.
Alias is: log-time.

[offline]

boolean

-

Whether to use offline mode when the plugin resolves an artifact. In offline mode the plugin will only use the local Maven repository for an artifact resolution.
Default value is: false.
Alias is: offline.

[pluginOptions]

Map

-

Arbitrary plugin options.
Alias is: plugin-options.

[recordState]

boolean

-

Whether to record provisioned state in .galleon directory.
Default value is: true.
Alias is: record-state.

[skip]

boolean

4.2.6

Specifies whether the provisioning should be skipped.
Default value is: false.
User property is: galleon.skip.

13.3.4. Parameter Details

installDir
The target installation directory.

  • Type: java.io.File

  • Required: Yes

  • Alias: install-dir

logTime
Whether to log provisioning time at the end

  • Type: boolean

  • Required: No

  • Default: false

  • Alias: log-time

offline
Whether to use offline mode when the plugin resolves an artifact. In offline mode the plugin will only use the local Maven repository for an artifact resolution.

  • Type: boolean

  • Required: No

  • Default: false

  • Alias: offline

pluginOptions
Arbitrary plugin options.

  • Type: java.util.Map

  • Required: No

  • Alias: plugin-options

provisioningFile
Path to a provisioning file located inside the current maven project used to provision the server.

  • Type: java.io.File

  • Required: Yes

  • Alias: provisioning-file

recordState
Whether to record provisioned state in .galleon directory.

  • Type: boolean

  • Required: No

  • Default: true

  • Alias: record-state

skip
Specifies whether the provisioning should be skipped.

  • Type: boolean

  • Since: 4.2.6

  • Required: No

  • User Property: galleon.skip

  • Default: false

14. Galleon CLI tool

This command line tool (bin/galleon.[sh|bat]) allows you to provision/manage any products/installations that comply with galleon feature-packs. Although being a generic tool, a builtin support is offered for products available from maven jboss community universe (eg: wildfly).
Possible actions that you can operate from the tool: install, uninstall, check for updates, patch, update, undo last provisioning command.

Launching the tool without any argument starts an interactive shell. Type exit to exit the tool.
Launching the tool with a command as argument will execute the command and exit, eg: galleon.sh install wildfly-core:current --dir=myinstallation
Launching the tool with --file=<path to script file> will execute the set of commands and exit.
Launching the tool with --help will display the descriptions of all available options and commands.

14.1. Feature-pack

A key concept in galleon system is the notion of feature-pack. A feature-pack is a content container. It can be a full product (eg: wildfly) or part of a product (eg: a wildfly subsystem packaged as a feature-pack). With the tool you are going to install/uninstall/update/…​ feature-packs.
NB: A galleon installation can be composed of 1 or more feature-packs.

A feature-pack can be a file on your local file system or located inside a universe (a product catalog).

The tool helps you identify the feature-pack that you can use for the task you want to achieve. In order to take benefit of the full capabilities offered by the tool, one needs to understand how products are identified inside a universe.

14.2. Universe feature-pack location (FPL)

A feature-pack location (FPL) is the way to identify a product inside a universe without actually expressing any build numbers. A lot to commands require that you provide FPL.

The main (non exhaustive) FPL syntax is: <product>[@universe]:[version]/[qualifier]
Some examples of FPL to identify wildfly products:

  • wildfly:current =⇒ Final (released) wildfly product current version

  • wildfly:current/alpha =⇒ The latest release of wildfly product current version that is at least of alpha quality.

The things to notice:

  • Universe (from where the product comes from) is optional for products located in jboss maven community universe.

  • No actual version nor build (eg: 1.0.0-Alpha1-SNAPHOT) is provided. The syntax of FPL is abstract it allows you to express a level of expected quality without hard-coding any version number.

  • Pointed by an FPL is an actual feature-pack artifact (a zipped file) that the tool will download/install,…​

  • A completer helps you compose FPL when the command you are calling expect one (eg: install).

For example, if one installs wildfly product using the following command:

install wildfly:current/alpha --dir=myInstallation

Then, later, when checking for updates or upgrading myInstallation directory, the latest build that is at least of quality alpha will be used to update. If a final release is available then it will be installed when upgrading.

NB: Products being unique inside an installation, some commands (eg: state update) only require the product part (<product>[@universe]) of an FPL. For example:

update --feature-packs=wildfly

14.3. Universe feature-pack id (FPID)

A feature-pack id (FPID) is the way to identify a product inside a universe by expressing a build number. This is the syntax to use when you want to deal with specific builds of a product.

The FPID syntax is: <product>[@universe]:[version]#[buildID]
Some examples of FPID to identify wildfly products:

  • wildfly:current#1.0.0-Final

  • wildfly:current#1.0.0-Alpha1

The things to notice:

  • Universe (from where the poduct comes from) is optional for products located in jboss maven community universe.

  • Pointed by an FPID is an actual feature-pack artifact (a zipped file)

  • A completer helps you compose your FPID when the command you are calling expect one (eg: install).

For example, to retrieve the informations of alpha1 build:

feature-pack get-info wildfly:current#1.0.0-Alpha1

14.4. Listing latest available feature-packs

[/]$ list-feature-packs [--all-frequencies] [--universe=<universe id>]

This command lists all the final feature packs present in all the installed universes.
The command looks in the current directory and its parent hierarchy for a possible installation in which some universes would have been added. By default the builtin universe is used.
If --all-frequencies option is set, then the latest build of all frequencies are displayed.
If --universe option is set, the command lists the feature packs of this universe.

The information displayed by this command can be re-used when installing, updating features-packs.

14.5. Searching for feature-packs

[/]$ find <pattern> [--universe=<universe id>] [--resolved-only]

This command searches for all the feature pack builds present in all the installed universes that match the provided pattern.
The command looks in the current directory and its parent hierarchy for a possible installation in which some universes would have been added. By default the builtin universe is used.
If --universe option is set, the command searches for feature packs inside this universe.
If --resolved-only option is set, the command only searches for feature packs installed in local repositories.

The information displayed by this command can be re-used when installing, updating features-packs.

14.6. Installing a feature-pack

install <[FPL|FPID] | [--file=<path to fp zip file>]> [--dir=<installation dir>] [--verbose] [feature-pack specific options]

This creates a directory containing the installed feature-pack content (binaries, configs).

NB: Using completion, when an installation directory has been identified, the options that are specific to the feature-pack to install are proposed. When installing for the first time a feature-pack this can take some time (a matter of few seconds up to minutes if the feature-pack needs to be downloaded from a remote location).

You can retrieve the set of feature-pack specific options without relying on completion, to do so call:
feature-pack get-info <[FPL|FPID] | [--file=<path to fp zip file>]> --type=options
You can then use the listed options (if any) to customize your install command.

14.7. Installing a subset of feature-pack configurations

When installing a feature-pack, all its default configurations are installed. Use the --default-configs=<comma separated list of config_model/config_name> option to specify the subset of configurations to install.

14.8. Installing feature-pack layers

The install command can be used to install a subset of feature-pack features. Such subset are called layers. When installing layers, a custom configuration is generated.

install <[FPL|FPID] | [--file=<path to fp zip file>]> [--dir=<installation dir>] [--layers=<comma separated list of layers>] [--config=<layers_model/configuration_name>]

In order to exclude an optional layer on which a layer from the list depends on, prefix the excluded layer with '-'. In order to un-exclude a layer already excluded in the current installation, prefix the layer with '+'.

NB: When installing layers, the existing provisioned installation (if any) is updated with the set of layers.

  • If some layers to install are already installed, they are ignored.

  • If some layers to exclude are already excluded, they are ignored.

  • If some layers to install are excluded from the existing installation, they are first un-excluded and installed.

  • If some layers to exclude are included in the existing installation, the command will fail. You can only exclude not directly included layers.

  • If some layers to un-exclude are not excluded, the command will fail.

  • If some layers to exclude are not optional dependencies of the layers to install (or from already installed layers), the command will fail. You can only exclude layers that are optional dependencies.

If no model name is provided, the CLI tries to identify the default model contained in the feature-pack. If no configuration name is provided, the <layers_model>.xml is used as the generated configuration file name.

You can retrieve the set of feature-pack defined layers without relying on completion, to do so call:
feature-pack get-info <[FPL|FPID] | [--file=<path to fp zip file>]> --type=layers
You can then use the listed layers (if any) to customize your install command.

14.9. Un-installing a feature-pack

uninstall [FPID] [--dir=<installation dir>] [--verbose] [feature-pack specific options]

This will remove the content installed by the feature-pack identified by the FPID. Some feature-pack specific options can be provided, they will be used when re-provisioning the remaining (if any) feature-packs.

NB: Completer proposes the FPID you can un-install from the installation (products and patches). Completion of feature-pack specific options are handled the same way as in the install command.

14.10. Un-doing the last provisioning command

undo [--dir=<installation dir>] [--verbose]

This will revert the installation to the previous installed state.

14.11. Patching an installation

Use the install command to patch an existing installation.

install <[FPL|FPID] | [--file=<path to patch zip file>]> [--dir=<installation dir>] [--verbose] [feature-pack specific options]

14.12. Un-installing a patch

Use the uninstall command to remove a given patch or use state undo if the last provisioning command has been a patch installation.

14.13. Checking for updates

check-updates [--dir=<installation dir>] [--include-all-dependencies] [--feature-packs=<list of feature-pack producers>]

If no products are provided, all installed products are checked for updates.

14.14. Updating an installation

The update command allows to update an installation to the latest available versions of installed feature-packs.

update [--dir=<installation dir>] [--include-all-dependencies] [--yes] [--feature-packs=<list of feature-pack producers or locations>] [feature-pack specific options]

Display the list of available updates/patches then update. If --yes is provided, the command will proceed without asking for confirmation.

NB: If the option --feature-packs contains feature-pack locations with versions, then these versions are used to update the feature-packs.

NB: Using completion, when an installation directory has been identified, the options that are specific to the installed feature-pack(s) are proposed. When updating an installation for the first time this can take some time (a matter of few seconds up to minutes if the feature-pack needs to be downloaded from a remote location).

You can retrieve the set of feature-pack specific options without relying on completion, to do so call:
installation get-info [--dir=<installation dir>] --type=options
You can then use the listed options (if any) to customize your update command.

14.15. Retrieving changes applied to an installation

In order to visualize files you have added, removed or modified, use the command get-changes [--dir=<installation>].
In the CLI output added files are prefixed by '+', removed ones by '-' and modified ones by 'M'.

14.16. Persisting changes applied to an installation

Installed feature-packs optionally support persistence of changes into the provisioning configuration. As an example, wildfly feature-packs persist configuration changes into the provisioning config.

Use the command persist-changes [--dir=<installation>] to persist the changes.

NB: If the installed feature-packs don’t support the ability to merge changes into the provisioning configuration, this operation has no side effect.

14.17. Observing an installation

[my-dir]$ installation get-info [--dir=installation] --type=[all|configs|dependencies|layers|optional-packages|options|patches|universes]

Display the set of installed feature-packs FPID. In addition can display configurations, dependencies layers and patches.
NB: If some patches are applied, the applied patches information is displayed.

14.18. Observing a feature-pack

[my-dir]$ feature-pack get-info <[FPL|FPID] | [--file=<path to fp zip file>]> --type=[all|configs|dependencies|layers|optional-packages|options]

Display the FPID of a feature-pack. In addition can display dependencies, configurations, layers and options usable when installing/provisioning/upgrading.

14.19. Optional packages

When getting information on an installation or a feature-pack, using --type=optional-packages option, you can retrieve the list of optional packages. At installation time the set of optional packages installed is controlled by the option --optional-packages=<all|none|passive|passive+>.

There are 2 kind of optional packages. passive ones, that are installed only if all their dependencies are installed and optional ones that have no requirements on their dependencies. Generally passive optional packages shouldn’t be excluded from an installation. They are needed for the package to properly operate when the other packages on which it depends are provisioned. Optional packages that are not passive can be excluded if not needed (according to the execution context).

When installing a complete feature-pack or installing a default configuration, the default value for --optional-packages is all (all optional and passive packages are installed).

When installing layers with the install commands the default value for --optional-packages is passive+ (all optional and passive packages that have all their dependencies installed are installed).

You can override these default values by using the --optional-packages option. Use none value to not install any optional nor passive packages, passive value to only install passive packages that have all their dependencies installed.

14.20. Managing the local cache of feature-packs

When a feature-pack is internally resolved (at install time, to expose information, to retrieve plugin options, …​). The feature-pack is added to a local cache. This cache is re-used to speed-up future resolutions. The CLI cleanup un-used feature-pack from the cache that are older than one month.

You can import (and optionally install in the universe for later resolution) a feature-pack zip file in the cache.

[my-dir]$ feature-pack import <path to fp zip file> [--install-in-universe=<true|false>]

You can clear the cache fully (NB: this will have a performance impact for future resolution).

[my-dir]$ feature-pack clear-cache

14.21. Exporting an installation to xml

[my-dir]$ installation export <new generated xml file> --dir=<installation>

14.22. Provisioning an installation from xml

[my-dir]$ provision <xml file> --dir=<target installation directory> [feature-pack specific options]

NB: Using completion, when an installation directory has been identified, the options that are specific to the feature-pack(s) located in the XML configuration file are proposed. When provisioning an installation for the first time this can take some time (a matter of few seconds up to minutes if the feature-pack needs to be downloaded from a remote location).

14.23. Managing the history of an installation

By default the history keeps the state of the last 100 provisioning operations. This should be enough to cover simple undo of provisioned state. Nevertheless you can increase/decrease this value by using the following command:

installation set-history-limit <history size limit> [--dir=<installation dir>]

To retrieve the history size limit do:

installation get-history-limit [--dir=<installation dir>]

14.24. Managing installation universes

A universe can be added/removed to/from an existing installation.

Add a named or default (without using the --name option) universe to an installation.
[/]$ installation add-universe [--dir=<installation dir>] [--name=<universe name>] --factory=<universe factory> --location=<universe location>

Remove a named or default (without using the --name option) universe from an installation.
[/]$ installation remove-universe [--dir=<installation dir>] [--name=<universe name>]

14.25. Directory option

Some commands (eg: install, get-info, check-updates, …​) allow you to optionally provide a target directory thanks to the --dir=<path> option. If no directory is provided, the command will lookup for an existing installation in the current directory (that you can change with the cd command) and its parent directories hierarchy. If no installation exists, the command will abort.

There are some exceptions to this installation lookup. install and provision commands expect the current directory to be empty or to be the root of an installation. uninstall, undo and update commands expect the current directory to be the root of an installation.

14.26. Exploring an installation or a feature-pack.

The tool allows you to switch to a state edit mode in which you can observe and edit a provisioning state in memory (without actually impacting the installation files).

To explore an installation:
[my-dir]$ state edit [<installation dir>]
[!edit!my-dir!/]$
After this point, the tool switched to edit mode with a set of new commands available.

Type help to list the set of available commands in this mode.

To explore a feature-pack:
[my-dir]$ state new
[!edit!/]$ add-dependency <[FPL|FPID] --default-configs-inherit --packages-inherit

Once exploring, prompt, ls, cd and pwd commands are bound to the feature-pack (or installation) exposed file-system.
Use leave-state to switch the tool back to its nominal mode.

[!edit!/]$ ls
configs
dependencies
feature-specs
packages
[!edit!/]$ leave-state
[my-dir]$

The fs is composed of:
/configs/final/<model>/<name>/<features>
/feature-specs/<origin>/<feature-specs>
/packages/<origin>/<packages>
Features and feature-specs are organized as a file system with containment.

Use ‘ls’ to visualize any item. Use ‘cd’ to navigate to a given node.

14.27. Searching the current state

When in edit mode, one can search for packages and features.

[!edit!/]$ search [--query=<some text> | --package=<package name>]

When searching with --query all packages and features are looked-up for a match. If packages are matched, the features that depend directly or indirectly on these packages will be shown in the result.

When searching with --package, the package completer can be used. The features that depend directly or indirectly on this package will be shown in the result.

14.28. Creating a new state (or editing an existing state from an installation or provisioning XML file)

This allow to start from an empty installation or re-use an installation and iteratively add/suppress content.

[my-dir]$ state new | state edit <path to installation dir | path to provisioning XML file>
[!edit!/]$ ls
configs
dependencies
feature-specs
packages

NB: Each action as the effect to build a runtime with the current state. The filesystem reflects the current state.

NB: Each action applied to a state in edition can be undone: undo.

NB: Use leave-state to leave the edit mode.

NB: The set of completer exposed commands is dynamic and is adjusted according to the current state.

14.29. Exporting or provisioning the current state

In edit mode, one can export the provisioning XML file or directly provision from the current state:

[!edit!/]$ export [<path to generated xml file>]
[!edit!/]$ provision <dir of new installation>

Use export to validate that what you get in the XML is in sync with the expose state.
Exporting a state without any XML target file will display the XML content in the CLI console.
The command 'get-info' can be used to get high level information.

14.30. Adding a feature-pack

[!edit!/]$ add-dependency <FPL|FPID> [--default-configs-inherit] [--packages-inherit]

By default nothing is inherited. Once at least one feature-pack has been added, configurations or packages can be handled.

14.31. Removing a feature-pack

[!edit!/]$ remove-dependency <FPL|FPID>

14.32. Including a default configuration

[!edit!/]$ include-config <model>/<name> [--origin=<fp origin>]

Origin is optional, by default will be included from all fp that expose it.

14.33. Removing an included default configuration

[!edit!/]$ remove-included-config <model>/<name> [--origin=<fp origin>]

The completer only proposes the set of configurations that have been previously included. Origin is optional, by default will be remove from all fp that include it.

14.34. Excluding a default configuration

[!edit!/]$ exclude-config <model>/<name> [--origin=<fp origin>]

Origin is optional, by default will be excluded from all feature-packs that expose it.

14.35. Removing an excluded default configuration

[!edit!/]$ remove-excluded-config <model>/<name> [--origin=<fp origin>]

The completer only proposes the set of configurations that have been previously excluded. Origin is optional, by default will be removed from all feature-packs that exclude it.

14.36. Including layers into a configuration

NB: Prior to be able to include layers into a configuration you need an included default or locally defined configuration. To define a new configuration call define-config --model=<config model> --name=<config name>

[!edit!/]$ include-layers <config model/config name> --layers=<comma separated list of layers>

NB: The completers for both configuration and layers propose you with the existing configurations and layers not already included.

14.37. Removing included layers from a configuration

[!edit!/]$ remove-included-layers <config model/config name> --layers=<comma separated list of included layers>

NB: You can only remove layers that have been explicitly included in your local configuration. Layers included in a default configuration can be excluded but their inclusion can’t be removed.

14.38. Excluding layers from a configuration

NB: Prior to be able to exclude layers from a configuration you need an included default or locally defined configuration that contain layers.

[!edit!/]$ exclude-layers <config model/config name> --layers=<comma separated list of layers>

NB: The completers for both configuration and layers propose you with the existing configurations and included layers.

14.39. Removing excluded layers from a configuration

[!edit!/]$ remove-excluded-layers <config model/config name> --layers=<comma separated list of excluded layers>

NB: You can only remove layers that have been explicitly excluded in your local configuration.

14.40. Reseting a configuration

[!edit!/]$ reset-config <model>/<name>

The custom content of this configuration is removed.

NB: This has no effect on included/excluded configurations.

14.41. Including a default package

[!edit!/]$ include-package <fp origin>/<package name>

14.42. Removing an included default package

[!edit!/]$ remove-included-package <package name> [--origin=<fp origin>]

The completer only proposes the set of packages that have been previously included. The origin is optional, the package will be removed from all feature-packs that exclude it.

14.43. Excluding a default package

[!edit!/]$ exclude-package <fp origin>/<package name>

14.44. Removing an excluded default package

[!edit!/]$ remove-excluded-package <package name> [--origin=<fp origin>]

The completer only proposes the set of packages that have been previously excluded. The origin is optional, the package will be removed from all feature-packs that exclude it.

14.45. Adding a new feature

[!edit!/]$ add-feature <config model/name> <path to feature-spec> <dynamic set of feature param=<value>>

For example:
add-feature standalone/standalone.xml org.wildfly.core:wildfly-core-galleon-pack/interface --interface=toto --inet-address=127.0.0.1

NB: All parameters are exposed as command option.

NB: All parameters that are not nillable and have no default values are required. The command being aborted if there are missing required parameters.

NB: If the parameter is not present, its default value is injected when creating the feature.

NB: The current location (thanks to cd) is not yet taken into account when completing/adding the feature. That is a TODO.

NB: A feature with the same feature-id can’t exist. A single feature with the given feature-id per config.

14.46. Removing a feature

[!edit!/]$ remove-feature <full path to feature inside a configuration>

For example:
remove-feature standalone/standalone.xml/interface/toto

14.47. Managing universes

A universe can be added/removed to/from a state.

Add a named or default (without using the --name option) universe to the state.
[!edit!/]$ add-universe [--name=<universe name>] --factory=<universe factory> --location=<universe location>

Remove a named or default (without using the --name option) universe from the state.
[!edit!/]$ remove-universe [--name=<universe name>]

15. CLI tool Maven configuration

By default the following maven repositories are used to retrieve FP.

The cli allows you to change the path to the local repository and add/remove remote maven repositories.

15.1. Relying on maven settings

In order to makes the cli to use a maven settings file call: maven set-settings-file <path to settings xml file> In order to remove the reference to the settings file call: maven reset-settings-file

NB: Advanced mirroring (eg: external:*) is not supported.
NB: Any other cli maven configuration items will be overridden when a settings xml file is set.
NB: If no local repository is set in settings file, the local repository (default or configured) is used.

The following default repositories are enabled if not already present in the enabled profiles:

NB: These default repositories can be mirrored by using their ids.

15.2. Adding new remote repositories

Use the following command to add new remote repositories:
maven add-repository --name=myrepo --url=http://foorepo [--release-update-policy=<policy>] [--snapshot-update-policy=<policy>] [--type=<type>] [--enable-release=[true|false] [--enable-snapshot=[true|false]

NB: The type, release update policy, snapshot update policy and enable/disable of snapshot/release are optional and have default values.

15.3. Default Repository policies

Daily update for releases, never update for snapshots.
Warn if checksum differs.

Snapshots are not resolved from remote repositories.
Releases are resolved from remote repositories.

Update polices can be changed by calling:
maven set-release-update-policy [<always|daily|interval:|never>]
maven set-snapshot-update-policy [<always|daily|interval:|never>]

Activation of snapshot/release resolution can be changed by calling:
maven enable-snapshot [<true|false>]
maven enable-release [<true|false>]

NB: A reset command can be called for any of these changes to set the value back to its default value.

15.4. Advanced maven configuration

Proxy, authentication and mirroring are only supported when setting a maven xml settings file.

15.5. Local repository

By default the local maven repository is located in <user.home>/.m2/repository. You can change this directory by using the command: maven set-local-repository <path to your local repository directory>
In order to reset to the default local maven repository call: maven reset-local-repository

15.6. Offline mode

By default maven is in online mode. In order to switch to offline use the command maven enable-offline <true|false>
In order to reset to the default mode call: maven reset-offline

15.7. Display maven configuration

Call command: maven get-info

15.8. Impact on Universe

Any change made to the maven configuration makes the CLI to re-resolve universe(s). This means that stream resolution stays in sync with maven configuration.

15.9. Resolving feature-packs

When remote repositories are set, feature-packs are automatically downloaded at install time. You can download feature-pack explicitly to the local repository by using the command: maven resolve-feature-pack <feature-pack location> [--verbose]

15.10. Maven tracing

When enabling "verbose" at installation and provisioning time, any artifact retrieved from a remote repository is advertised in the console. This also applies when fetching explicitly feature-packs.