Gradle, Java conflicts between a file jar dependency and maven central dependencies - java

I am trying to add a dependency as jar file and that jar is shipped with all the classes which are needed for it to run.
compile files('lib/org.hl7.fhir.igpublisher.jar')
Along with that, I have few other dependencies which are added as maven dependencies.
compile ("ca.uhn.hapi.fhir:hapi-fhir-base:2.3")
Now I am facing a lot of issues related to class conflicts because same classes have been shipped with different versions.
In an ideal case, how should I solve this problem? I want to say that the local jar should always use its own files and other dependencies should ignore the local jar files.
Note:- I am using IntelliJ idea.

This is a tricky problem. There is only one classpath and multiple versions of the same class mean that only one of that versions is visible and the other ones are hidden.
One should generally avoid to declare dependencies on "fat jars" that contain their own dependencies. If possible, one should use the slim version without the dependencies (often both versions are published). If there is not alternative one can construct such a slim jar yourself by manually splitting up the jar file. It is also possible to control the structure by carefully ordering the dependencies on the classpath, but this is a little brittle.

Related

How to use ommited library in java project

I have two libraries as dependencies in my project. Each of those two libraries has bunch of libraries as dependency. However there are two same named libraries with different version, and one of them as I can see in maven pom dependency hierarchy is ommited conflicting with same named one. When I run program program it uses elements of both "parent" libs, but it uses one of conflicting "child" libs whit which it tries to work with "parent" lib which should use other conflicting lib. So is it possible to have both conflicting libs used in project.
Thanks
Not really.
You can use the Maven shade plugin to construct a shaded jar that contains the dependency with a different package hierarchy.
But the usual solution is to try to find a version of the library that works with all of the other stuff (not always possible, I know).

Runtime conflicts with uber-jars

I have recently come across some libraries which provide their jar files with their dependencies bundled with them (sometimes referred to as an uber jar, fat jar, or shaded jar thanks to Maven's Shade plugin).
The problem is that I have two libraries (A and B) which contain
different versions of the same class file (same.fully.qulaified.class), and one of the libraries doesn't play nicely with the class file version in the other. I know I could play around with a custom classloader to sandbox the classes from A and B, but I'd rather go with a simpler, more standard solution if one exists.
Also, in general I'm surprised that these libraries are released as uber jars at all. It seems like when library providers package their dependencies in this way, this sort of problem is likely to show up.
So I have a couple questions:
1) Is it common and accepted practice for library providers to release uber jars?
2) Are there standard solutions to resolve conflicting transient dependencies (dependencies of dependencies) that show up at runtime when two of your required libraries have different versions of a class?

How to configure Maven for a single codebase but multiple artifacts

I have a single very large codebase that compiles down to a JAR. I also use the shade plugin to compile it down and package it up with all dependencies. I also use the war plugin to get a WAR file.
With respect to the WAR file, once the goal is created I have a post-build event that simply copies the WAR file to its destination, so technically I'm good with that.
The problem I have is with the other two JARs. They both share the same artifactId since they're both built in a single pom.xml and this isn't acceptable for a number of reasons (including, but not limited to the fact that some caching of dependencies is pretty dumb about realizing that one JAR is the thin one and one is the full-dependency one).
What I need to do is create a pom.xml (or group thereof) suitable for builds (by Jenkins) that can use the same codebase (pulled from Github) but create two separate JAR files, each with their own artifactId.
Being a Maven novice, I've read through the beginning book and it seems to me that what I want is a parent pom.xml with two modules. But from what I can tell, each module means a separate directory with separate code. As I said, this is built from the same codebase. The only difference is one is built from the "regular" build, and the other is built using the "shade" plugin and goal.
The only other thing I can think of is build the "regular" JAR and then build the shaded JAR with a classifier of "full?" If this is the answer, may I humbly ask for some adult supervision on how to do this, as I'm not seeing how.
If that's not the answer, I suspect this must be a common problem, so again, some guidance would be very helpful!
The solution I came up with was to use a classifier for the "shaded" jar. Thus, the artifacts don't collide.
I then had an issue accessing it, but found the solution to that issue as well - How do I access a jar with a classifier?

Maven group library

I have a web app with thousands classes packed in hundred jar's placed in several folders.
I want create in local maven repository a library, containing all classes from those jars.
And I can use this dependensy in all my projects...
Like in a IntelliJ IDEA i create a global library. Select a folder with sets of jars with subfolders and set name "My web-app libs". And then i add this global lib on my project.
I have founded a way for construct group for several libraries, described here. But I have a hundred jar files and stupid make new project for each.
In advance thanks.
Look at maven shade plugin.
This plugin provides the capability to package the artifact in an uber-jar,
You may want to create another project which enlists all your artifacts as dependencies. So when you include it into your project all the needed 100 dependencies will be transitively resolved.
Maven Versions plugin could help you bulk updating the many versions inside this new artifact.
UPDATE
If all your 300+ jars are completely static, i.e. their versions are fixed, you might probably need to repack them with the shade plugin. Otherwise updating a version of a JAR from this huge set could be a trouble... I can't predict the performance, but my guess is that a normal Maven approach is more efficient.
A note on Maven shade plugin: you might need to move your shaded libraries to shaded package. That's what they usually do to avoid library versions conflicts. I.e. if your 300+ libs use spring-2.0 and your current project uses spring-3.1.0, both will be included anyway. So to avoid conflicts, it's recommended to configure this plugin to move spring-2.0 packages under a different package.
UPDATE 2
If your jars are not mavenized, Maven won't be a big help here. You should probably merge your jars manually and check if it works for you: Merging Multiple Jars in to a Single Jar.

How to check dependencies of libraries against classes in java

I have a java project which is previously developed by another developer, in this application there are a lot of unnecessary libraries. I was able to delete some of those libraries. But, as there are a lot of them I want to know whether there is a technique to scan the project and detect unrelated libraries to the project.
I recommend Tattletale from JBoss.
Depending on the build method, it should be easy to remove unnecessary libraries without deleting/adding them by simply recompiling the application modifying the classpath at compile time, or rather modifying the build files by one-by-one deletion of lib dependencies. Either one of these methods will require no manual deletion of jars.
1) If you set the jars using the classpath manually, you can play with classpath wild cards to remove / add different jars when running : Setting multiple jars in java classpath classpaths . This does not require manual deletion / adding of jars.
2) Find the dependencies definition (pom.xml in maven, ivy.xml for some ant projects).
and One by one delete the (maven)
<dependency>..</dependency>
or (ivy)
<dependency .... />
entries in your build file.
If you have the correct build plugins installed - then your IDE will immediately rebuild the project using your new definitions (no error prone removal/deletion of jars or classpath entries).

Categories