Maven dependency aliasing - maven

I've just noted that my war contains both woodstox-core-asl-4.4.1.jar and woodstox-core-5.0.2.jar. They are two different version of the same library, but the library changed both groupId and artifactId. Furthermore both are included in my war as transitive dependencies by two different modules of my project.
I know that I can use exclusions to remove the old version of the library but in this case I should also explicitly "include" the new version in case that module would be used alone (that is not with the other one that includes woodstox-core-5.0.2.jar).
I don't like this solution. Is there any way to declare that woodstox-core is an alias of woodstox-core-asl so that Maven includes only one of these jars?
A similar problem affects old Spring 2.x that published both an all-in-one artifact and smaller separated artifacts. However I think that the most common issue is the one related to artifacts that change their groupId and/or artifactId.

There is no way to do this. Maven doesn't understand the concept of aliases. If it did, then that would open the door to a whole other kind of dependency hell.
What you've described -- adding an <exclusion/> for the <dependency/> for all dependencies that need it and then explicitly adding a new <dependency/> for the renamed artifact -- is the only way you can achieve this at the moment.

Related

A question about best practice on multiple dependency jar versions when packing war with maven

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.

How to correctly import a Maven dependency that I altered and re-built into an existing project?

I have a Maven dependency, pulsar-log4j2-appender, which I forked and changed the source code because it was throwing exceptions in my project.
After changing the source code, I ran the maven package command to build the jar and imported it into my project (in Intellij: Project Structure | Modules | Dependencies | Add JARs or directories...).
However, when I run the application, it seems like it's not able to find that dependency because the Pulsar appender which I declared in my log4j2.xml file isn't being configured.
Am I importing the JAR properly? I'm wondering if the JAR needs to be within the org.apache.pulsar namespace to be imported properly.
For example,
This is what the dependency looks like unaltered:
And this is what it looks like when I modify and build it myself:
If you modify the code from an open source project you should change both the groupId and the artifact id. If you do not you will have problems and future developers will say your name in ways you do not want to hear.
Changing these are necessary so that Maven knows to use your version instead of the publicly available version. Also, when people look at your project and see the groupId and artifactId from the "real" project they will naturally assume that is what is being used (which is why they will curse you if that is not the case). In addition, you will have to do something convoluted to get Maven to use your dependency reliably.
The practice I have followed is the prepend "com.mycorp", where mycorp is my employer's name, to the groupId and add mycorp into the artifactId. The only downside to this is that you must ensure that the "real" artifact's coordinates are not referenced as a dependency or as a transitive dependency or else you will have duplicate classes on the class path.
Finally, your best bet is to create a pull request for Apache Pulsar with your fix so that other people experiencing the same problem you are get the benefit of it.

How two know when a maven project has the same transitive dependenciy twice of different versions?

I have to add a new dependency to a maven project. This dependency has four transitive dependencies(according to http://mvnrepository.com/) and between them, there is spring-data-jpa jar.
The maven project I am working in has many dependencies configured in the pom so I understand there could be a big possibility that there is already a spring-data-jpa dependency in the project(transitive or not).
When you work in a large project with many dependencies and you have to add a new one, how to check if there is already the same transitive dependency of a different version? I have to check manually the transitive dependencies for each direct dependency configured? Has maven a warning for this situation?
How maven works in this situation? I mean, there could be two spring-data-jpa jars of different versions(this would be a problem) or maven resolves this in another way?
The simple answer is that the dependency plugin can tell you. The longer answer is that there are a number of different situations to consider about transitive dependency management, and how the plugin helps and what to do about it differs for each one.
Maven automatically chooses which dependency to include if two dependencies have the same coordinates (groupId, artifactId) with different versions. Broadly speaking, it picks the version that's highest in the tree - effectively overriding dependencies defined in downstream transitive dependency poms. So, if you have two different versions of exactly the same dependency then you will still only find one version of the dependency on the relevant classpath.
The dependency plugin can help you identify this situation by highlighting points where its made a decision, but you probably want to use the dependencyManagement section of your top-level pom to ensure that the dependencies which you bring in are the ones you expect.
Separate difficulties can arise when a dependency changes its groupId or artifactId. Then you can get two dependencies on the classpath - one with an old version on the old coordinates and one with the new version on the new coordinates. As examples, Spring, Hibernate and Apache commons have all found themselves doing this at some point or another. In this case all you can do is use to the dependency plugin to identify duplicated dependencies and then use exclusions tags to explicitly exclude them as transitive dependencies from the dependencies which are pull them in.
It's important to note that all of this dependency management can cause unintended breakage. If the thing that your application depends on really does depend on some specific version of a package as a transitive dependency then you can break it by overriding that version. So testing the features that you use is essential.
Have you tried the Maven Dependency Plugin? There's some useful goals you can run, such as mvn dependency:tree etc.

how can I find the artifactId and version information for '"libopencv_java.so" and "libnative_camera_r2.2.2.so" in pom.xml in Maven?

I've searched for hours but no artifactId and version information for "libopencv_java.so" and "libnative_camera_r2.2.2.so".. I know how to add dependency into pom.xml to be included in lib/armeabi in .apk, but I just cannot find the correct information.. The pox.xml keeps complaining
"Missing artifact org.opencv:libnative_camera_r2.2.2:so:2.2.2
Missing artifact org.opencv:libopencv_java:so:1.0"
Thank you so much~!!
These are native non-Java libraries. They aren't normally handled by Maven. If you would like to use static objects in your module, I suggest you have something like ${basedir}/lib and place your static libraries in there. Add the directory as a <resource/> as well and have it included in you jar. I think it should be possible to load the .so from within the jar. This is one option.
Another option would be, (if you really, really must re-use the .so-s across modules), to extract them to a separate module and have your module depend on that one.
Either way, you'll need to do quite a bit of magic, which isn't covered by Maven by default.

Is declaring maven "dependencies" in pom.xml really necessary?

I need some verification of how Maven works.
How important is it for us to specify the project dependencies explicitly (<dependencies>) in pom.xml? Some said that it's necessary only when we need a specific version of that jar, otherwise Maven will be able to find the jar in your local / Maven's remote repository. However, I find that sometimes I could not build or package a Maven project without specifying/declaring the dependencies.
So.. is the declaration really necessary?
If your code just uses "plain" Java and does not depend on any other libraries you do not need to declare any dependencies (because you do not depend on anything other than the Java runtime).
In most cases you will use some 3rd party libraries - thus you have to declare them as dependencies in your project to let maven construct a valid classpath which lets your build work (transitive dependencies will be resolved automatically - as already mentioned).
Regarding to the specific version of a jar have a look at the Project Dependencies section of the "Maven: The Complete Reference" book provided by Sonatype. You have several options to declare the version you need (including version ranges).
Do not expect that the declaration
<version>1.2.4</version>
will force Maven to use that version. That is only meant as "allow anything, but prefer 1.2.4". If you need to force maven to use a specific version and nothing else you have to use
<version>[1.2.4]</version>
Yes, the dependencies are needed. Most plugins use them to construct the necessary classpath, or to determine what to include in the artifact. Maven is declarative - you are declaring what you need, not how and where to find them locally.
You need not to declare Transitive dependencies of a JAR. Other than that, everything must be declared. Here is a good read on how maven mananges dependencies. http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
You always need to specify the dependencies. Maven can't predict, which libraries you need. What you in most times don't need to specify, are additional Maven repositories. You need that only when you have libraries as dependencies, which are not contained in Maven Central.
What you also can eliminate in your projects, are the version numbers of your dependencies, if you have a parent POM, where the versions are specified.

Resources