The assembly descriptor

The assembly descriptor is an XML-based configuration, which defines how to build an assembly and how its content should be structured.

If we go back to our example, the attached goal of the assembly plugin creates a binary distribution according to the assembly descriptor, both in the test and package phases of the default Maven lifecycle. The assembly descriptors for each phase can be specified under the descriptors element. As in this particular example, there can be multiple descriptor elements defined under the descriptors parent element. For the package phase, it has the following three assembly descriptors:

<descriptors>
  <descriptor>src/assembly/bin.xml</descriptor>
  <descriptor>src/assembly/src.xml</descriptor>
  <descriptor>src/assembly/docs.xml</descriptor>
</descriptors>

Each descriptor element instructs the assembly plugin where to load the descriptor, and each descriptor file will be executed sequentially in the defined order.

Let's have a look at the src/assembly/bin.xml file, shown as follows. The file path is given relative to the root POM file under the distribution module. You can find the complete bin.xml file at https://svn.wso2.org/repos/wso2/carbon/platform/branches/turing/products/is/5.0.0/modules/distribution/src/assembly/bin.xml:

<assembly>
  <formats>
    <format>zip</format>
  </formats>

The value of the format element specifies the ultimate type of the artifact to be produced. It can be zip, tar, tar.gz, tar.bz2, jar, dir, or war. You can use the same assembly descriptor to create multiple formats. In this case, you can include multiple format elements under the formats parent element.

Note

Even though you can specify the format of the assembly in the assembly descriptor, it is recommended that you do this via the plugin configuration itself. In the plugin configuration, you can define different formats for your assembly shown as follows. The benefit here is that you can have multiple Maven profiles to build different archive types. We will be talking about Maven profiles in Chapter 9, Best Practices:

<configuration>
  <formats>
    <format>zip</format>
  </formats>
</configuration>
  <includeBaseDirectory>false</includeBaseDirectory>

When the value of the includeBaseDirectory element is set to false, the artifact will be created with no base directory. If this is set to true, which is the default value, the artifact will be created under a base directory. You can specify a value for the base directory under the baseDirectory element. In most of the cases, the value of includeBaseDirectory is set to false so that the final distribution unit directly packs all the artifacts right under it, without having another root directory.

  <fileSets>
    <fileSet>
      <directory>target/wso2carbon-core-4.2.0</directory>
      <outputDirectory>wso2is-${pom.version}</outputDirectory>
      <excludes>
        <exclude>**/*.sh</exclude>

Each fileSet element under the fileSets parent element specifies the set of files to be assembled to build the final archive. The first fileSet element instructs to copy all the content from the directory (which is target/wso2carbon-core-4.2.0) to the output directory specified under the outputDirectory configuration element, excluding all the files defined under each exclude element. If no exclusions are defined, then all the content inside directory will be copied to the outputDirectory. In this particular case, the value of ${pom.version} will be replaced the by version of the artifact, which is defined in the pom.xml file under the distribution module.

The exclude element instructs not to copy any file that has the .sh extension from anywhere inside target/wso2carbon-core-4.2.0 to the outputDirectory.

        <exclude>**/wso2server.bat</exclude>
        <exclude>**/axis2services/sample01.aar</exclude>

The exclude element instructs not to copy the sample01.aar file inside a directory called axis2services from anywhere inside target/wso2carbon-core-4.2.0 to outputDirectory.

        <exclude>**/axis2services/Echo.aar</exclude>
        <exclude>**/axis2services/Version.aar</exclude>
        <exclude>**/pom.xml</exclude>
        <exclude>**/version.txt</exclude>
        <exclude>**/README*</exclude>
        <exclude>**/carbon.xml</exclude>
        <exclude>**/axis2/*</exclude>
        <exclude>**/LICENSE.txt</exclude>
        <exclude>**/INSTALL.txt</exclude>
        <exclude>**/release-notes.html</exclude>
        <exclude>**/claim-config.xml</exclude>
        <exclude>**/log4j.properties</exclude>
        <exclude>**/registry.xml</exclude>
      </excludes>
    </fileSet>
    <fileSet>
      <directory>../p2-profile-gen/target/wso2carbon-core- 4.2.0/repository/conf/identity
      </directory>
      <outputDirectory>wso2is-${pom.version}/repository/ conf/identity
      </outputDirectory>
      <includes>
        <include>**/*.xml</include>
      </includes>

The include element instructs to copy only the files that have the .xml extension from anywhere inside the ../p2-profile-gen/target/wso2carbon-core-4.2.0/repository/conf/identity directory to the outputDirectory. If no include element is defined, everything will be included.

    </fileSet>
    <fileSet>
      <directory>../p2-profile-gen/target/wso2carbon-core- 4.2.0/repository/resources/security/ldif
      </directory>
      <outputDirectory>wso2is-${pom.version}/repository/ resources/security/ldif
      </outputDirectory>
      <includes>
        <include>identityPerson.ldif</include>
        <include>scimPerson.ldif</include>
        <include>wso2Person.ldif</include>
      </includes>

The include element instructs to copy only the files having specific names from anywhere inside the ../p2-profile-gen/target/wso2carbon-core/4.2.0/repository/resources/security/ldif directory to the outputDirectory.

    </fileSet>
    <fileSet>
      <directory>../p2-profile-gen/target/wso2carbon-core- 4.2.0/repository/deployment/server/webapps
      </directory>
      <outputDirectory>${pom.artifactId}-${pom.version} /repository/deployment/server/webapps
      </outputDirectory>
      <includes>
        <include>oauth2.war</include>
      </includes>

The include element instructs to copy only the WAR file with the name oauth2.war from anywhere inside the ../p2-profile-gen/target/wso2carbon-core/4.2.0/repository/resources/deployment/server/webappas directory to the outputDirectory.

    </fileSet>
    <fileSet>
      <directory>../p2-profile-gen/target/wso2carbon-core- 4.2.0/repository/deployment/server/webapps
      </directory>
      <outputDirectory>${pom.artifactId}-${pom.version} /repository/deployment/server/webapps
      </outputDirectory>
      <includes>
        <include>authenticationendpoint.war</include>
      </includes>
    </fileSet>
    <fileSet>
      <directory>../styles/service/src/main/resources /web/styles/css
      </directory>
      <outputDirectory>${pom.artifactId}-${pom.version} /resources/allthemes/Default/admin
      </outputDirectory>
      <includes>
        <include>**/**.css</include>
      </includes>

The include element instructs to copy any file with the .css extension from anywhere inside the ../styles/service/src/main/resources/web/styles/css directory to the outputDirectory.

    </fileSet>
    <fileSet>
      <directory>../p2-profile-gen/target/WSO2-CARBON-PATCH- 4.2.0-0006
      </directory>
      <outputDirectory>wso2is- ${pom.version}/repository/components/patches/
      </outputDirectory>
      <includes>
        <include>**/patch0006/*.*</include>
      </includes>

The include element instructs to copy all the files inside the patch006 directory from anywhere inside the ../p2-profile-gen/target/WSO2-CARBON-PATCH-4.2.0-0006 directory to the outputDirectory.

    </fileSet>
  </fileSets>
  <files>

The file element is very similar to the fileSet element in terms of the key functionality. Both can be used to control the content of the assembly.

Tip

The file element should be used when you are fully aware of the exact source file location, while the fileSet element is much more flexible to pick files from a source based on a defined pattern.

The fileMode element in the following snippet defines a set of permissions to be attached to the copied file. The permissions are defined as per the four-digit octal notation. You can read more about the four-digit octal notation from http://en.wikipedia.org/wiki/File_system_permissions#Octal_notation_and_additional_permissions:

    <file>
      <source>../p2-profile-gen/target/WSO2-CARBON-PATCH- ${carbon.kernel.version}- 0006/lib/org.wso2.ciphertool-1.0.0-wso2v2.jar
      </source>
      <outputDirectory>${pom.artifactId}-${pom.version}/lib/
      </outputDirectory>
      <filtered>true</filtered>
      <fileMode>644</fileMode>
    </file>
  <files>
</assembly>

There are three descriptor elements defined under the assembly plugin for the package phase. The one we just discussed earlier will create the binary distribution, while the src/assembly/src.xml and src/assembly/docs.xml files will create the source distribution and the documentation distribution, respectively.

Let's also look at the assembly descriptor defined for the test phase:

<descriptors>
  <descriptor>src/assembly/dist.xml</descriptor>
</descriptors>

This is quite short and only includes the configuration required to build the initial distribution of WSO2 Identity Server. Even though this project does this at the test phase, it seems like it has no value in doing this. In this case, it seems like maven-antrun-plugin, which is also associated with the package phase but prior to the definition of the assembly plugin, needs the ZIP file distribution. Ideally, you should not have the assembly plugin run at the test phase unless there is a very strong reason. You might need the distribution ready to run the integration tests; however, the integration tests should be executed in the integration-test phase, which comes after the package phase. In most of the cases, the assembly plugin is associated with the package phase of the Maven default lifecycle.

<assembly>
  <formats>
    <format>zip</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <fileSets>
    <!-- Copying p2 profile and osgi bundles-->
    <fileSet>
      <directory>../p2-profile-gen/target/wso2carbon-core- 4.2.0/repository/components
      </directory>
      <outputDirectory>wso2is-${pom.version}/repository/components
      </outputDirectory>
      <excludes>
        <exclude>**/eclipse.ini</exclude>
        <exclude>**/*.lock</exclude>
        <exclude>**/.data</exclude>
        <exclude>**/.settings</exclude>
      </excludes>
    </fileSet>
  </fileSets>
  <dependencySets>
    <dependencySet>
      <outputDirectory>wso2is-${pom.version}/repository/ deployment/client/modules
      </outputDirectory>
      <includes>
        <include>org.apache.rampart:rampart:mar</include>
      </includes>
    </dependencySet>
  </dependencySets>
</assembly>

This configuration introduces a new element that we have not seen before: dependencySet. The dependencySet element lets you include/exclude project dependencies to/from the final assembly that we are building. In the previous example, it adds the rampart module into the outputDirectory. The value of the include element should be in the groupdId:artifactId:type[:classifier][:version] format. Maven will look for this artifact with the defined coordinates in its local Maven repository first, and if found, it will copy the artifact to the outputDirectory element.

Unlike the fileSet or file configuration, dependencySet does not define a concrete path to pick and copy the dependency from. Maven finds artifacts via the defined coordinates. If you want to include a dependency just by its groupId and the artifactId, then you can follow the groupdId:artifactId pattern. The particular artifact should be defined in the POM file, which has the assembly plugin defined under the dependencies section. You can find the following dependency definition for the rampart module in the POM file under the distribution module. If two versions of the same dependency are being defined in the same POM file (rather unlikely), then the last in the order will be copied.

<dependency>
  <groupId>org.apache.rampart</groupId>
  <artifactId>rampart</artifactId>
  <type>mar</type>
  <version>1.6.1-wso2v12</version>
</dependency>

You can also include a dependency by its groupId, artifactId, and type elements, as shown in the following configuration. Then, you can follow the groupdId:artifactId:type[:classifier] pattern. This is the exact pattern followed in the previous example:

<includes>
  <include>org.apache.rampart:rampart:mar</include>
</includes>

If you want to be more precise, you can also include the version in the pattern. Then, it will look like this:

<includes>
  <include>org.apache.rampart:rampart:mar:1.6.1-wso2v12
  </include>
</includes>

Note

Most of the time, we talk about four Maven coordinates; however, to be precise there are five. A Maven artifact can be uniquely identified by these five coordinates: groupdId:artifactId:type[:classifier]:version. We have already discussed about the four main coordinates, but not about the classifier. This is very rarely used; it can be quite useful in a scenario where we build an artifact out of the same POM file but with multiple target environments. We will discuss classifiers in detail in Chapter 9, Best Practices.

The previous example only covered a very little subset of the assembly descriptor. You can find all available configuration options at http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html, which is a quite exhausting list.

Tip

It is a best practice or a convention to include all the assembly descriptor files inside a directory called assembly, though it is not mandatory.

Let's have a look at another real-world example with Apache Axis2. Axis2 is an open source project released under the Apache 2.0 license. Axis2 has three types of distributions: a binary distribution as a ZIP file, a WAR file distribution, and a source distribution as a ZIP file. The binary ZIP distribution of Axis2 can be run on its own, while the WAR distribution must be deployed in a Java EE application server.

All three Axis2 distributions are created from the POM file inside the distribution module, which can be found at http://svn.apache.org/repos/asf/axis/axis2/java/core/trunk/modules/distribution/pom.xml. This POM file associates the single goal of the Maven assembly plugin with the project, which initiates the process of creating the final distribution artifacts. The assembly configuration points to three different assembly descriptors: one for the ZIP distribution, another for the WAR distribution, and a third one for the source code distribution.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <executions>
    <execution>
      <id>distribution-package</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
        <finalName>axis2-${project.version}</finalName>
        <descriptors>
          <descriptor>src/main/assembly/war-assembly.xml
          </descriptor>
          <descriptor>src/main/assembly/src-assembly.xml
          </descriptor>
          <descriptor>src/main/assembly/bin-assembly.xml
          </descriptor>
        </descriptors>
      </configuration>
    </execution>
  </executions>
</plugin>

Let's have a look at the bin-assembly.xml file, which is the assembly descriptor that builds the ZIP distribution:

<assembly>
  <id>bin</id>
  <includeBaseDirectory>true</includeBaseDirectory>
  <baseDirectory>axis2-${version}</baseDirectory>
  <formats>
    <!--<format>tar.gz</format>
    //uncomment,if tar.gz archive needed-->
    <format>zip</format>
  </formats>

This is exactly what we discussed earlier and exactly what we wanted to avoid due to the same reason as in the comment. If we want to build a tar.gz distribution, then we need to modify the file. Instead of doing this, we should have moved the format configuration element out of the assembly descriptor to the plugin configuration defined in the pom.xml file. Then, you can define multiple profiles and configure the archive type based on the profile.

  <fileSets>
  </fileSets>
  <dependencySets>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>

The useProjectArtifact configuration element instructs the plugin whether or not to include the artifact produced in this project build into the dependencySet element. By setting the value to false, we avoid it.

      <outputDirectory>lib</outputDirectory>
      <includes>
        <include>*:*:jar</include>
      </includes>
      <excludes>
        <exclude>org.apache.geronimo.specs:         geronimo-activation_1.1_spec:jar
        </exclude>
      </excludes>
    </dependencySet>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <outputDirectory>lib/endorsed</outputDirectory>
      <includes>
        <include>javax.xml.bind:jaxb-api:jar</include>
      </includes>
    </dependencySet>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <includes>
        <include>org.apache.axis2:axis2-webapp</include>
      </includes>

The includes and excludes configuration elements will make sure that all the JAR files defined under the dependencies section of the distribution/pom.xml file will be included in the assembly, except the JAR files defined under the excludes configuration element. If you do not have any include elements, all the dependencies defined in the POM file will be included in the assembly, except what is defined under the excludes section.

    <unpack>true</unpack>

Once the unpack configuration element is set to true, all the dependencies defined under the include elements will be unpacked to the outputDirectory. The plugin is capable of unpacking the jar, zip, tar.gz, and tar.bz2 archives. The unpackOptions configuration element, can be used to filter out the content of the dependencies getting unpacked. According to the following configuration, only the files defined under the include elements under the unpackOptions element will be included; the rest will be ignored and won't be included in the assembly. In this particular case, axis2-webapp is a WAR file and the distributions/pom.xml file has a dependency to it. This web app will be exploded, and then all the files inside the WEB-INF/classes and axis2-web directories will be copied into the webapp directory of the ZIP distribution along with the WEB-INF/web.xml file:

     <outputDirectory>webapp</outputDirectory>
      <unpackOptions>
        <includes>
          <include>WEB-INF/classes/**/*</include>
          <include>WEB-INF/web.xml</include>
          <include>axis2-web/**/*</include>
        </includes>
      </unpackOptions>
    </dependencySet>
  </dependencySets>
</assembly>

Now, let's have a look at war-assembly.xml, which is the assembly descriptor that builds the WAR distribution. There is nothing new in this configuration, except the outputFileNameMapping configuration element. As the value of the format element is set to zip, this assembly descriptor will produce an archive file conforming to the ZIP file specification. The value of the outputFileNameMapping configuration element gets applied to all the dependencies. The default value is parameterized, that is, ${artifactId}-${version}${classifier?}.${extension}. In this case, it's hardcoded to axis2.war, so the axis2-webapp artifact will be copied to outputDirectory as axis2.war. As there is no value defined for the outputDirectory element, the files will be copied to the root location.

<assembly>
  <id>war</id>
  <includeBaseDirectory>false</includeBaseDirectory>
  <formats>
    <format>zip</format>
  </formats>
  <dependencySets>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <includes>
        <include>org.apache.axis2:axis2-webapp</include>
      </includes>
      <outputFileNameMapping>axis2.war</outputFileNameMapping>
    </dependencySet>
  </dependencySets>
  <fileSets>
    <fileSet>
      <directory>../..</directory>
      <outputDirectory></outputDirectory>
      <includes>
        <include>LICENSE.txt</include>
        <include>NOTICE.txt</include>
        <include>README.txt</include>
        <include>release-notes.html</include>
      </includes>
    <filtered>true</filtered>
  </fileSet>
  </fileSets>
</assembly>
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.190.217.253