I know there are a lot of questions answered for dependency exclusion with maven. Sadly I couldn't find an answer for my situation, since I don't want to replace the excluded lib with another version of my own.
Let me describe the exact problem.
We are using swagger for our REST endpoint documentation. Hence, swagger is declared a dependency in the pom file.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
Swagger itself declares google guava as compile dependency like this:
springfox-swagger2
-> springfox-spi
-> springfox-core
-> guava
Now guava is available in our project and people start using it, which we want to prevent. I tried to exclude guava from the swagger dependency like this:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
Now Eclipse tells me that swagger is referencing a lib from guava that is not on the classpath. Isn't it possible to tell maven I don't want to have the transitive dependency in my project but let swagger use it as it may.
You can use the Maven dependency plugin with the analyze-only goal:
https://maven.apache.org/plugins/maven-dependency-plugin/analyze-only-mojo.html
Here, you can fail the build if someone directly uses a transitive dependency (without declaring it explicitly). This would especially fail the build if someone uses guava without putting guava into the pom.
You could try static code analysis tools. Possible answer for your question: https://stackoverflow.com/a/7475862/7550277
Or via Maven plugins: here and here.
Related
I'd like to use the Guava collection com.google.common.graph.ImmutableDirectedGraph, documented here, with Maven. I can't find the Maven dependency name and version including this particular class/API on the usual repositories.
What would be the correct Maven dependency/ies ?
It doesn't look like this API has been published to Maven central yet, but I see it in the latest snapshot, 20.0-SNAPSHOT on Github:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0-SNAPSHOT</version>
</dependency>
I am using Apache Maven to building the project..
Problem is some jars are added two times with the different versions.
httpclient-4.0.3
httpclient-4.3.3
httpcore-4.0.1
httpcore-4.3.2
jackson-core-asl-1.6.7
jackson-core-asl-1.9.13
i want the higher version of jars
Usually what you would do is look first at the dependency tree and see where the same jars are coming from:
mvn dependency:tree
After you tracked down where the different dependencies come from you, as in your case, you pick the ones that are older and you go ahead and add a <exclusion/> tag inside the dependency that retrieves the older ones.
Example of how to exclude a dependency inside another dependency:
Let us presume you have hibernate and ehcache dependencies in your pom.xml. If hibernate 3.2.6.ga, for example, has inside ehcache, but it is an older version and we don't want that version. So in order to exclude ehcache from hibernate dependency we would do the following
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.6.ga</version>
<exclusions>
<exclusion>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</exclusion>
</exclusions>
</dependency>
Now, I would help you and add the correct exclusions to the dependencies that are retrieving your older dependencies, but since I am not able to see your pom.xml it is hard to help more.
I have a Maven Java project. I don't want my project dependencies to be satisfied by chance through a chain of subdependencies when compiling the project. It is OK for me when building the final war when maven must check all used dependencies and add necessary libs to the war, but when compiling the code I want to be sure that only direct dependencies are used. Why?
Let's say I have two dependencies:
<dependency>
<groupId>com.package</groupId>
<artifactId>module-1</artifactId>
</dependency>
<dependency>
<groupId>com.package</groupId>
<artifactId>module-2</artifactId>
</dependency>
For our project module-1 and module-2 serve completely different purposes, but somewhere in the dependency tree of module-2, module-1 is used. I delete module-1 dependency, but maven continue to build my project without compilation errors, because it resolves module-1 from module-2 sub-dependencies. This change goes unnoticed.
After sometime we decide to remove module-2, because we don't need it. Strange enough but we can not any more compile classes which were using imports from module-1 and which are not connected to module-2 logic.
This is a simple case, but in big project this can make quite a dependency mess.
You can use the Maven dependency plugin goal "dependency:analyze" to give you a report of all used dependencies which are not declared on the current module (included transitively). That way Maven will still use transitive dependencies (no way around that I guess), but you can force yourself via the plugin to make sure these are also declared. It will also warn you of unnecessary dependencies. Mind, the plugin analyzes the compiled classes. At times, you may need to configure the plugin, because occasionally it may not detect that a dependency is required at compile time but not at runtime, e.g. because a constant was inlined.
If you really need to do this then you can setup exclusions in the pom.
e.g. here's an example of an exclusion in one of my poms where I don't want it to automatically get commons-logging because I'm using a different logging provider.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
You could do something like this (untested)
<dependency>
<groupId>com.package</groupId>
<artifactId>module-2</artifactId>
<exclusions>
<exclusion>
<groupId>com.package</groupId>
<artifactId>module-1</artifactId>
</exclusion>
</exclusions>
</dependency>
I wouldn't necessarily recommend this though. It makes sense in the case of my logging exclusion because I'm using slf4j instead of commons logging. I've seen other examples where this is used to exclude spring 2 if the project as a whole is using spring 3.
It's a bit difficult to tell from your example because it's so vague. In general you should keep your dependencies to a minimum. If module-2 depends on module-1 then it implies that your application won't compile or run without module-1. If in fact it can live happily without it then it's not really dependent.
As a side note it's a bit alarming that you don't have a version number against the dependencies. You'll probably find maven warns you about this. It's good practice to always include a version number. If you're dependent on a module which is currently in development then you should use the .SNAPSHOT suffix on the version to get the latest build for that version.
There seems to be no way to tell maven not to resolve dependency transitively: How to exclude all transitive dependencies of a Maven dependency. One of the reason's I think, is that the user can soon run into runtime troubles, when he finds that some of the artifacts are not being resolved at runtime or there are artifact versions problems. However, if you check the link out, you can make each of the deps 'standalone' with a wildcard exclusion pattern.
One other option is to use <optional> dependency for each of your module-X sub-dependencies. This will make sure the project compiles and non of your module-X would be resolved transitively. Like:
<dependency>
<groupId>com.package</groupId>
<artifactId>module-1</artifactId>
<optional>true</optional>
</dependency>
Still, analyzing the dependency tree might be the most safe and predictable choice.
It does sound a bit strange what you plan to do. In a way you sabotage the dependency management you want to use.
If your module-2 depends on module-1 and has a dependency to it, then any module that depends on module-2 only need to define that one.
You may be able to restrict the depth of the resolution using exclusions: Exclude all transitive dependencies of a single dependency
Newer versions of maven allow wildcards in those.
But: you will need to re-add the ones you actually need, this is by repeating the dependencies you have an other modules. This duplicates the work.
If there are artifacts that cause weirdness it may be possible to define a scope: http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html so it is not propagated to dependant modules as well.
I'm new to Maven and I'm trying to build a project for the first time. I want to write some code that depends on apache lucene. Here's a list of artifacts in maven that I'm trying to get.
Is there any way instead of explicitly listing each artifact, I could simply depend on all artifacts of a given version? I tried this:
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>*</artifactId>
<version>3.6.1</version>
</dependency>
which gave me the error
'dependencies.dependency.artifactId' for org.apache.lucene::jar with value '' does not match a valid id pattern. # line 19, column 19
I can verify that I can download dependencies when I explicitly state them. IE this works fine:
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>3.6.1</version>
</dependency>
I realize depending on everything in lucene is probably sub-optimal, but for doing something quick-and-dirty I'd hate to have to manually populate all these little lucene libraries. What is the typical practice for getting a large set of related dependencies in maven?
Short answer: you can't. Remember you just do this once and later you can simply copy-paste dependencies (not very DRY though). Also consider creating an archetype that will quickly create a skeleton with all required dependencies (for quick and dirty projects).
Longer answer: well, you can work around that. Create a separate pom.xml with:
<packaging>pom</packaging>
and declare all Lucene dependencies there manually, one after another. Once and for all. Later you can simply add a dependency to your pom.xml (that is to groupId/artifactId/version defined there) which will transitively include all dependencies of that pom.xml.
Talking about transitivity: if you depend on a JAR in maven and that JAR has other dependencies, you get that transitive dependencies implicitly. Examine Lucene poms, maybe it's enough to import few of them and rely on transitive dependencies?
Inside a single dependency for a groupId add different artifactId's
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<artifactId>spring-context</artifactId>
<artifactId>spring-beans</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
I added some jars as dependencies in pom.xml, but it seems that some of them are useless because those jars were already downloaded using dependencies mechanism...
Is there a way to see those "built-in" dependencies, so that I could add only the needed dependencies in my pom.xml?
For example if I add a hibernate dependency in pom.xml one for cglib is not needed.
Don't do that - list every dependency of your code, but not of the libraries you use; Maven will do its transitive dependency thing and take care of them.
you can run mvn dependency:tree to get the whole tree including the transient dependencies that get included in your project.
There you can start looking
Hope that helped
First, check out Transitive Dependencies:
Transitive dependencies are a new
feature in Maven 2.0. This allows you
to avoid needing to discover and
specify the libraries that your own
dependencies require, and including
them automatically.
Then, a good dependency analyzer will help...
The mvn command-line is your first aid:
mvn dependency:tree
Sometimes you have to figure out where the version numbers came from (See also: Dependency Management). Here you'll have to unveil the parent relationships, and the 'effective-pom' command can help with that:
mvn help:effective-pom
Tool support is helpful as well...
m2eclipse has a Dependency Tree tab that shows how the different hierarchies collapse::
alt text http://www.sonatype.com/books/m2eclipse-book/reference/figs/web/eclipse_pom-editor-depend-tree.png
IntelliJ has another interesting view that lets you detect the conflicts:
(source: jetbrains.com)
If you are using Eclipse then you are see a visual dependency tree which is automatically generated. While adding a dependency if you do not want it to automatically pull some transitive dependencies use the exclusions tag like so
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>${hibernate.version}</version>
<exclusions>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm-attrs</artifactId>
</exclusion>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
</exclusions>
</dependency>
There are some known conflicts when using certain versions of hibernate and AOP due to cglib.
Is there a way to see those "built-in" dependencies, so that I could add only the needed dependencies in my pom.xml?
There are no built-in dependencies. However, when declaring a dependency on a given artifact, Maven will also retrieve the dependencies of this dependency, transitively. Such dependencies are called 3.4.4. Transitive Dependencies:
A transitive dependency is a dependency of a dependency. If project-a depends on project-b, which in turn depends on project-c, then project-c is considered a transitive dependency of project-a. If project-c depended on project-d, then project-d would also be considered a transitive dependency of project-a.
So if you need a dependency in your project, just declare it (and the dependencies of this dependency will come transitively).
To visualize the dependency tree of a project, the best tool is mvn dependency:tree (or any fronted offered by your favorite IDE). This is a must use tool to analyze your dependencies and check them for proper convergence and potential conflicts resulting in expected version being used.
For example if I add a hibernate dependency in pom.xml one for cglib is not needed.
Actually, this is a bad example, cglib is an optional dependency of Hibernate Core which declares in its pom.xml:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-cglib-repack</artifactId>
<version>2.1_3</version>
<optional>true</optional><!-- think of it as "excluded by default" -->
</dependency>
Hibernate gives you the choice between javassist and cglib, it's up to you to decide which one to use and to declare it explicitly, hence the optional status.
See also
Introduction to the Dependency Mechanism
The whole section 3.4. Project Dependencies in the Maven Reference Guide