为WildFly创建补丁文件

发布者    |       讨论

WildFly应用程序服务器附带一个补丁机制,这使得升级服务器现有模块或添加新模块变得非常容易。例如,Hibernate Validator提供补丁文件,可让您将WildFly 10.1升级到Bean Validation 2.0的预览版本。

但您也可以使用补丁机制将您自己的自定义库添加到WildFly中,使其可供部署的应用程序使用。即使您只将单个应用程序部署到一个WildFly实例,这也可以非常有用,因为它可以减小您的部署单元(WAR等)的大小,从而加快构建和部署时间。

但是WildFly补丁是如何创建的呢?补丁文件通常是包含要添加或更新的模块(以及一些额外的元数据)的ZIP文件。因此,从理论上讲,您可以通过手工创建它们,但有一个patch-gen工具可以极大地简化这项任务。

以下我们将一步一步地描述如何使用patch-gen-maven-plugin创建一个WildFly补丁。作为一个例子,我们将生成一个补丁文件,将该Eclipse Collections库添加到WildFly实例中。

模块描述符

我们首先需要的是JBoss Modules系统的模块描述符,这是WildFly的底层基础。Eclipse Collections分为两个JAR,一个用于API,一个用于实现。因此,我们将创建以下两个描述符

src/main/modules/system/layers/base/org/eclipse/collections/api/main/module.xml
<?xml version="1.0" encoding="UTF-8"?>

<module xmlns="urn:jboss:module:1.3" name="org.eclipse.collections.api">
    <resources>
        <resource-root path="eclipse-collections-api-${eclipse.collections.version}.jar" />
    </resources>
</module>
src/main/modules/system/layers/base/org/eclipse/collections/main/module.xml
<?xml version="1.0" encoding="UTF-8"?>

<module xmlns="urn:jboss:module:1.3" name="org.eclipse.collections">
    <resources>
        <resource-root path="eclipse-collections-${eclipse.collections.version}.jar" />
    </resources>

    <dependencies>
        <module name="org.eclipse.collections.api" />
    </dependencies>
</module>

每个描述符指定了对应JAR的资源(版本属性占位符使用Maven资源过滤进行替换)。实现模块还声明了对API模块的依赖。

补丁工具配置文件

《patch-gen》工具需要一个小的配置文件,用于描述一些补丁元数据(例如,补丁应用的服务器版本和补丁类型——一次性或累积型)以及修复的模块。

src/main/patch/patch.xml
<?xml version='1.0' encoding='UTF-8'?>

<patch-config xmlns="urn:jboss:patch-config:1.0">
    <name>wildfly-${wildfly.version}-eclipse-collections-${eclipse.collections.version}</name>
    <description>This patch adds Eclipse Collections ${eclipse.collections.version} to a WildFly ${wildfly.version} installation</description>
    <element patch-id="layer-base-wildfly-${wildfly.version}-eclipse-collections-${eclipse.collections.version}">
        <one-off name="base" />
        <description>This patch adds Eclipse Collections ${eclipse.collections.version} to a WildFly ${wildfly.version} installation</description>
        <specified-content>
            <modules>
                <added name="org.eclipse.collections.api" />
                <added name="org.eclipse.collections" />
            </modules>
        </specified-content>
    </element>
    <specified-content/>
</patch-config>

准备补丁创建

《patch-gen》工具需要两个要修复的发行版的目录作为输入:一个包含原始、未修复的WildFly结构的目录,另一个包含原始WildFly结构以及添加(或更新)的模块的目录。我们可以使用Maven依赖插件通过两次提取WildFly发行版来创建这两个目录。

pom.xml
...
<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>unpack-wildfly</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>unpack</goal>
            </goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>org.wildfly</groupId>
                        <artifactId>wildfly-dist</artifactId>
                        <version>${wildfly.version}</version>
                        <type>tar.gz</type>
                        <overWrite>false</overWrite>
                        <outputDirectory>${project.build.directory}/wildfly-original</outputDirectory>
                    </artifactItem>
                    <artifactItem>
                        <groupId>org.wildfly</groupId>
                        <artifactId>wildfly-dist</artifactId>
                        <version>${wildfly.version}</version>
                        <type>tar.gz</type>
                        <overWrite>false</overWrite>
                        <outputDirectory>${project.build.directory}/wildfly-patched</outputDirectory>
                    </artifactItem>
                </artifactItems>
            </configuration>
        </execution>
    </executions>
</plugin>
...

现在我们需要将Eclipse Collections JAR文件添加到第二个目录中。让我们为这一步配置Maven依赖插件的另一个执行。

pom.xml
...
<execution>
    <id>add-eclipse-collections</id>
    <phase>prepare-package</phase>
    <goals>
        <goal>copy</goal>
    </goals>
    <configuration>
        <artifactItems>
            <artifactItem>
                <groupId>org.eclipse.collections</groupId>
                <artifactId>eclipse-collections-api</artifactId>
                <version>${eclipse.collections.version}</version>
                <overWrite>false</overWrite>
                <outputDirectory>${wildflyPatched}/modules/system/layers/base/org/eclipse/collections/api/main</outputDirectory>
            </artifactItem>
            <artifactItem>
                <groupId>org.eclipse.collections</groupId>
                <artifactId>eclipse-collections</artifactId>
                <version>${eclipse.collections.version}</version>
                <overWrite>false</overWrite>
                <outputDirectory>${wildflyPatched}/modules/system/layers/base/org/eclipse/collections/main</outputDirectory>
            </artifactItem>
        </artifactItems>
    </configuration>
</execution>
...

我们还需要添加module.xml描述符,以便它们位于相应的JAR文件旁边。Maven资源插件有助于完成这项工作。它还可以用于替换patch.xml描述符中的占位符。以下两个插件执行是必需的

pom.xml
...
<plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-module-descriptors</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>${wildflyPatched}/modules</outputDirectory>
                <resources>
                    <resource>
                        <directory>src/main/modules</directory>
                        <filtering>true</filtering>
                    </resource>
                </resources>
            </configuration>
        </execution>
        <execution>
            <id>filter-patch-descriptor</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/</outputDirectory>
                <resources>
                    <resource>
                        <directory>src/main/patch</directory>
                        <filtering>true</filtering>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>
...

配置Patch-Gen Maven插件

在所有这些准备工作完成之后,我们现在需要配置patch-gen Maven插件,该插件最终将组装补丁文件。

pom.xml
...
<plugin>
    <groupId>org.jboss.as</groupId>
    <artifactId>patch-gen-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>create-patch-file</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>generate-patch</goal>
            </goals>
            <configuration>
                <appliesToDist>${wildflyOriginal}</appliesToDist>
                <updatedDist>${wildflyPatched}</updatedDist>
                <patchConfig>${project.build.directory}/patch.xml</patchConfig>
                <outputFile>${patchFile}</outputFile>
            </configuration>
        </execution>
    </executions>
</plugin>
...

插件需要以下配置

  • 未修复WildFly目录的路径

  • 已修复WildFly目录的路径

  • patch.xml描述符的路径

  • 补丁文件的输出路径

最后一步,我们需要确保创建的补丁文件被添加到Maven构建中。这样,创建的ZIP文件可以被安装到本地Maven仓库并部署到Nexus等仓库服务器。构建辅助Maven插件有助于完成最后这项任务

pom.xml
...
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>attach-patch-artifact</id>
            <phase>package</phase>
            <goals>
                <goal>attach-artifact</goal>
            </goals>
            <configuration>
                <artifacts>
                    <artifact>
                        <file>${patchFile}</file>
                        <type>zip</type>
                        <classifier>wildfly-${wildfly.version}-patch</classifier>
                    </artifact>
                </artifacts>
            </configuration>
        </execution>
    </executions>
</plugin>
...

运行构建

在完成所有配置后,可以通过运行mvn clean install来构建补丁文件。创建的补丁文件应该具有以下结构

target/eclipse-collections-8.1.0-wildfly-10.1.0.Final-patch.zip
├── META-INF
├── README.txt
├── layer-base-wildfly-10.1.0.Final-eclipse-collections-8.1.0
│   └── modules
│       └── org
│           └── eclipse
│               └── collections
│                   ├── api
│                   │   └── main
│                   │       ├── eclipse-collections-api-8.1.0.jar
│                   │       └── module.xml
│                   └── main
│                       ├── eclipse-collections-8.1.0.jar
│                       └── module.xml
├── misc
└── patch.xml

正如我们预期的那样,补丁包含Eclipse Collections JAR文件以及相应的module.xml描述符。patch.xml描述符包含补丁基础设施的元数据,例如,此补丁可以应用的WildFly版本以及添加的模块的哈希校验和。

应用和使用补丁

一旦创建了补丁,我们可以使用随WildFly一起提供的jboss-cli工具来应用它。

<JBOSS_HOME>/bin/jboss-cli.sh "patch apply --path path/to/eclipse-collections-8.1.0-wildfly-10.1.0.Final-patch.zip"

如果补丁已成功应用,您应该看到以下输出

{
    "outcome" : "success",
    "result" : {}
}

然后您就可以在您的部署应用程序中使用Eclipse Collections API。只需确保将两个新模块暴露给您的应用程序。为此,请将一个名为META-INF/jboss-deployment-structure.xml描述符添加到您的部署单元中

src/main/resources/META-INF/jboss-deployment-structure.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure
    xmlns="urn:jboss:deployment-structure:1.2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <deployment>
        <dependencies>
            <module name="org.eclipse.collections.api" />
            <module name="org.eclipse.collections" />
        </dependencies>
    </deployment>
</jboss-deployment-structure>

如果您想尝试创建自己的WildFly补丁,请查看GitHub上的此示例项目。它包含创建Eclipse Collections补丁的完整pom.xml。还有一个集成测试模块,该模块接收补丁文件,将其应用到WildFly实例上,并运行一个小的测试(使用Arquillian),在服务器上调用Eclipse Collections API。

如果您对这篇博客文章有任何反馈或想分享您对WildFly修复基础设施的经验,请在我们下面的评论中告诉我们。


返回顶部