I have two applications - A and B.
In Application A there are some jars say J1,J2,J3.
And in Application B there is overlay and dependency of Application A. But I don't want jar J2 in application B.
How to exclude jar J2 ?
What you are asking for isn't possible. If Application B has dependencies on application A; and A depends on J2 - how do you think you can run "B" without providing J2?
The only thing that can work: if you can further slice your applications; it might be possible to come up with some component B'; where B' depends on A'; and A' does not depend on J2. Then you can package B' without J2.
You can use the Maven dependency exclusions as described here:
<project>
...
<dependencies>
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
However, bear in mind that you might face ClassNotFoundExceptions at runtime if the class required is no longer present.
Related
I have a project A which creates 10 artifacts with same group id . For example generated artifacts from the project A will be -
<groupId>com.example.abc</groupId>
<artifactId>A1</artifactId>
<version>v1</version>
<groupId>com.example.abc</groupId>
<artifactId>A2</artifactId>
<version>v2</version>
Likewise from A1 to A10 and v1 to v10 . Group Id remains same.
The generated artifacts needs to be used in another project B but I need to exclude two dependencies which are common to all the ten artifacts generated by Project A.
I know I can add dependency management tag in Project B's pom.xml with explicit exclusions tag.
What I am looking for is a less verbose way of excluding those two dependencies ? I tried with
<dependencyManagement>
<dependency>
<groupId>com.example.abc</groupId>
<artifactId>*</artifactId>
<version>*</version>
<exclusions>
<exclusion>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencyManagement>
which is not working .
Is there any less verbose way ?
could you declare the mockito dependency as a one provide.
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>YOUR VERSION</version>
<scope>provided</scope>
</dependency>
Note: The dependency won't end up inside the build artifact but it's still available during tests
Take a look at here too.
Regards.
I have 2 stub jars - say B.jar,C.jar which have XyZ.class in common.The dependency in pom is below:
<dependency>
<groupId>pack.y.b</groupId>
<artifactId>B</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>pack.y.b</groupId>
<artifactId>C</artifactId>
<version>1.0</version>
</dependency>
It is known that dependencies are loaded from pom.xml in the order it is mentioned as in Maven: Multiple class with the same path implemented in different jar that is indeed how it behaves i.e in local, I get XyZ.class loaded from B.jar right and if B is not available, it is loaded from C.
In contrary, during runtime after deployment, the class is extracted from C instead of B and I ain't sure why it happens and how to rectify. Please clarify and favour.
I'm having some problems with conflicting versions of some jars. I have a dependency on a library group-a:artifact-a:0.0.1 that has a dependency on group-b:artifact-b:0.0.1, but I don't want that group-b:artifact-b:0.0.1 to be included given that I know that at runtime there will be group-b:artifact-b:0.0.2.
How do I have to write the pom.xml file?
Is this one of the following correct? And what's the difference between these?
Solution 1:
Exclude group-b:artifact-b from group-a:artifact-a:0.0.1:
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>0.0.1</version>
<exclusions>
<exclusion>
<groupId>group-b</groupId>
<artifactId>artifact-b</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Solution 2:
Add group-b:artifact-b dependency as provided:
<dependencies>
<dependency>
<groupId>group-b</groupId>
<artifactId>artifact-b</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
Solution 3:
Add group-b:artifact-b dependency as runtime:
<dependencies>
<dependency>
<groupId>group-b</groupId>
<artifactId>artifact-b</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
Solution 4:
Add group-b:artifact-b dependency as provided or runtime and exclude it from group-a:artifact-a:0.0.1.
UPDATE:
Sorry for not being explicit, but yes #Tunaki's assumption is correct, the dependency group-b:artifact-b:0.0.2 is not required at compile time.
Option 5: Just declare the version explicitly in your POM.
Maven will overwrite the transitive dependencies if you explicitly declare them in the pom. You don't need to do any mucking about with provided or runtime scope.
According to the docs (emphasis mine):
Dependency mediation - this determines what version of a dependency will be used when multiple versions of an artifact are encountered. Currently, Maven 2.0 only supports using the "nearest definition" which means that it will use the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM. Note that if two dependency versions are at the same depth in the dependency tree, until Maven 2.0.8 it was not defined which one would win, but since Maven 2.0.9 it's the order in the declaration that counts: the first declaration wins.
So your pom should just be:
<dependencies>
<dependency>
<groupId>group-b</groupId>
<artifactId>artifact-b</artifactId>
<version>0.0.2</version>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
You should use solution 4. Let's go through each solution:
Solution 1
This is using the exclusions principle of Maven. Maven resolves dependencies transitively. But when you do not want a specific transitive dependency to be included in your classpath, you can exclude it using this mechanism.
The excluded dependency will not be used at compile-time or run-time.
But this is not what you want, since you know that your project requires group-b:artifact-b at run-time. In this scenario, the pom.xml does not declare it.
Solution 2
You are using the provided scope. provided in Maven means that this dependency is required at compile-time but should not be included in the final artifact. Typically, this dependency will be provided at run-time by a container, such as a web server.
As such, Maven will override the transitive dependency group-b:artifact-b:0.0.1 of group-a:artifact-a. In the final dependency tree, group-b:artifact-b:0.0.2 will be resolved as a provided dependency and will not be included in the final artifact (for example, if building a war, this library will not end up in WEB-INF/lib).
Solution 3
This time, you are using the runtime scope. This is much like Solution 2.
The difference is that in the final dependency tree, group-b:artifact-b:0.0.2 will be resolved as a run-time dependency and will be included in the final artifact (for example, if building a war, this library will end up in WEB-INF/lib).
Solution 4
This is the same as solution 2 and 3. The difference is that Maven will not override the dependency since you are explicitely excluding it from the list of transitive dependencies of artifact-a. But the result will be the same.
What is the correct solution?
This really depends on how your dependency will be present at run-rime. If it provided by a container, you should use Solution 4 with the provided scope. If not, you should use Solution 4 with the runtime scope.
I am suggesting this solution because:
You are explicitely excluding the unwanted dependency from artifact-a transitive dependency: this makes it more clear that that specific dependency should not be used in the project.
You are explicitely including the wanted dependency in the right scope and the right version. Again, this makes the pom.xml easier to read and to understand.
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>0.0.1</version>
<exclusions>
<exclusion>
<groupId>group-b</groupId>
<artifactId>artifact-b</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>group-b</groupId>
<artifactId>artifact-b</artifactId>
<version>0.0.2</version>
<scope>provided</scope> <!-- or runtime, depending on your specific case -->
</dependency>
</dependencies>
I have a project foo-instrumented that depends on foo.
This project actually instruments foo with additional code, and replaces it. That is, foo is a compile-time dependency of foo-instrumented but it is definitely not a runtime dependency (foo-instrumented replaces foo), and it should not be propagated to children (that is, projects depending on foo-instrumented should not end up depending on foo).
Is there an appropriate maven scope for that kind of dependency, or another solution?
Edit: I am not being clear enough with my request: although foo should not end up in the children project dependencies, foo's dependencies should (e.g. if foo depends on log4j, then a project that depends on foo-instrumented should have log4j as part of its dependencies), which seems to rule out the provided scope.
Thanks!
Edit: Okay, I need to have a little rant here: DID ANY REAL, ACTUAL HUMAN BEING ACTUALLY UNDERSTAND THE MAVEN DOCS? I had a look at a few pages and guess what: no explanations, no illustrations, JUST TONS OF XML VOMIT. XML VOMIT IS NOT DOCUMENTATION, PEOPLE!
You should use the import scope. In your foo-instrumented project:
<dependencies>
<dependency>
<groupId>bar</groupId>
<artifactId>foo</artifactId>
<type>pom</type>
<scope>import</scope>
<dependency>
<dependencies>
This will pull the dependencies of foo into foo-instrumented without also including foo.
You cannot exclude a dependency, but still include it's dependencies.
However, you can define an exclusion for your non-instrumented dependency and add the dependencies over to your other module (again). When you define the dependency to foo-instrumented, do:
<dependencies>
<dependency>
<groupId>bar</groupId>
<artifactId>foo-instrumented</artifactId>
<exclusions>
<exclusion>
<groupId>bar</groupId>
<!-- Exclude the non-instrumented dependency: -->
<artifactId>foo</artifactId>
</exclusion>
</exclusions>
<dependency>
<!-- Add the dependencies you need for foo to work here -->
<dependencies>
I have a case that I have the following cyclic dependencies in maven:
JAR A version 1.1 depends on JAR B version 1.0
JAR B version 1.1 depends on JAR A version 1.0
For some reason that I don't know, Maven brings all the 4 JARs: A 1.0, A 1.1, B 1.0 and B 1.1, which results in a classpath conflict.
This really sucks. I already ask the developers of both JARs to fix this, however I can't simply sit and wait for the day that they decide to fix this.
I tried this:
<dependency>
<groupId>groupA</groupId>
<artifactId>artifactA</artifactId>
<version>1.1</version>
<type>pom</type>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>groupB</groupId>
<artifactId>artifactB</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>groupB</groupId>
<artifactId>artifactB</artifactId>
<version>1.1</version>
<type>pom</type>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>groupA</groupId>
<artifactId>artifactA</artifactId>
</exclusion>
</exclusions>
</dependency>
The result is that maven excludes all of the JARs as if none dependency were added, and the project does not compiles because there are missing classes.
So, other than just asking both JARs developers to solve this, what can I do? How can I import both the new dependencies while leaving out both the old ones?
Pragmatic solution would be to redeclare the unwanted dependencies as provided, for example:
<dependency>
<groupId>groupA</groupId>
<artifactId>artifactA</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
I'm not particularly fond of using provided in such manner, since it leaves the dependency in the compile time and could lead to unwanted compile dependencies, but I see no other way in your case ;(.