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.
Related
I have a maven war project with submodules. One module uses google-api-client, another use google-cloud-storage. I draw some of their dependencies below
A
|-google-api-client:jar:1.33.1
|-google-http-client-gson:jar:1.41.1
B
|-google-cloud-storage:jar:2.4.4
|-google-api-client:jar:1.33.1
|-google-http-client-gson:jar:1.41.2
When packaging wars, both gson 1.41.1 and 1.41.2 will be packaged. I know maven has a nearest rule to determine which jar to use when compiling. But when the webserver loads my project I have no control to which jar will be loaded first. So I want to keep only a newer version for each jar.
I know that I can add <exclusion> tags to the dependencies and add a new dependency to tell maven to use a specific version of jars. However, I am not sure if that is the best practice because it requires me to go through the dependencies of third-party libraries. There are just too many of them.
Any suggestions on how to handle the multiple versions of jars properly?
A good practice I recommend is to use enforcer Plugin with dependency convergence goal. This way you are forced to decide which version will be on the class path. Of course it might be additional effort because you have to handle conflicts (also by setting exclusions), but in the end it's well defined, which versions you get.
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
I am currently working in a Java project, and we use maven to build the final jar. There are two ways to build the jars as we all know, i.e. one single jar with-dependencies, and a jar without dependencies. In the latter case, we need to add dependent jars to the classpath as well.
In principle both can work, personally I prefer one jar with dependencies, but in the project team members decided to use separate jar without dependencies. So hereby I would like to know which choice is better?
This question has no answer, since it depends on what you need to do.
If you're writing an utility package or component, that could be a dependency of another project, then there's no point in having all the dependencies inside it - it's better to leave dependency resolution to a dependency manager, like Maven.
If you, instead, are writing a full application packaged as a jar, I mean something with a MainClass that can be executed with java -jar myjar, then having the dependencies together will make distribution easier.
Consider that, for instance, if you're writing a webapp, that'll be packaged as a WAR, it normally comes with dependencies.
this is a more conceptual question:
I want to create an application which uses the WALA framework, which itself is packaged as a eclipse plugin, built with maven-tycho. When I try to add this as an dependency no transitive dependency gets resolved, because they are covered by the tycho build.
This is the pom of the WALA project I need at least https://github.com/wala/WALA/blob/master/com.ibm.wala.core/pom.xml
Should my application be a OSGI Bundle itself or can I create a regular jar with it without having much trouble? Which approach is more practical?
If I have seen it correctly, wala.core has only two dependencies wala.util and wala.shrike (util has none, shrike depends on util). So you might as well simply include all three dependencies in your project.
On the long haul, however, you might should indeed consider creating an osgi application instead.
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.