Normalize remote Maven repo JAR filename? - java

I'm building a web app with Dropwizard, and trying to use the Shiro bundle module (Maven repo) to integrate Shiro authentication.
My problem is that in the remote Maven repo the filename is dw-shiro-bundle-0.0.1-20130412.232035-4.jar, instead of dw-shiro-bundle-0.0.1-SNAPSHOT.jar. I understand this happens when you build the same SNAPSHOT version four times to avoid clobbering the first three, and the index takes care of finding the latest one.
However I'm also following this advice to avoid using maven-shade-plugin and effectively do the shading myself, since the final JAR is otherwise too big. maven-assembly-plugin is configured to copy the Shiro bundle JAR to lib/dw-shiro-bundle-0.0.1-SNAPSHOT.jar, but in the final JAR's MANIFEST.MF, the dependency is listed as io.ifar.dw-shiro-bundle-0.0.1-20130412.232035-4.jar, and hence I get a ClassDefNotFoundError at runtime.
A workaround is to manually rename the lib jar to io.ifar.dw-shiro-bundle-0.0.1-20130412.232035-4.jar so it gets picked up on the classpath, but it's not really a solution. Is there a way to either:
fix the MANIFEST.MF entry
normalize the name of third-party JARs as they are downloaded by Maven to strip any build numbers, or
automate the process of renaming the JAR file to include the build number?
My plugins are as follows:
In maven-jar-plugin:
<configuration>
<forceCreation>true</forceCreation>
<archive>
<manifest>
<mainClass>${mainClass}</mainClass>
<addClasspath>true</addClasspath>
<classpathLayoutType>custom</classpathLayoutType>
<customClasspathLayout>lib/${artifact.groupId}.${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}</customClasspathLayout>
</manifest>
</archive>
</configuration>
In maven-dependency-plugin:
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<prependGroupId>true</prependGroupId>
</configuration>
</execution>
</executions>
assembly.xml:
<?xml version="1.0" encoding="UTF-8"?>
<assembly>
<id>package</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/dependency</directory>
<outputDirectory>/lib</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<fileSet>
<includes>
<include>configuration.yml</include>
</includes>
</fileSet>
</fileSets>
</assembly>

As soon as I posted this I found the answer. I guess that's just how it goes.
Buried in the documentation for the Maven Archiver is a section on Handling Snapshot Versions, which says to replace ${artifact.version} with ${artifact.baseVersion}. And it works! The 20130412.232035-4 on the end is replaced with SNAPSHOT.

Related

Include parents documentation into zip-file

I have a multimodule maven project and I want to create an ZIP-File in the end which contains an .ear and the documentation.
The documentation is made with docbkx and is part of the parent.
The .ear file is made in a module.
My structure:
partent
|-src/docbkx
|-moduleEJB
|-moduleEAR
Where I am now?
I can create an ZIP including my ear (using mvn clean package)
I can create the PDF output of my documentation (using mvn clean site)
I want now to include the generated PDF of my documentation into my ZIP-file. How can I achieve that? I tried to include the target directory of my parent project but nothing happened - which seems logical because when I run mvn clean package the documentation PDF isn't made as it's part of the pre-sitelifecycle.
This is my assembly.xml
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>bin</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}</directory>
<includes>
<include>*.ear</include>
</includes>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>${parent.project.build.directory}/docbkx/pdf</directory>
<includes>
<include>*.pdf</include>
</includes>
<outputDirectory>docs/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
This is the part of docbooks execution of my parent.pom:
<executions>
<execution>
<phase>pre-site</phase>
<goals>
<goal>generate-pdf</goal>
</goals>
<configuration>
</configuration>
</execution>
</executions>
Thanks in advance
edit: I also tried to change the phase of docbkx to compile but still nothing in my final zip.
I got it myself. As the parent project is the last to build I created a new project named documentation to create the PDF. I then added this to the zip using a fileset
<fileSet>
<directory>${project.build.directory}/../../documentation/target/docbkx/pdf</directory>
<includes>
<include>*.pdf</include>
</includes>
<outputDirectory>docs/</outputDirectory>
</fileSet>

Whats the best way to bundle the whole project in Maven?

I'd like to create a fat-jar which is autoexecutable (Shade Plugin), but also includes sources, resources, tests, and everything in a Eclipse-importable way.
The jar would be single-file executable app, which also contains the whole project in an importable fashion as a maven project someway (after unzipping the jar, I assume).
Another option would be a resulting project zip that includes the binary distribution at base level.
Is there such a thing?
A possible solution requires 3 steps:
Create an uber-jar of the project with the maven-shade-plugin. This JAR will contain all the dependencies and will be executable.
Create a side artifact consisting of the sources of the project with the maven-assembly-plugin. This ZIP will contain the pom.xml and all of the sources under src.
Create another side artitact that will effectively be our final artifact, that will contain both the unpacked shaded JAR (to make it effectively executable) and the sources ZIP.
This would be a possible configuration:
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>make-uberjar</id>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>fully.classified.name.to.main.Class</mainClass>
</transformer>
</transformers>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>sources</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly-sources.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>final</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
This configures the execution of the maven-shade-plugin and 2 execution of the maven-assembly-plugin. The first execution will creates the sources ZIP. This would be the assembly-sources.xml assembly descriptor file:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>sources</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}</directory>
<includes>
<include>pom.xml</include>
<include>src/**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
It includes pom.xml and everything under src into a ZIP having the sources classifier.
The second assembly.xml assembly descriptor file would be:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>jar-with-sources</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<includes>
<include>${project.groupId}:${project.artifactId}:jar:${project.version}</include>
</includes>
<unpack>true</unpack>
</dependencySet>
<dependencySet>
<useProjectAttachments>true</useProjectAttachments>
<includes>
<include>${project.groupId}:${project.artifactId}:zip:sources:${project.version}</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
This creates 2 <dependencySet>. The first one unpacks the shaded JAR (which replaced the main artifact at that point in the build). The second one simply includes the sources ZIP attached artifact; note that we need to use <useProjectAttachments> to include the attached sources ZIP.
When you run mvn clean install, you will have as result a file {finalName}-jar-with-sources.jar that will be your wanted executable JAR. It will also contain a ZIP file of all the sources in the root folder.
I found that using the maven assembly-plugin gives you the best control over these kind of things, for both an uber jar or an installable zip. The shade plugin works well for uber jars, but not so well for installer zips or installers.
In the past i also augmented that functionality by adding in the mix the izpack plugin, which creates a real installer, off of the distributable zip that you create with the assembly plugin.
For example, with the assembly-plugin you can choose to include or exclude certain file resources. This happens for example when you want to use a configuration file while working with the IDE, but you really want to exclude it in the final distribution zip, or you want to include a slightly different one.
Same happens when you want to generate an rpm: the assembly plugin can help quite a bit in first preparing what's needed for the rpm plugin to operate.
The assembly plugin comes with all sort of settings, which you declare in its xml configuration file and it is well documented.
In most cases, trying to pack all the application dependencies in a single .jar is a bad idea, mainly because .jars are not designed to be used this way. In fact, they might contain META-INF/ and other jar-specific files that might clash each other.
When I have to build binary distributions that can be run from the command line, I use the Assembly plug-in, as I've described in this post. If you need to distribute a GUI application or a one-click, self-contained web server, the approach would be very similar.

maven assembly plugin including jars dependencies and external files

I am trying to use the Assembly plugin to include the dependecies as well as
Here is my assembly plugin
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<id>create-executable-jar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>
jar-with-dependencies
</descriptorRef>
</descriptorRefs>
<descriptors>
<descriptor>src/assembly/assembly.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>com.sarm.myproject.XMLParser.LPUnMarshaller</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
here is my assembly.xml descriptor, i made the id same as the descritpor ref as it was creating a different jar for this descriptor. So i have two descriptors one is a jar-with-dependencies descriptor ref and one is the below descriptor, in this case what is happening is that it creating two jars and the second jar overwrites the previous jar. How is it possible to include these two in the same jar.
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<fileSets>
<fileSet>
<directory>${basedir}</directory>
<includes>
<include>*.xml</include>
</includes>
<excludes>
<exclude>30000dests.xml</exclude>
</excludes>
</fileSet>
<fileSet>
<directory>${basedir}/test</directory>
<includes>
<include>*.xml</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Edit: I have tried some other approaches and i have seen that if i use the assembly.xml as a descriptor, a new jar is created along side any other default jar that is created as well. So i end up with two jars. The default jar is an executable like the jar plugin is configured. even though the assembly plugin is configured to have a manifest.mf with my main class name the jar created thru the assmbly.xml is not executable and has a folder of my projects name with the executable jar inside it.
I use mvn clean install to build my project and the jar file.
You should create two modules that produce two jars. Typically maven is going to produce one jar file per module with the module name as the jar name.
Maven recommends that each module have a single output artifact.
If you have concerns about duplicating code. You can inherit relevant stuff by have a parent pom.

Maven Spring jar packaging

We have created a jar(Spring project) which we are including using Maven in another Spring project (war)
we can use this no problem if we include the required dependancies.
If I wanted to ensure the jar contained all it's depenadancies and used them what is the best way to go about this ?
To avoid having to include the dependancies I have tried in using the maven assembly plugin
which definately includes the files - but these appear to be ignored as they are still required as dependancies in the consuming project - any suggestions why?
POM detail for assembly plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
You can use the maven winstone plugin to create a standalone executable jar with all dependencies included of the war, the jar etc....
Adding
<plugins>
<plugin>
<groupId>net.sf.alchim</groupId>
<artifactId>winstone-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<goals>
<goal>embed</goal>
</goals>
<phase>install</phase>
</execution>
</executions>
<configuration>
<filename>${project.parent.build.finalName}.jar</filename>
</configuration>
</plugin>
...
</plugins>
will bundle all modules of your app, wars and jars, and any needed dependencies in a executable jar which includes a servlet engine.
This works really nice to give a single deployable bundle to your Ops team for deploying.
I would advise against creating a jar which contain all dependencies to be used by the war however. You are likely to end up with multiple copies of slightly different versions of the same classes in the class path. Certain libraries are a bit euhhmmm, ..., temperamentfull about this (hibernate and log4j spring to mind).
Maven does a decent job of figuring out which dependencies to take, and if things break mvn dependency:tree make things a lot clearer. You lose this when you create an uber-jar.
If there are good reasons to do this, I would recommend an environment where you can tightly control the classpaths like a full-blown J2EE server or using an OSGi container. However, be careful what you wish for : these are not kittens to be handled without (iron) gloves.
I use the following assembly configuration to create a jar with all runtime dependencies included:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>runnable</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>

Packaging a jar into a dist dir with separated external resources and dependencies

Here's what I'm trying to achieve - a dist directory (or a zip file) that looks like this:
dist/
|-- application-1.0.jar
|-- conf/
|-- application.properties
|-- log4j.properties
|-- lib/
|-- *.jar
Basically:
An executable jar is produced (with appropriate classpath in the manifest)
I want to exclude src/main/resources from being automatically packaged with the jar, so that application.properties can be modified
I want to have external dependencies in the lib/ directory
I came up with a solution using a profile with plugins attached to the package phase, but would using the assembly plugin be a better solution?
The solution using the assembly plugin has a few parts:
The pom includes configuring the jar plugin (maven-jar-plugin), and configuring the assembly plugin (maven-assembly-plugin).
During maven's packaging phase, the jar plugin is called to construct the application jar.
Then the assembly plugin is run, and combines the constructed jar, resources and dependencies into a zip file as defined by the assembly file (distribution-zip.xml).
In the pom, configure the plugins:
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<!-- Make an executable jar, adjust classpath entries-->
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>./lib/</classpathPrefix>
<mainClass>com.acme.KillerApp</mainClass>
</manifest>
<!--Resources will be placed under conf/-->
<manifestEntries>
<Class-Path>./conf/</Class-Path>
</manifestEntries>
</archive>
<!--exclude the properties file from the archive-->
<excludes>
<exclude>*.properties</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<configuration>
<descriptors>
<descriptor>${basedir}/assembly/distribution-zip.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
...
The contents of the assembly file distribution-zip.xml (with thanks to Neeme Praks) combines the created jar, resources and dependencies:
<assembly>
<id>dist</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<dependencySets>
<dependencySet>
<!--Include runtime dependencies-->
<outputDirectory>lib</outputDirectory>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<!--Get the generated application jar-->
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<fileSet>
<!--Get application resources-->
<directory>src/main/resources</directory>
<outputDirectory>conf</outputDirectory>
</fileSet>
<fileSet>
<!--Get misc user files-->
<directory>${project.basedir}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>README*</include>
<include>LICENSE*</include>
<include>NOTICE*</include>
</includes>
</fileSet>
</fileSets>
</assembly>
The resulting distributable zip file is created like target/killer-app-1.0-dist.zip!
You need to use two plugins to accomplish this: maven-jar-plugin and maven-assembly-plugin.
Useful pom.xml samples:
how make JAR executable and set manifest classpath
how to exclude files from JAR file
assembly plugin usage
(I would recommend you to separate the user-editable properties files to separate directory, but it is a matter of taste.)
Sample assembly configuration, to get you started:
<assembly>
<id>dist</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<baseDirectory>dist</baseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>src/conf</directory>
<outputDirectory>conf</outputDirectory>
</fileSet>
<fileSet>
<directory>src/run</directory>
<outputDirectory></outputDirectory>
<excludes>
<exclude>*.sh</exclude>
</excludes>
</fileSet>
</fileSets>
<files>
<file>
<source>src/run/run.sh</source>
<outputDirectory></outputDirectory>
<fileMode>0755</fileMode>
</file>
</files>
</assembly>

Categories

Resources