Using the Project Assembly to Create Example Projects
By Tim OBrien
3 minute read time
Anders Nawroth of the Neo4J project asked an interesting question on the neo4j-user list:
What's the best option when deploying neo4j code examples
using Maven? It's really not of any interest to deploy the artifact
itself, it's the sources (if possible with some exclusion of resources)
that we want.
Anders' requirements: create a project which packages itself, wire the appropriate goal into the lifecycle. He's headed in the right direction, the Maven Assembly Plugin, but he might not know about the pre-defined assembly descriptors as they are somewhat hidden on the Apache Maven site. Since other projects might have similar requirements, here's a quick explanation of all the moving parts...
What is the Maven Assembly Plugin?
The Maven Assembly Plugin allows you to create an archive with an arbitrary structure. If you have a project which needs to produce a ZIP file with a bin/ directory an a set of shell scripts, or if you want to create an archive which contains a particular project's bytecode and all the runtime dependencies, Maven Assembly Plugin is the place to look. To generate an archive, you'll need to do a few things:
- Include the Maven Assembly Plugin in your project's pom.xml file.
- Configure an assembly by referencing a built-in assembly or define your own assembly.
- (optional) configure the lifecycle to bind the assembly goal to the package phase of the lifecycle.
What is an Assembly?
The Maven Assembly Plugin produces an assembly of files and folders using an Assembly descriptor which describes the contents of a directory. You can use one of several predefined assembly descriptors which are built into the Maven Assembly plugin, or you can define your own assembly by configuring your assembly in an assembly descriptor. An assembly descriptor is an XML file which selects files and directories to include in the final, assembled artifact.
Just what sort of "assemblies" can you create on your own with an Assembly descriptor? Just about anything, a collection of .class files and all of your runtime dependency JARs? Sure. The assembly descriptor is flexible enough to describe just about anything. If you want a full explanation of the power of Maven Assemblies, read the Assemblies Chapter of the Free Maven Book or Chapter 4 which introduces a built-in assembly descriptor.
A Project Which Assembles Itself
Back to Anders' requirements, he wants a project that can package itself up as an example project. He also wants this assembly to be created when he runs mvn deploy. To do this, he can use the built-in project descriptor. Adding the following plugin configuration to any project will configure this built-in project descriptor to create an assembly of a project itself (a self-replicating project) and the executions section will attach the "assembly:attached" goal to the package phase of the lifecycle.
<build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>project</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>examples</id> <phase>package</phase> <goals> <goal>attached</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
Go ahead, try it. Run mvn package or mvn deploy and you'll end up with an assembly in ${basedir}/target. If you want to customize the name of the final product, use the finalName element in the build section of your POM.
The Lifecycle
My next post will likely be on the lifecycle, I've had a few questions from people over the past few weeks about running specific goals directly from the command-line. It appears that many people haven't fully grok'd the Maven Lifecycle. Many people grew familiar with Maven 1, the way that people customized a build in Maven 1 was to string along a number of goals. If you needed to run a specific goal, you would just craft a long command line. In Maven 2, you should shy away from running specific goals on the command line, and you should configure executions (see above). This is the more natural way to customize a build, think of it as hooking your own project's customized goals to the default lifecycle. If you find yourself running "mvn deploy assembly:assembly" often, you should take a look at the executions element in your plugin configuration.
For more information about the Maven 2 Lifecycle, read Chapter 10: Lifecycles.
Written by Tim OBrien
Tim is a Software Architect with experience in all aspects of software development from project inception to developing scaleable production architectures for large-scale systems during critical, high-risk events such as Black Friday. He has helped many organizations ranging from small startups to Fortune 100 companies take a more strategic approach to adopting and evaluating technology and managing the risks associated with change.
Explore All Posts by Tim OBrien