Creating uber jar with maven - maven

My project inherits it's compile dependencies from parent and I have no control over it - can't change them to provided. Additionally, I have added another dependency 'a:b:1.0.0' to my project's pom. I want to include only 'a:b:1.0.0' with it's own dependencies (recursively ) to my uber jar.
Seems like neither assembly nor shade plugin doesn't support such case.
How this could be done ?
Thanks

Shading recursively has some significant disadvantages. Especially, the problem of duplicate files from multiple dependencies being overwritten with only a single version of the file. This can cause some pretty annoying problems to troubleshoot at runtime. You'd be better off using something like spring boot to build a standalone jar where instead of shading files into a single hierarchy, will embed dependent libraries into itself as a subdirectory and include on the classpath for you.
http://docs.spring.io/spring-boot/docs/current/maven-plugin/repackage-mojo.html

Related

Gradle shadow jar with conflicting dependencies

I'm playing with the idea of creating uber jars for my services but I'm worried about including jars that have conflicting dependencies. What happens when jar A depends on slf4j-1.0 and jar B depends on slf4j-2.0 and there were major changes between 1.0 and 2.0? When those jars both get included in the uber jar do I have to write specific filters by namespace or does something happen during the shadow process that namespaces the jars?
thanks for the help
You are correct to worry. You end up with collisions (a colleague called it 'dll hell all over again') and sometimes you can have classes from both v1 and v2 in the same directory in the jarfile.
You can exclude one or the other version easily, but if your dependencies need them both, you are faced with the following options:
find a new dependency that doesn't have the conflict
upgrade or downgrade a current dependency to bring versions in line
ship as a war file or some other type of file that handles this better, including a normal jarfile with a manifest that includes a classpath
consider spring boot, which uses a different strategy than shading: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#executable-jar
Whatever you do, gradle dependencies is helpful.

How to control what of dependencies will be bundled into uber jar generated by Spring Boot?

My project inherits default configuration from spring-boot-starter-parent . The command mvn package generates so-called uber Jar, which contains all the application compiled code plus all the dependencies from the dependency tree.
The problem is that there are too many dependencies copied into the target Jar file. I tried to control that by setting some of dependencies' scope to compile, but that didn't work.
Is it possible to control what dependencies will be taken into the final Jar file?
Thanks!
The ueberjar only contains the dependencies that you specifically asked for. I'm not sure what else you are looking for. If you are using "starter" poms as dependencies (no-one forces you to do that) then you are perhaps selecting more than you will strictly need at runtime. We do try to be conservative about the transitive of the starters, but the whole point of them is that they have transitive dependencies that might be useful. Like I said, you don't have to use them if you don't like them.

Using maven-shade-plugin, how can one use dependencyReducedPom?

I'm working on an open-source project (neo4j-connector) which make intensive use of maven-shade-plugin to include in packaged RAR the neo4j application without referencing multiple jars (seems like a limitation of maven-rar-plugin).
Anyway, when doing so, the neo4j-connector-impl (which uses the shade plugin) pom references neo4j as a dependency, which is not totally exact, as neo4j source code is embedded in neo4j-connector-impl jar.
I've noticed there is a createDependencyReducedPom flag that allows one to generate a pom containing only non-shaded components. How can i use that pom instead of the standard one for dependencies of that project ?

Best way to package a command line Java project

I'm creating a java command line project, with no GUI. The project uses any number of open source projects : Spring, Logback, Commons CLI etc.
When I started to think about packaging, I imagined it would come out as a zip file, that could be exploded to the jar, with a lib sub directory, and dependent jars in the lib.
adapter.jar
/lib/dependencyA.jar
/lib/dependencyB.jar
etc.
I've been playing with Maven Assembly, but it's still not coming out like the above, and I haven't found any examples that do generate the structure above. Is it possible to do so ?
In addition, having a multi-module structure adds another layer of complexity that I haven't been able to resolve, as the assembly module can't find the core module as a dependency. This is my first Maven project, so am still learning how Maven works. I've been through the Sonatype book, but missed something as even using the Best Practices section couldn't get the missing dependency resolved.
The examples I've seen usually involve merging into an uber executable jar, some of which use the Shade project, some don't. My question is, is doing an uber jar including 3rd party libs like Spring etc a good idea ? Or should I persevere with my original zip / lib subdirectory plan ?
Have your assembly module depend on the modules you want to package and then use the <dependencySets> of <moduleSets> tags to include them in any layout you wish. If you have some other files that do not come from a dependency, you can put them in the deployment module itself.
Please have a good read on the assembly descriptor docs. You can pack, unpack, include/exclude and set permissions for the files in your assembly.
In case you haven't seen the sonatype book on maven, here is the relevant chapter: http://www.sonatype.com/books/mvnref-book/reference/assemblies-sect-best-practices.html
EDIT: escaped the <'s
You just need to be more specific in your assembly descriptor. Use one dependencySet that includes only the main jar and delivers it to the top, and another that excludes only the main jar and delivers to the lib dir.

Exclude unused parts of dependencies from jar (Maven)

We have a small project with some heavy-weight dependencies (e.g. Spring) of which we only use small parts. Therefore, the JAR we get when packing with all dependencies weighs several megabytes, even for out two-class-server. This seems unnecessary.
Is there a way to restrict JAR assembly to actually used (class) files?
You can use the maven-shade-plugin to create a Jar-with-dependencies (your project and the dependencies merged into one big jar) while limiting the classes or packages that are added to that jar. See the includes / excludes page for reference.
If you don't want to manually specify what needs to be included, perhaps there is a way to integrate ProGuard with your build.
It's not possible to include only classes which are used. But you can exclude dependencies from your depencies to reduce the JAR size. Only drawback: you need to know what you can exclude and what not.

Resources