Maven assembly plugin - multiple descriptors? - maven

The goal is to create a single ZIP file, but split the configuration of the Maven Assembly plugin into a general and more specific descriptor.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<descriptors>
<descriptor>${project.basedir}/../src/assembly/rest-executables.xml</descriptor>
<descriptor>${project.basedir}/../../src/assembly/deliverables.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
However, when the two custom descriptors have unique IDs, two ZIP files are created - each with the expected contents. When the IDs are identical, only the last descriptor is executed (or it overwrites the previous contents).
Is what I'm attempting not possible or am I missing an option somewhere like 'append to existing ZIP' rather than 'always create new ZIP'?

I was able to fix it by for removing inner descriptor tags
<configuration>
<descriptors>${project.basedir}/../src/assembly/rest-executables.xml,${project.basedir}/../../src/assembly/deliverables.xml</descriptors>
</configuration>

Component Descriptors is definitely the way to go. Yes, I am pulling from the comments, but that is because the accepted answer did not work and I wanted to highlight what #user944849 said.
The accepted answer doesn't actually make a difference to the maven assembly plugin, it is just a different way to convey multiple descriptors.
Component Descriptors however, allow you to define a "component" that can be used in an assembly. So you can define a common set of files, without having to copy and paste all of them into different assemblies.

Related

Create Symlink for dependencies in Maven assembly

I have a Maven assembly that after unpacking the tar, creates three directories
each containing a /lib directory. So e.g.
folder1/lib
folder2/lib
folder3/lib
Currently, I am packing a same .jar in each of these /lib directories. Since this is a waste of space, I was wondering if I could have just one copy of that .jar and create something like a symlink for other two locations that could reference that .jar?
Thanks!
Here is my solution with maven-antrun-plugin for very similar situation. Zookeeper dependencies are previously placed into ${basedir}/target/package/lib by maven-dependency-plugin. Now I'm creating symlinks for all libraries into ${basedir}/target/package/lib/zookeeper/lib which point 2 dirs upper.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>prepare-delivery</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- Prepare zookeeper layout. -->
<mkdir dir="${basedir}/target/package/lib/zookeeper/lib"/>
<apply executable="ln" dir="${basedir}/target/package/lib/zookeeper/lib" relative="true">
<arg value="-s"/>
<srcfile prefix="../../"/>
<targetfile/>
<fileset dir="${basedir}/target/package/lib" includes="**"/>
<mapper type="identity"/>
</apply>
</target>
</configuration>
</execution>
</executions>
</plugin>
Plugin management for antrun is set as following:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
</plugin>
I believe this is unsupported in Maven packaging and assembly. Another Stack Overflow question from just a year ago asked the same thing and got the "unsupported" answer. And there have been two JIRAs on this feature (at least) that have been open for quite some time: one for the assembly plugin and one for Plexus components. I would say this the odds of this ever being directly supported are not good.
Just FYI, if I say "source project," I'll be refering to the project that assembled the tar. If I say "destination project," I'll mean the one unpacking the tar. This is assuming you have Maven projects on both sides- if that assumption is wrong, you should rely on command line utilities to do the tar-ing or untar-ing for you.
Since it sounds to me like you are unpacking the tar in the context of a Maven build, there are ways of working around this. As far as I know, the best solution if symlinking is important to you is to use either the junction plugin, the exec-maven-plugin, or the maven-antrun-plugin.
The junction plugin has the advantage of being portable, even on Windows. The problem is the project doing the unpacking must have explicit knowledge of the structure of the original structure of the tar, which is generally not desirable as it will now have to be updated should the intended symlinking that is changed. The plugin also seems to be pretty unmaintained, so there's that.
The exec plugin will allow you to call commandline utilities or scripts to do your linking, but you will have to toy with profiles to get crossplatform capabilities. The best benefit of doing it this way is that the project doing the unpacking is completely agnostic of the original structure of the tar. The details of the mechanism are in the question from a year ago that I mentioned above.
For my project, I am probably going to use antrun for Ant's symlink task- it is possible to have Ant record all symlinks to a file on the source side, and then package that file along with Maven. The receiving project can then check for the file and recreate its symlinks. This allows the symlinking intended for the tar distribution to be changed from its source project with no changes on the destination project. My project only supports OS X and Linux, so this is acceptable- you will need to decide which is best for you.
In either case, you will unfortunately have a situation where the project doing the unpacking must have knowledge about the way the tar was before being packed.
You can use symlink task/goal of ant-run plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>package</phase>
<configuration>
<target>
<symlink link="folder2/lib/${project.artifactId}-${project.version}.jar"
resource="folder1/lib/${project.artifactId}-${project.version}.jar"/>
<symlink link="folder3/lib/${project.artifactId}-${project.version}.jar"
resource="folder1/lib/${project.artifactId}-${project.version}.jar"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
If you want the symlinks to have relative path, you can give relative path in resource like below
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>package</phase>
<configuration>
<target>
<symlink link="folder2/lib/${project.artifactId}-${project.version}.jar"
resource="../../folder1/lib/${project.artifactId}-${project.version}.jar"/>
<symlink link="folder3/lib/${project.artifactId}-${project.version}.jar"
resource="../../folder1/lib/${project.artifactId}-${project.version}.jar"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

Rename using regex on maven-dependency-plugin:copy-dependencies

I'd like to rename all dependencies to strip off SNAPSHOT so my file handling scripts and installer don't break when I release.
I presently, use maven-dependency-plugin:copy-dependencies and copy with individual artifacts listed and renamed. I'd rather have something akin to ant's regex mapper establish a renaming rule.
Presently, I plan to copy-dependencies to 1st stage directory in prepare-package and use antrun's copy + regex mapper in package to copy/rename but that wastes time and space.
Is there a more direct way to approach this problem? Can the dependency plugin handle rule based renames?
Thanks
Peter
If you just want to remove the version from the dependencies, then add the stripVersion parameter to the plugin configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>copy-dependencies</id>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<silent>true</silent>
<outputDirectory>libs</outputDirectory>
<stripVersion>true</stripVersion>
<includeTypes>swc</includeTypes>
<excludeGroupIds>com.adobe.flex.framework</excludeGroupIds>
<excludeTypes>pom</excludeTypes>
</configuration>
</execution>
</executions>
</plugin>

Read a file into a Maven property

Is it possible to read a file and store the entire contents into a Maven property?
I'm trying to generate some custom JavaDocs, and they have an option to set a header, but it has to be a string, not a file name (for some reason). I obviously don't want to put a bunch of HTML into my pom.xml, so I need a way to read my header.html as a Maven property.
Is this possible? I'm not able to find a standard way, but it seems like a Maven plugin might do this.
Apparently Ant has what I want, but I'd prefer something lighter weight than the Ant task.
See this question on SO. And here is the properties-maven-plugin.
If you'd like not to use .properties file, than I can suggest to use the Groovy plugin and a small script that I've written:
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<properties>
<header_file>header.html</header_file>
</properties>
<source>
def file = new File(project.properties.header_file)
project.properties.header_content = file.getText()
</source>
</configuration>
</execution>
</executions>
</plugin>
After execution of this plugin, you should be able to refer to ${header_content} property that contains header.html file contents.

Jboss Maven JdocBook Plugin, Multiple Executions

My team is working on a webservice project, and I am working on creating the documentation for the web service API. I have used a custom JavaDoc doclet to create two xml outputs of the available methods, one for internal developers and one for external developers.
Now, we are using the Jboss Maven Jdocbook plugin to create a DocBook output, along with other xml files, to create a users guide for our webservices.
What I want to do is run the Maven JdocBook plugin twice, once using the internal methods and once on the external methods, to create two separate users guides for either internal or external developers, using two different master.xml files. The pom file:
<build>
<defaultGoal>generate</defaultGoal>
<plugins>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-plugin</artifactId>
<extensions>true</extensions>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<formats>
<format>
<formatName>html</formatName>
</format>
<format>
<formatName>html_single</formatName>
</format>
</formats>
</configuration>
<executions>
<execution>
<id>internal</id>
<phase>compile</phase>
<configuration>
<baseOutputDirectory>../../Test/JavaDocTest/internal/</baseOutputDirectory>
<sourceDocumentName>masterInternal.xml</sourceDocumentName>
</configuration>
</execution>
<execution>
<id>external</id>
<phase>compile</phase>
<configuration>
<baseOutputDirectory>../../Test/JavaDocTest/external/</baseOutputDirectory>
<sourceDocumentName>masterExternal.xml</sourceDocumentName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jboss.maven.plugins</groupId>
<artifactId>maven-jdocbook-style-plugin</artifactId>
<version>1.0.0</version>
<extensions>true</extensions>
</plugin>
</plugins>
The problem I am running in to is that unless I put the sourceDocumentName in the base configuration (outside of the execution section and in the section with the formats) the build does not recognize the different source document name. The standard master file is called master.xml, and on compiling in NetBeans, it says it is looking for master.xml, which it can't find because it does not exist, and then skips the generation.
It is appearing to just skip the execution sections altogether, as when I try to run the build with multiple executions (such as above) it still just runs once. Any ideas why it's skipping the execution sections?
I believe it might have something to do with the phase tag of the execution, but according to http://www.jboss.org/maven-jdocbook-plugin/ there are only a few phases (process-resources, compile, package, install, deploy), and I've tried all of them and none of them seem to work.
Thanks in advance.
My group figured out that you need to set sourceDocumentName in the main configuration area. It turns out that the docbook is generated once using the main config section, and then it looks for any other executions and runs those using the specific sub-configuration for that execution.
Hope this helps someone in the future.

get maven to replace values based on user/build.properties

im at the point in my project where im moving data connections to the beta and production databases for testing. obviously, having the alpha database credentials stored in the source repository is fine, but the beta and production credentials, id be put in front of a firing squad for that one.
i know maven can have a {userdir}/build.properties file. this is the file i want to use to keep the db credentials out of the source repository. but i can't seem to get maven to figure out that for file x.cfg.xml it has to replace values.
so i have in one of my hibernate.cfg.xml files this line
<property name="hibernate.connection.url">#ssoBetaUrl#</property>
now how do i get maven to replace that variable with the value thats in the {userdir}/build.properties file?
edit-------------
ive been playing with the properties-maven-plugin plugin but i seem to not be able to get it to fire. i put this in my parent pom
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<id>read-properties</id>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
</execution>
</executions>
</plugin>
but when it builds, it does not fire. if im reading http://maven.apache.org/maven-1.x/reference/properties.html right it should find the build properties file in the ~/build.properties folder and go from there, but im not sure.
I think you are approaching this the wrong way around. Instead of having the build process bake the appropriate connection details into the JAR file you should instead have the program look for a configuration file at startup.
Typically, my hibernate based apps, will look for a file under %user.home&/.appname/config.properties and load DB credentials and other deployment specfic data from there. If the file is missing, a default version can be included in the JAR and copied to this location (on initial startup so you don't have to copy-paste the file to new systems) that is then edited with appropriate settings.
This way, you can use the same build to produce JAR (or WAR) files for test and production servers, the differences will be in the (presumably already deployed) configuration files. This also makes it possible to have multiple production deployments, each talking to a different database, without any complications in the build process.
You could use two plugins.
properties-maven-plugin
replacer
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>{userdir}/build.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.2</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>target/**/*.*</include>
</includes>
<replacements>
<replacement>
<token>#ssoBetaUrl#</token>
<value>http://[anyURL]</value>
</replacement>
</replacements>
</configuration>
</plugin>

Resources