© 2018 The original authors.

1. Introduction

WildFly Galleon Plugins project includes Galleon and Maven plugin implementations that are dedicated to building feature-packs (including generation of feature specs, packages and other resources) for WildFly releases and provisioning of WildFly-based distributions. These plugins can also be used by projects that integrate into or extend WildFly (Core, Servlet or Full base distributions).

2. Maven plugin

This chapter is dedicated to the Maven plugin that can be used to build WildFly-based feature-packs. Maven coordinates of the Maven plugin artifact are

Maven plugin installing feature-packs and provisioning distributions is a part of Galleon project itself. Please, refer to Galleon documentation for more information.
<dependency>
    <groupId>org.wildfly.galleon-plugins</groupId>
    <artifactId>wildfly-galleon-maven-plugin</artifactId>
    <version>2.0.0.Final</version>
</dependency>

2.1. Goals overview

generate-feature-specs

Generates feature specs from WildFly extensions that are later included into the feature-pack.

build-feature-pack

Creates a feature-pack archive from the provided resources in the WildFly fashion.

2.2. generate-feature-specs

2.2.1. wildfly-galleon:generate-feature-specs

Full name: org.wildfly.galleon-plugins:wildfly-galleon-maven-plugin:2.0.1.Alpha1-SNAPSHOT:generate-feature-specs

2.2.2. Description

This plug-in generates WildFly feature specifications. It starts a minimal embedded server with the specified extensions, resolving dependencies via Aether, and gets an export of the meta-model from the server to produce the specifications for Galleon.

2.2.3. Attributes

  • Requires a Maven project to be executed.

  • Requires dependency resolution of artifacts in scope: runtime.

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

Table 1. Required Parameters

Name

Type

Since

Description

[moduleTemplatesDir]

Path

-

A directory where the module templates from the dependent feature packs are gathered before they are transformed and copied under their default destination wildflyHome/modules. Intended mainly for debugging.
Default value is: ${project.build.directory}/module-templates.
User property is: wfgp.moduleTemplatesDir.
Alias is: module-templates.

[outputDirectory]

File

-

The directory where the generated specifications are written.
Alias is: output-dir.

[wildflyHome]

Path

-

A directory from which the embedded WildFly instance will be started that is used for exporting the meta-model. Intended mainly for debugging.
Default value is: ${project.build.directory}/wildfly.
User property is: wfgp.wildflyHome.
Alias is: wildfly-home.

Table 2. Optional Parameters

Name

Type

Since

Description

[configDir]

File

-

The feature-pack build configuration file directory
Default value is: ${basedir}.
User property is: wildfly.feature.pack.configDir.
Alias is: config-dir.

[configFile]

String

-

The feature-pack build configuration file.
Default value is: wildfly-feature-pack-build.xml.
User property is: wildfly.feature.pack.configFile.
Alias is: config-file.

[forkEmbedded]

boolean

-

Whether to launch the embedded server to read feature descriptions in a separate process
Alias is: fork-embedded.

2.2.4. Parameter Details

configDir
The feature-pack build configuration file directory

  • Type: java.io.File

  • Required: No

  • User Property: wildfly.feature.pack.configDir

  • Default: ${basedir}

  • Alias: config-dir

configFile
The feature-pack build configuration file.

  • Type: java.lang.String

  • Required: No

  • User Property: wildfly.feature.pack.configFile

  • Default: wildfly-feature-pack-build.xml

  • Alias: config-file

forkEmbedded
Whether to launch the embedded server to read feature descriptions in a separate process

  • Type: boolean

  • Required: No

  • Alias: fork-embedded

moduleTemplatesDir
A directory where the module templates from the dependent feature packs are gathered before they are transformed and copied under their default destination wildflyHome/modules. Intended mainly for debugging.

  • Type: java.nio.file.Path

  • Required: Yes

  • User Property: wfgp.moduleTemplatesDir

  • Default: ${project.build.directory}/module-templates

  • Alias: module-templates

outputDirectory
The directory where the generated specifications are written.

  • Type: java.io.File

  • Required: Yes

  • Alias: output-dir

wildflyHome
A directory from which the embedded WildFly instance will be started that is used for exporting the meta-model. Intended mainly for debugging.

  • Type: java.nio.file.Path

  • Required: Yes

  • User Property: wfgp.wildflyHome

  • Default: ${project.build.directory}/wildfly

  • Alias: wildfly-home

2.2.5. Sample Configuration

Sample plugin configuration
<plugin>
  <groupId>org.wildfly.galleon-plugins</groupId>
  <artifactId>wildfly-galleon-maven-plugin</artifactId>
  <executions>
    <execution>
      <id>feature-spec-build</id>
      <goals>
        <goal>generate-feature-specs</goal>
      </goals>
      <phase>prepare-package</phase>
      <configuration>
        <output-dir>${basedir}/target/resources/features</output-dir> (1)
      </configuration>
    </execution>
  </executions>
</plugin>
1 output-Dir: The directory where the generated specifications are written.

2.2.6. How it works

This section explains the basic mechanism of feature spec generation in WildFly.

Since the whole mechanism relies on the WildFly metamodel, we create a mininal configuration file with all the extensions we want to be able to configure in the feature-pack. Then we boot the embedded server and execute read-feature-description(recursive) management operation on the root resource. The operation returns the description of Galleon feature spec for every resource in the model that may appear in server configurations.

Each resource registration in the WildFly model is considered to be a feature as long as it is not a proxy, a runtime only or an alias. The registration address is used to define the feature-id of the feature and all attributes that can be used in the add operation handler will become parameters.

Capabilities are used to define the links between feature specs thus defining how the operations will be grouped, ordered and executed.

Complex attributes are represented as usual feature parameters and also as separate feature specs. Which means complex attribute values can be configured using Galleon features. Dependending on the actual parameter type, features that represent complex attribute values will be added to the configuration using write-attribute or list-add operations instead of add.

Certain feature specs for standalone server, domain and host controller are processed and merged into a single feature spec (if no incompatibility exists between those three models) to have a single feature spec re-usable in the three configuration models.

2.3. build-feature-pack

2.3.1. wildfly-galleon:build-feature-pack

Full name: org.wildfly.galleon-plugins:wildfly-galleon-maven-plugin:2.0.1.Alpha1-SNAPSHOT:build-feature-pack

2.3.2. Description

This Maven mojo creates a WildFly style feature-pack archive from the provided resources according to the feature-pack build configuration file and attaches it to the current Maven project as an artifact. The content of the future feature-pack archive is first created in the directory called layout under the module’s build directory which is then ZIPped to create the feature-pack artifact.

2.3.3. Attributes

  • Requires a Maven project to be executed.

  • Requires dependency resolution of artifacts in scope: runtime.

  • Binds by default to the lifecycle phase: compile.

Table 3. Required Parameters

Name

Type

Since

Description

[resourcesDir]

String

-

Represents the directory containing child directories packages, feature_groups, modules etc. Either an absolute path or a path relative to configDir.
Default value is: src/main/resources.
User property is: wildfly.feature.pack.resourcesDir.
Alias is: resources-dir.

Table 4. Optional Parameters

Name

Type

Since

Description

[buildName]

String

-

The directory for the built artifact.
Default value is: ${project.build.directory}.
User property is: wildfly.feature.pack.buildName.

[configDir]

File

-

The feature-pack build configuration file directory
Default value is: ${basedir}.
User property is: wildfly.feature.pack.configDir.
Alias is: config-dir.

[configFile]

String

-

The feature-pack build configuration file.
Default value is: wildfly-feature-pack-build.xml.
User property is: wildfly.feature.pack.configFile.
Alias is: config-file.

[fpArtifactId]

String

-

The artifactId for the generated feature-pack.
Default value is: ${project.artifactId}.
Alias is: feature-pack-artifact-id.

[releaseName]

String

-

The name of the release the feature-pack represents which will be stored in the feature-pack’s resources/wildfly/wildfly-tasks.properties as product.release.name property.
Default value is: ${product.release.name}.
Alias is: release-name.

[taskProps]

Map

-

Various properties that will be added to feature-pack’s resources/wildfly/wildfly-tasks.properties.
NOTE: values of this parameter will overwrite the corresponding values from task-properties-file parameter, in case it’s also set. +
Alias is: task-properties.

[taskPropsFile]

File

-

Path to a properties file content of which will be added to feature-pack’s resources/wildfly/wildfly-tasks.properties file that is used as the source of properties during file copying tasks with property replacement.
Alias is: task-properties-file.

2.3.4. Parameter Details

buildName
The directory for the built artifact.

  • Type: java.lang.String

  • Required: No

  • User Property: wildfly.feature.pack.buildName

  • Default: ${project.build.directory}

configDir
The feature-pack build configuration file directory

  • Type: java.io.File

  • Required: No

  • User Property: wildfly.feature.pack.configDir

  • Default: ${basedir}

  • Alias: config-dir

configFile
The feature-pack build configuration file.

  • Type: java.lang.String

  • Required: No

  • User Property: wildfly.feature.pack.configFile

  • Default: wildfly-feature-pack-build.xml

  • Alias: config-file

fpArtifactId
The artifactId for the generated feature-pack.

  • Type: java.lang.String

  • Required: No

  • Default: ${project.artifactId}

  • Alias: feature-pack-artifact-id

releaseName
The name of the release the feature-pack represents which will be stored in the feature-pack’s resources/wildfly/wildfly-tasks.properties as product.release.name property.

  • Type: java.lang.String

  • Required: No

  • Default: ${product.release.name}

  • Alias: release-name

resourcesDir
Represents the directory containing child directories packages, feature_groups, modules etc. Either an absolute path or a path relative to configDir.

  • Type: java.lang.String

  • Required: Yes

  • User Property: wildfly.feature.pack.resourcesDir

  • Default: src/main/resources

  • Alias: resources-dir

taskProps
Various properties that will be added to feature-pack’s resources/wildfly/wildfly-tasks.properties.
NOTE: values of this parameter will overwrite the corresponding values from task-properties-file parameter, in case it’s also set.

  • Type: java.util.Map

  • Required: No

  • Alias: task-properties

taskPropsFile
Path to a properties file content of which will be added to feature-pack’s resources/wildfly/wildfly-tasks.properties file that is used as the source of properties during file copying tasks with property replacement.

  • Type: java.io.File

  • Required: No

  • Alias: task-properties-file

2.3.5. Feature-pack packages

The Maven project module which creates a feature-pack may describe its packages and/or provide more data for the packages generated from JBoss modules in the Maven module’s src/main/resources/packages.

Every child directory of src/main/resources/packages represents a package with the directory name being the package name. The content of the package directory is going to be copied to the corresponding package directory in the feature-pack.

The usual package directory structure is:

package_name
|- content/
|- pm/
|  `- wildfly/
|     `- tasks.xml
`- package.xml

In general, the only required child of the package directory is package.xml.

Package content directory includes content that will be copied to the installation root directory when the package is installed.

pm/wildfly/tasks.xml file is optional, it may include instructions to copy and/or delete files and diretcories, create directories, resolve and copy Maven artifacts to the installation directory, etc. These tasks are executed when the content of all the packages has been copied into the installation.

2.3.6. Generating JBoss module packages

JBoss modules of the distribution are turned into feature-pack packages. A package is created per JBoss module. JBoss module dependencies are reflected in the corresponding package dependencies.

JBoss modules packages don’t have to be manually described in src/main/resources/packages.

Traditionally, WildFly-based builds use module.xml templates to generate the final module.xml files based on the distribution type selected: thin (when the JBoss module artifacts are loaded directly from the Maven repository at runtime) or thick (when the JBoss module artifacts are resolved and copied to the distribution directory at provisioning time).

The Maven module that is building a feature-pack may include src/main/resources/modules/system/layers directory containing module.xml templates. The mojo will read those and generate a package per module.xml.

For example, here is an excerpt from a module.xml template:

<module xmlns="urn:jboss:module:1.8" name="org.jboss.as.jmx">
    <properties>
        <property name="jboss.api" value="private"/>
    </properties>

    <exports>
        <exclude path="org/jboss/as/jmx/logging"/>
    </exports>

    <resources>
        <artifact name="${org.wildfly.core:wildfly-jmx}"/>
    </resources>

    <dependencies>
        <!-- skipped content -->

It looks pretty much like the final module.xml except that the artifact name is an epression which should be replaced with either the complete artifact coordinates in case of a thin distribution, e.g.

<module name="org.jboss.as.jmx" xmlns="urn:jboss:module:1.8">
    <properties>
        <property name="jboss.api" value="private"/>
    </properties>

    <exports>
        <exclude path="org/jboss/as/jmx/logging"/>
    </exports>

    <resources>
        <artifact name="org.wildfly.core:wildfly-jmx:5.0.0.Beta3-SNAPSHOT"/>
    </resources>

    <dependencies>
        <!-- skipped content -->

or the resource-root element in case of a thick distribution, e.g.

<module name="org.jboss.as.jmx" xmlns="urn:jboss:module:1.8">
    <properties>
        <property name="jboss.api" value="private"/>
    </properties>

    <exports>
        <exclude path="org/jboss/as/jmx/logging"/>
    </exports>

    <resources>
        <resource-root path="wildfly-jmx-5.0.0.Beta3-SNAPSHOT.jar"/>
    </resources>

    <dependencies>
        <!-- skipped content -->

module.xml template processing is happening at provisioning time and depends on the kind of distribution being provisioned.

It is possible that a module depends on another module which is not found in the current feature-pack. In that case, the feature-pack that contains the package representing the module from the dependency must be declared as the dependency of the current feature-pack in the feature-pack build config file. If the dependency could not be resolved locally (among the modules included in the current feature-pack), the module will be looked up in the dependencies of the current feature-pack (in the order the dependencies are specified in the feature-pack build config file).

In case a module dependency could not be resolved neither locally nor in the feature-pack dependencies, an error will be thrown with the corresponding message.

The package generated for a JBoss module can still be customized by, e.g., adding pm/wildfly/tasks.xml to it in src/main/resources/packages. In this case the package dir in src/main/resources/packages has to include only the content that the generated package is missing. It doesn’t have to include package.xml unless the generated one has to be replaced with a custom one.
modules.all package

If a feature-pack includes JBoss modules, in addition to the module packages, the mojo will generate a package called modules.all. This package will not contain any content but will simply depend on all the module packages generated for this feature-pack. This package exists for convenience only to be able to install all the modules from the feature-pack (and its dependencies) by including a single package.

Original WildFly feature-packs include modules.all into the default package list at the moment to follow the legacy approach of building distributions. This is configured in the feature-pack build config file.

2.4. Feature-pack build config file (wildfly-feature-pack-build.xml)

Feature-pack building starts with this file. The file describes the feature-pack in terms of its dependencies on other feature-packs, default packages, configs and other options such as from which artifact groups to extract schemas into the distribution’s docs/schema directory.

If the file includes feature-pack dependencies, those feature-packs must be resolvable as Maven artifacts during the build process. They will be explored to collect the provisioning descriptions (such as feature-pack.xml, etc) of the dependencies.

Normally, most of the content of this file will be copied directly into the final feature-pack.xml generated by the mojo. Here is an example from WildFly Servlet feature-pack build config file

<build xmlns="urn:wildfly:feature-pack-build:2.0">
    <dependencies>
        <dependency group-id="org.wildfly.core" artifact-id="wildfly-core-galleon-pack">
            <name>org.wildfly.core:wildfly-core-galleon-pack</name>
            <packages inherit="false">
                <exclude name="product.conf"/>
            </packages>
            <default-configs inherit="false"/>
        </dependency>
    </dependencies>
    <default-packages>
        <package name="modules.all"/>
        <package name="docs"/>
    </default-packages>
    <package-schemas>
        <group name="org.jboss.as"/>
        <group name="org.wildfly"/>
        <group name="org.wildfly.core"/>
    </package-schemas>
    <config model="standalone">
        <packages>
            <package name="product.conf" optional="true"/>
            <package name="misc.standalone"/>
        </packages>
    </config>

    <!-- other configs are skipped -->

    <generate-feature-specs>
        <extensions>
            <standalone>
                <extension>org.jboss.as.ee</extension>
                <extension>org.jboss.as.naming</extension>
                <extension>org.jboss.as.security</extension>
                <extension>org.wildfly.extension.undertow</extension>
            </standalone>
            <domain>
                <extension>org.jboss.as.ee</extension>
                <extension>org.jboss.as.naming</extension>
                <extension>org.jboss.as.security</extension>
                <extension>org.wildfly.extension.undertow</extension>
            </domain>
        </extensions>
    </generate-feature-specs>
</build>

All the elements in the above example except for package-schemas and generate-feature-specs are actual feature-pack.xml content that will be copied to the resulting feature-pack.xml as-is.

Extracting schemas

The presence of element package-schemas instructs the mojo to create a package called docs.schema. The package includes no content but a file with Maven artifact groupIds from which XSD schemas should be extracted into the distribution’s docs/schema directory, in case docs.schema package was selected to be installed (it is by default).

Feature specs generation

Feature-pack may or may not include feature specs (XML files describing configuration features). Feature specs are included only if the feature-pack includes one or more subsystems that should be added to the confuration when the feature-pack is installed.

In WildFly feature-packs, feature specs are generated. generate-feature-specs is an element that lists extensions included in the feature-pack for which feature specs should be generated.

feature specs are generated using generate-feature-specs goal of the plugin.
Adding provisioning plugins

Feature-packs that depend on WildFly (or WildFly Core), normally, don’t need to add any provisioning plugins to be usable by Galleon. WildFly Core feature-pack includes the plugins that are used during provisioning for all the feature-packs that (directly or indirectly) depend on it. Here is a snipped from WildFly Core wildfly-feature-pack-build.xml that adds WildFly provisioning plugin JARs:

<build xmlns="urn:wildfly:feature-pack-build:3.0" producer="wildfly-core@maven(org.jboss.universe:community-universe):current">
    <!-- content skipped -->

    <plugins>
        <plugin artifact="org.wildfly.galleon-plugins:wildfly-galleon-plugins"/> (1)
    </plugins>

    <resources>
        <copy artifact="org.wildfly.galleon-plugins:wildfly-config-gen" to="wildfly/wildfly-config-gen.jar"/> (2)
    </resources>

    <!-- content skipped -->
</build>
1 plugins element may include multiple plugin elements specifying Maven artifact coordinates of the plugin
2 copy element under resources instructs to copy the specified artifact to the feature-pack resources directory
Both artifact coordinates above are missing versions. Although the versions could specified, in this case they will be resolved from the Maven project dependencies at the plugin execution time.