Excluding a specific directory using Maven jar-with-dependencies - maven

I'm using jar-with-dependencies in Maven to create a compiled jar file for my project. However, one of the dependencies has got source code in its jar in a non-standard place (/jvm/), and this is being included in the combined output jar.
How do I exclude a specific directory in a specific jar from being included in the combined output jar? An <excludes> tag doesn't seem to be valid anywhere in the plugin definition (at least, IntelliJ doesn't think it's valid)

I have never used jar-with-dependencies but for the same problem you mentioned above we used maven-shade-plugin in our project to include and exclude classes from particular packages.
<excludes>
<exclude>com.techidiocy.dump.*</exclude>
</excludes>
In above it will ignore all the classes from the package com.techidiocy.dump
Thanks

Related

How to figure out artifactSet to exclude in Maven pom.xml

I have a java spark maven project. I am building an uber jar, this jar size is huge. I dont think I am using all of the dependencies it is packaging. My questions:
How do I find out the jars(dependencies) that are not used during compile/run?
How do I find out what is 'provided' vs the ones I need to package?
I see some poms having the following to do exactly that. How do I find out this list for my use case? Is this trial and error? Like I remove some, deploy and test? somehow even with a handful of entries in my pom, somehow maven has imported about 2000 jars. How do people find out the absolutely needed set of jars and keep the size to as minimum as possible?
<artifactSet>
<excludes>
<exclude>org.bouncycastle:bcpkix-jdk15on</exclude>
<exclude>org.bouncycastle:bcprov-jdk15on</exclude>
<exclude>com.google.code.findbugs:jsr305</exclude>
<exclude>com.apple:AppleJavaExtensions:*</exclude>
<exclude>javax.servlet:*</exclude>
<exclude>org.apache.hadoop:*</exclude>
<!-- Other long list of jars -->
</excludes>
</artifactSet>
Expected to build a small jar

include yajsw in maven build

My project uses YAJSW wrapper. When i build project, i simple copy jars, required by YAJSW into assembly. So YAJSW's jars simple commited into my svn. I don't like this because my project hold 25 MB of space and 20 MB of that is YAJSW's libs.
I want to try:
delete unnecessary YAJSW's libs, but i don't know which of them are required.
download required libs from repo during build. But how to make it easy without listing all YAJSW jars in dependencies?
It will be best if there is a YAJSW pom with dependencies, but i don't find that. Maybe someone create that, so i can upload it to my repo?
This is most fundamental things you need to copy in your assembly cycle:
<fileSet>
<directory>
your_yajsw_folder
</directory>
<outputDirectory>/yajsw</outputDirectory>
<includes>
<include>bat/</include>
<include>conf/</include>
<include>lib/</include>
<include>scripts/</include>
<include>wrapper.jar</include>
<include>wrapperApp.jar</include>
</includes>
</fileSet>
Right now I'm trying to add the wrapper.jar and wrapperApp.jar from maven, hence removing it from the assymbly file. However for that I might need to edit the scripts to look for the jar in the lib folder instead of the wrapper_home
I found the maven dependencies:
<dependency>
<groupId>org.rzo.yajsw</groupId>
<artifactId>wrapper</artifactId>
<version>11.11</version>
</dependency>
<dependency>
<groupId>org.rzo.yajsw</groupId>
<artifactId>wrapperApp</artifactId>
<version>11.11</version>
</dependency>
Indeed, I have done this - please check out my project at:
https://github.com/griels/yajsw-maven-mk2
I think there are some other projects that have performed such an integration, e.g.
https://github.com/neo4j-attic/yajsw
But I couldn't find much info on them.
Alternatively, if you can find some way to run the YAJSW Gradle build scripts from Maven, you might be able to use that. I had to track down most of the dependencies by hand.

Maven Assembly include specific version of the artifact

I am including few jars in DependencySet include section
<includes>
<include>dom4j:dom4j:jar</include>
<include>log4j:log4j:jar</include>
</includes>
However I am getting dom4j-1.5.jar and log4j-1.2.jar. Since there are many other versions in repo,
I would like to pull specific version for my application. [dom4j-1.6.1.jar and log4j-1.2.5.jar]
How do I force maven to pickup specific version in Assembly.xml?
Try the includes in the following format:
(groupId:artifactId:type:[classifier:]version)
Alternatively, fix you dependencies. You can do this by adding an explicit dependency to the version of the dependency you would like to use in the pom.xml you're using to invoke the assembly plugin from.

Intellij: jboss-ejb3.xml entry keeps disappearing from ${PROJECT_DIR}/.idea/artifacts/XXX_war_exploded.xml

Why is it that although I've
set the proper path to the JBoss EJB deployment descriptor in my project's EJB facet
added jboss-ejb3.xml to Intellij's artifact Patrac-web:war exploded's <output root>/WEB-INF
that any time I make the simplest change to pom.xml Intellij removes the following entry from ${PROJECT_DIR}/.idea/artifacts/Patrac_web_war_exploded.xml:
<element id="file-copy" path="$PROJECT_DIR$/Patrac-ejb/src/main/resources/META-INF/jboss-ejb3.xml" />
and, as a result, jboss-ejb3.xml does not get copied to the target directory?
It's as though each time I make a change to pom.xml Intellij "reloads" the deployment configuration using the POM to override what settings I make within the IDE. Perhaps because I have no entry in my pom.xml for copying jboss-ejb3.xml from source directory to target directory the settings I make in Intellij IDE keep disappearing whenever Intellij "reloads." Pure conjecture on my part, but this is what seems to be happening.
If so, what change do I need to make to pom.xml in order to make this stop happening?
When a project is (re)imported from Maven IDEA configures it such way that when you invoke 'Build' from IDEA it produces the same result as Maven's 'package' goal. If you need to copy jboss-ejb3.xml to WEB-INF just put it under 'src/main/webapp/WEB-INF' directory and it will be copied by Maven and so do IDEA.
Here is an alternative to Nik's solution that I tried because I wanted to leave jboss-ejb3.xml in META-INF. Taking a look at the maven documentation, which shows how to treat jboss-ejb3.xml as a web resource and copy it into WEB-INF, I added the following to the maven-war-plugin configuration and the problem was resolved. Well, kinda sorta. But not really.
<webResources>
<resource>
<directory>../Patrac-ejb/src/main/resources/META-INF</directory>
<includes>
<include>jboss-ejb3.xml</include>
</includes>
<targetPath>WEB-INF</targetPath>
</resource>
</webResources>
Although doing it this way eliminated the need to fiddle around with IDEA facet configuration settings (because Maven was configured to copy the file, not IDEA), a new problem was introduced: two copies of jboss-ejb3.xml appeared in the WAR, one in WEB-INF and the other inside the EJB JAR (in META-INF). Although there were no apparent consequences (the application ran just fine) I preferred not to have a duplicate copy of the descriptor located inside the EJB JAR.
Using the Maven EJB plugin documentation, I tried to add an exclusion to my maven-ejb-plugin configuration e.g.
<configuration>
<ejbVersion>3.1</ejbVersion>
<excludes>
<exclude>**/jboss-ejb3.xml</exclude>
</excludes>
</configuration>
This should have prevented the duplicate copy of jboss-ejb3.xml from appearing in the EJB JAR META-INF but it didn't work for me, and after fruitlessly googling various variations of "maven-ejb-plugin excludes not working properly" I gave up.
If I could have gotten the excludes to work then I would have preferred this solution over moving jboss-ejb3.xml into src/main/webapp/WEB-INF because although this solution is slightly more complex (it requires additional Maven configuration settings in two POMs), the EJB-related descriptor would remain in the EJB module.
I've decided to go with Nik's solution until I can resolve the excludes problem.

Maven: Force Jersey to use specific artifact version

I have a Maven repository where I load Jena TDB 0.9.3 (which depends on Jena ARQ 2.9.3), Jersey 1.8 and RMOnto 1.0. The point is, as you expected, to do some analysis on semantic datasets.
It looks like RMOnto has ARQ 2.8.7 built in, as in "hardwired". There isn't any explicit dependency in its pom file, yet the jar file contains a ARQ.class. It's very tricky because you won't notice it with Maven Enforcer Plugin and the like.
It looks like this causes Jersey to use RMOnto's ARQ version instead of the one defined in pom.xml. Here is a minimal example. When you run the test (checks whether or not ARQ.VERSION equals 2.9.3), it succeeds. When you build the project and deploy it on a Tomcat 7, you should see 2.8.7 as output.
Is this behaviour expected and why?
How could one force Jersey to use ARQ 2.9.3?
In case it's not possible, could one isolate RMOnto to use 2.8.7 while the rest of the source uses 2.9.3?
Thanks in advance!
You should define the ARQ 2.9.3 first in the dependencies list. By doing that you force your build to use that specific version. The dependency order is relevant when choosing what artifact to use.
Update
OK, I understand what the problem is.
The RMOnto jar is obviously shaded according to the pom: http://semantic.cs.put.poznan.pl/maven/put/semantic/RMOnto/1.0/RMOnto-1.0.pom.
Tomcat 7 loads the jars in WEB-INF/lib in an undefined order. This means that even if you define ARQ 2.9.3 to be first in your dependencies it will not be the case when the application is run in Tomcat. http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html
Good thing is that Tomcat always look in WEB-INF/classes before WEB-INF/lib for dependencies.
So what you can do as a work around is to make sure that the ARQ 2.9.3 version is added to the WEB-INF/classes folder. This can be done using the maven-dependency-plugin:
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.apache.jena</groupId>
<artifactId>jena-arq</artifactId>
<version>2.9.3</version>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<excludes>**/META-INF/</excludes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Your war as well as your exploded war will now contain all the classes from ARQ 2.9.3 in the WEB-INF/classes folder. They will be loaded before any jar-file that is in WEB-INF/lib folder.
NB: I have not tested this on Tomcat but I cannot see that it would not work.
NB2: This is a hack. Best thing would be to remove the ARQ packages out of the RMOnto jar.
You should file a defect report against RMOnto. Hard-wiring library code into a jar, instead of including it as a dependency you can manage in the POM, is definitely a bad idea that the code maintainer should fix.
If the files have been copied directly to the RMOnto .jar, the behaviour is expected.
In that case, I'd say the best bet is to hardcode it away, aka remove the ARQ files directly from the package. Opening up the RMOnto-1.0.jar package one can see arq files in the arq folder. What you'd need to do is open up the jar file (it's just a .zip), remove the ARQ files from there, store the edited RMOnto package in your version control / repository and refer to the edited package from there. Also, you'd need to add excludes statement to your pom for the old version of ARC and keep the dependency to the new version.
If you feel like it, it would be also good practice to remove the other dependencies that haven't been mentioned in the RMOnto's pom file, then add them in the RMOnto pom file (and rebuild, if you have the source code). This way Maven mechanism would be aware of them. The file seems to contain a lot of dependencies like this, which will cause headaches in the future.

Resources