Maven Combat (ix)--Packaging tips

Source: Internet
Author: User
Tags zip maven central

The word "pack" sounds relatively earthy, the more formal version should be "Build the project package", specifically, the project will be a variety of files, such as source code, compile generated bytecode, configuration files, documents, in accordance with the canonical format of the generation of archives, the most common of course is the jar package and war package, The example of a complex point is the bundle of the MAVEN official download page, which has a custom format that is easy for users to unzip and use at the command line. As a "packaging tool", MAVEN naturally has the obligation to help users create a variety of packages, the specification of the jar package and war package naturally no longer, a slightly more complex custom packaging format must also support, this article introduces some common packaging cases and related implementation, in addition to some of the previous mentioned packages, You can also see how to generate source packages, Javadoc packages, and CLI packages that can be run directly from the command line. the meaning of packaging

Any MAVEN project needs to define the POM element packaging (the default value is jar if not written). As the name implies, this element determines how the project is packaged. In the actual case, if you do not declare the element, MAVEN will help you build a jar package; If you define the value of the element as war, you will get a war package, and if you define its value as a pom (such as a parent module), none of the packages will be generated. In addition, MAVEN supports some other popular packaging formats, such as EJB3 and ear, by default. You don't need to know the specifics of the package, all you have to do is tell maven, "What kind of Project am I," and that's the power of the Convention over configuration.

To better understand Maven's default packaging, let's take a look at what's going on behind a simple statement, perform a MVN package operation on a Jar project, and see the following output:

[INFO]---maven-jar-plugin:2.3.1:jar (default-jar) @ git-demo---
[info] Building jar:/home/juven/git_juven/ Git-demo/target/git-demo-1.2-snapshot.jar

In contrast, the MVN package operation is performed on a war project, and the output is this:

[INFO]---maven-war-plugin:2.1:war (default-war) @ webapp-demo---
[info] Packaging webapp
[INFO] Assembling WebApp [Webapp-demo] in [/home/juven/git_juven/webapp-demo/target/webapp-demo-1.0-snapshot]
[INFO] Processing War Project
[INFO] Copying webapp resources [/home/juven/git_juven/webapp-demo/src/main/webapp]
[INFO] Webapp assembled in [msecs]
[INFO] Building War:/home/juven/git_juven/webapp-demo/target/ Webapp-demo-1.0-snapshot.war

In response to the same package lifecycle phase, Maven called Maven-jar-plugin for the Jar project, called Maven-war-plugin for the War project, in other words, packaging directly affects the MAVEN build lifecycle. It's important to understand that, especially when you need to customize the packaging behavior, you have to know which plugin to configure. A common example is to exclude certain Web resource files when you package a war project, and you should configure Maven-war-plugin as follows:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId> maven-war-plugin</artifactid>
    <version>2.1.1</version>
    <configuration>
      <webResources>
        <resource>
          <directory>src/main/webapp</directory>
          < excludes>
            <exclude>**/*.jpg</exclude>
          </excludes>
        </resource>
      </webResources>
    </configuration>
  </plugin>
Source Package and Javadoc package

As explained in the article, "Coordinate planning" in this column, a MAVEN project generates only one main component, which is needed when other dependencies are generated. Classifier. Source and Javadoc packages are excellent examples of ancillary components. They have a wide range of uses, especially source packages, when you use a third-party dependency, sometimes you want to go directly into that dependent source in the IDE to see the details of its implementation, if the dependency is to publish the source package to the MAVEN repository, It is convenient to download the source package and link it to your project, like Eclipse, through the M2eclipse plugin. Since generating the source package is a very common requirement, MAVEN has provided a plugin to help users with this task:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId> maven-source-plugin</artifactid>
    <version>2.1.2</version>
    <executions>
      <execution>
        <id>attach-sources</id>
        <phase>verify</phase>
        <goals >
          <goal>jar-no-fork</goal>
        </goals>
      </execution>
    </executions >
  </plugin>

Similarly, the build Javadoc package only needs to be configured with the plugin as follows:

  <plugin>          
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId> maven-javadoc-plugin</artifactid>
    <version>2.7</version>
    <executions>
      < execution>
        <id>attach-javadocs</id>
          <goals>
            <goal>jar</goal>
          </goals>
      </execution>
    </executions>
  </plugin>    

To make it easier for all MAVEN users to use the vast resources in the MAVEN central repository, the maintainer of the central repository forces the source package and the Javadoc package to be available when the project is submitted to the component. This is a good practice, and readers can also try to implement it within their own company to facilitate communication between different projects. Executable CLI Package

In addition to the usual jar packages, war packages, source packages, and Javadoc packages, another commonly used package is a CLI (command line) package that can be run directly on the command lines. The default maven-generated jar package contains only the. class files and project resource files that were compiled, and a jar file that can be run directly from the command line through a Java command, and also satisfies two conditions:/meta-inf/manifest in the jar package. The MF metadata file must contain main-class information. All dependencies of the project must be in Classpath.

MAVEN has several plug-ins to help the user do the above tasks, but the most convenient or maven-shade-plugin, it allows the user to configure the value of Main-class, and then in the packaging of the value to fill in/meta-inf/manifest. MF file. With regard to project dependencies, it is very clever to extract all the dependent jar files and then merge the resulting. class files with the. class files of the current project into the final CLI package, so that all the required classes are in Classpath when executing the CLI jar file. Here is a sample configuration:

 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin< /artifactid> <version>1.4</version> <executions> <execution> <phase> ;p ackage</phase> <goals> <goal>shade</goal> </goals> <c onfiguration> <transformers> <transformer implementation= "Org.apache.maven.plugins.shade . Resource.
            Manifestresourcetransformer "> <mainClass>com.juvenxu.mavenbook.HelloWorldCli</mainClass> </transformer> </transformers> </configuration> </execution> & Lt;/executions> </plugin> 

In the above example, My main-class is Com.juvenxu.mavenbook.HelloWorldCli, after the build is complete, corresponds to a regular Hello-world-1.0.jar file, I also get a Hello-world-1.0-cli.jar file. The attentive reader may have noticed that this is the classifier of the CLI. Finally, I can run the program through the Java-jar hello-world-1.0-cli.jar command. Custom Format Packages

The actual software projects often have more complex packaging requirements, such as we may need to provide customers with a product bundle, this package does not only contain the project bytecode files, but also contains dependencies and related script files to facilitate the customer decompression can be run, in addition to the distribution package also contains some necessary documents. At this point the source directory structure of the project is basically this:

Pom.xml
src/main/java/
src/main/resources/
src/test/java/
src/test/resources/
src/main/ scripts/
src/main/assembly/
README.txt

In addition to the basic Pom.xml and general Maven catalogs, there is also a src/main/scripts/directory that contains script files such as run.sh and run.bat,src/main/assembly/ Will contain a assembly.xml, which is a packaged profile, described later, and the final README.txt is a simple document.

We want to eventually generate a zip-format bundle that contains a structure like this:

bin/
lib/
README.txt

Where the bin/directory contains executable scripts run.sh and run.bat,lib/directories contain the project jar package and all dependent jar,readme.txt are the documents mentioned earlier.

After describing the requirements, we're moving out of MAVEN's most powerful packaging plugin: Maven-assembly-plugin. It supports a variety of packaged file formats, including Zip, tar.gz, tar.bz2, and more, through a packaged profile (in this case, Src/main/assembly.xml) that helps users choose which file collections, dependencies, modules, and even local warehouse files to package, The specific package path for each item is freely controlled by the user. The following is a package description file that corresponds to the above requirements Src/main/assembly.xml:

<assembly> <id>bin</id> <formats> <format>zip</format> </formats> &L t;dependencysets> <dependencySet> <useProjectArtifact>true</useProjectArtifact> <o
    utputdirectory>lib</outputdirectory> </dependencySet> </dependencySets> <fileSets> <fileSet> <outputDirectory>/</outputDirectory> <includes> <include>readm e.txt</include> </includes> </fileSet> <fileSet> &LT;DIRECTORY&GT;SRC/MAIN/SCR ipts</directory> <outputDirectory>/bin</outputDirectory> <includes> <includ
  e>run.sh</include> <include>run.bat</include> </includes> </fileSet> </fileSets> </assembly>
First, the ID of this assembly.xml file corresponds to the classifier of its final generated file. Next formats defines the file format that the package generates, and here is the zip. So we're going to get a file named Hello-world-1.0-bin.zip with the ID. (assuming that Artifactid is hello-world,version to 1.0) Dependencysets is used to define the selection dependency and define what directory is ultimately packaged, and here we declare that a depenencyset by default contains all dependencies, The useprojectartifact means that the artifacts generated by the project itself are also included and eventually packaged into the Lib path within the output package (specified by OutputDirectory). Filesets allows users to control packaging through the granularity of files or directories. Here the first Fileset packages the README.txt file to the root of the package, and the second Fileset packages the run.sh and Run.bat files under src/main/scripts into the bin directory of the output package.

The package description file supports configurations that are far beyond the scope of this article, and in order to avoid the reader being distracted by too much detail, this is no longer the case, and the reader can refer to this document if necessary.

Finally, we need to configure Maven-assembly-plugin to use a packaged profile and bind the lifecycle phase to automate the packaging operation:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId> maven-assembly-plugin</artifactid>
    <version>2.2.1</version>
    <configuration>
      <descriptors>
        <descriptor>src/main/assembly/assembly.xml</descriptor>
      </ descriptors>
    </configuration>
    <executions>
      <execution>
        <id> make-assembly</id>
        <phase>package</phase>
        <goals>
          <goal>single </goal>
        </goals>
      </execution>
    </executions>
  </plugin>

After running the MVN clean package, we can get a bundle named Hello-world-1.0-bin.zip in the target/directory. Summary

Packaging is one of the most important components of project building, this article describes the main MAVEN packaging techniques, including the principle of default packaging, how to create a source and Javadoc package, how to make a CLI package that can run on a command line, and how to customize the packaging format based on personalization requirements. This involves a lot of Maven plugins, and of course the most important and most complex and powerful packaging plugin is maven-assembly-plugin. In fact, Maven's own distribution is produced through the Maven-assembly-plugin, interested readers can directly see the source of a glimpse.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.