Create Symlink for dependencies in Maven assembly - maven

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>

Related

Are directions available for the maven plugin com.alexnederlof jasperreports-plugin?

I have read up on the limited information regarding com.alexnederlof jasperreports-plugin and I'm looking to convert my current ant build to use this maven plugin, but there doesn't seem to be any documentation available.
My biggest concern is run-time: If I use this plugin at build-time, what version of jasper-reports do I need to use at run-time?
Am I missing a reference somewhere? As the old adage goes, "If there isn't any documentation, then I guess I'll have to write it."
I am not sure of what you are after but, I am using this plugin in maven to generate the source .jrxml files to .jasper files and the configuration in pom goes like this:
<plugin>
<groupId>com.alexnederlof</groupId>
<artifactId>jasperreports-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>jasper</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- These are the default configurations: -->
<compiler>net.sf.jasperreports.engine.design.JRJdtCompiler</compiler>
<sourceDirectory>src/main/jasperreports</sourceDirectory>
<outputDirectory>${basedir}/src/main/webapp</outputDirectory>
<outputFileExt>.jasper</outputFileExt>
<xmlValidation>true</xmlValidation>
<verbose>false</verbose>
<numberOfThreads>4</numberOfThreads>
<failOnMissingSourceDirectory>true</failOnMissingSourceDirectory>
<sourceScanner>
org.codehaus.plexus.compiler.util.scan.StaleSourceScanner
</sourceScanner>
</configuration>
</plugin>
Hope this helps

Maven assembly plugin - multiple descriptors?

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.

How to create a windows cabinet file using Maven 3?

I'm new to Apache Maven and would like to know a way to create a windows cabinet file as part of the maven build life cycle.
I was hoping there would be a plugin for the task, but can't seem to locate one.
Help appreciated.
Edit: It looks like the Ant Cab task relies on a dependency that no longer exists. Other resources point to using a Cab creator written in Java, the lcab tool if you're on Linux, or makecab.exe on Windows. Another option would be to use a zip file, which is more widely supported.
What you're looking for the AntRun plugin for Maven, which will then give you access to the Ant Cab task.
Here is an untested example of what you would add to your POM in the plugins section:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>ant-example</id>
<phase>prepare-package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<cab cabfile="target/example.cab" basedir="deploy/folder"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>

rename jsp file in target dir just before packing using maven

I ve got an maven based web project including the "normal" directory structure.
I've the need to generate to war artifacts, one is the normal app, the other is an admin "version", which is realised by using 2 different maven-profiles.
In case of the admin version I need to rename a JSP-file just before the war file is packaged.
How can I do this?
Which maven-plugin fits this requirement?
IMHO you must use ant run to rename your files and attach this execution to prepare-package phase.
sorry, but to copy/rename the JSPs during prepare-package phase doesn't work, because the files are not yet in the target directory at this point.
sample code:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>prepare-package</phase>
<configuration>
<target>
<copy file="${project.build.directory}\myProject\loginAdmin.jsp"
tofile="${project.build.directory}\myProject\loginUser.jsp"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

Integrating ant resource generation targets into a Maven build

I'm currently working on a fairly large project that has been migrated from Ant to Maven. There are no problems with the actual build process (it compiles and packages the source code fine).
The problem is that I also have a lot of targets that generate additional resources for the project (compile LessCSS, generate & upload documentation, generate tld files for custom tags and functions etc.). I am not sure how I should handle these tasks. Let's take the target that builds CSS&JS as an example (the others are more or less similar, but not connected). It looks like this (simplified):
<target name="build.css_js">
<concat destfile="${webapp.dir}/scripts/main.js">
<fileset dir="${webapp.dir}/scripts/src" includes="*.js"/>
</concat>
<!-- build css files from less sources -->
<taskdef name="lesscss" classname="com.asual.lesscss.LessEngineTask" classpathref="libraries" />
<lesscss input="${webapp.dir}/syles/src/input.less" output="${webapp.dir}/styles/output.css" />
</target>
In the pom.xml I have the following plugin set up:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<configuration>
<tasks>
<echo message="Hello World from pom.xml"/>
<ant target="build.css_js"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
The dependencies I'm using are no longer in our SVN repository (since they are managed by Maven), so I switched the libraries variable to point to the Maven repo:
<property name="lib.dir" location="${env.HOMEPATH}/.m2/repository" />
This is not good, as that path may be valid only on my machine. I don't know any other way to reference the libraries from the Maven repository and I need them to run the ant targets.
Is my approach ok or is there a better way of doing things?
How do I get over the library problem?
Some resources are needed when packaging the project but some are not. Is there a lifecycle phase that is out of scope for compile/package? I found the site lifecycle which I think fits my needs.
Ideally, I should give up on the ant build file altogether, but I'm not sure it's worth the effort of making the scripts run as maven plugins (I currently have no idea how to do that). What do you think about this?
I'm new to Maven so any suggestions are appreciated.
Generally embedding antrun calls is not ideal, but if you've not found a suitable plugin to do what you need then I wouldn't worry about it. If the processing is fairly simple it is actually quite easy to embed it in a Maven plugin yourself, see this example for help getting started.
If you are going with antrun, and the dependency jars have already been installed to your Maven repository, you can configure the antrun plugin to use those jars in its execution by adding them as dependencies of the plugin configuration. This means the dependencies will be resolved and available for use, but not be visible to your project (useful to help avoid accidental inclusion). To then access them in a portable way you can use:
<property name="lib.dir" location="${settings.localRepository}" />
Alternatively you can use some of the other properties available to expose the Maven classpaths to the antrun plugin, for example ${maven.compile.classpath} See the antrun documentation for more details.
If you have multiple discrete executions for ant, you can configure them individually in the antrun plugin and specify a suitable id for each one. The example below shows two executions, both bound to the process-resources phase. Of course you need to supply some actual goals.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>build-css</id>
<phase>generate-resource</phase>
<configuration>
<target>
...
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>build-js</id>
<phase>generate-resource</phase>
<configuration>
<target>
...
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>some.group.id</groupId>
<artifactId>artifactId</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>another.group.id</groupId>
<artifactId>anotherId</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>

Resources