On my end if I build your project using the pom.xml
you’ve showed us, with apache-poi
declared after jfreechart
, then as you’ve mentioned I get a corrupt JAR. Swapping the order of these two dependencies indeed gives me a correct JAR.
I’ve some previous experience with the maven-shade-plugin
and when I used it I had trouble with the created JAR’s META-INF
directory, so I’ve checked that for defects.
I’ve tried to copy (using Total Commander) the META-INF
directory somewhere on my local filesystem and what I’ve noticed is that there were errors while copying the files in META-INF/licences/
. If I’ve tried to copy those somewhere individually and it worked but I couldn’t copy the whole thing. My conclusion was that the JAR/ZIP archive is corrupt.
What I did was I entered that JAR in Total Commander (Ctrl+PgDown over the JAR file) and I renamed thirdpartylicenses.txt
to thirdpartylicenses.txt.wtf
. Doing this Total Commander offers to save this and it repackages the JAR (I’ve the Total7zip Total Commander packer plugin installed – if anyone tries this and it doesn’t work try it with this installed).
After this. It works.
(I’ve also tried to repack the whole thing without renaming anything using Cygwin’s unzip
/zip
commands, but that didn’t work the new archive was still corrupt. Total Commander or the plugin I’ve mentioned does some magic.)
I guess the maven-shade-plugin
merely creates a corrupt or invalid ZIP/JAR archive. I’m not sure why and maybe what I’ve described won’t work for anyone else but I thought I’d mention it so maybe I could help.
I couldn’t just leave this alone, so I’ve dug deeper and I think I’ve found the answer.
The bad JAR contains 65608 entries.
The good JAR contains 65450 entries.
Guess what’s the upper limit of the number of entries for a plain ZIP file? Yeah. The Wiki article speaks about a ZIP64 format which overcomes this limitation.
The good JAR has less entries because the actual dependencies change because of the position of the dependency declarations in your pom.xml
. (As described by this answer.)
I’ve counted the entries like this.
Collections.list(new JarFile("...").entries()).size();
I was using Java 7 which seems to support the new ZIP64 format, so maybe if someone tries to count the entries in the bad JAR using Java 5 or 6 will receive an error (I’m not sure though).
I also tried to run the JAR exploded. I’ve unpacked the whole JAR into a directory and run the whole thing like this.
java -cp <dir/ com.mycompany.test.Start
Worked like a charm.
Bottom line. Don’t overuse the maven-shade-plugin
.
I have a project at work where I build my project like this.
- I copy my project’s dependencies using the
maven-dependency-plugin
. Checkout thecopy-dependencies
goal. This copies your dependencies intotarget/dependency
if I remember correctly. -
Using the
maven-jar-plugin
I add these dependencies to my final JAR’sMANIFEST.MF
asClass-Path
entries using these options in the plugins configuration.<classpathPrefix>dependency/</classpathPrefix> <addClasspath>true</addClasspath>
So I’ll have
Class-Path
entries likedependency/<artifactId>-<version>.jar
, etc. - After this I’m using the
maven-assembly-plugin
to create a distribution ZIP which contains my final JAR and the wholedependency/
folder. - When I deploy my application I can run it like
java -jar final.jar
.
Primarily I’ve opted to use this solution, because in my project I use some Bouncy Castle JARs which JARs have some extravagant this and that inside their META-INF
directory. When I used the maven-shade-plugin
to create my final runnable JAR all hell broke loose and I got nasty that method couldn’t be found and this signature is not quite right errors.
You should be doing something like this also. This Maven shade business is too shady to be useful (pun intended).
Here’s a blog post on the whole process that I’ve tried to describe just above (thanks to
baba), maybe it’ll help someone in the future.