For example I have dependency:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.6</version>
</dependency>
Can I exclude one class, for example org/slf4j/Marker.class?
Try it with the shade plugin
Details on why use shade and basic usage
Excluding a single class in not possible. Within <dependency> tags you can define <exclusions/>. However, these are for entire dependencies.
The shade plugin should be handled with care. Generally, it's not good practice to be creating a jar containing all your dependencies in one place as it tends to lead to problems if you are to be using the produced artifact in another project as a dependency. For example, shading slf4j in your jar and then depending on your artifact in another project where you have another slf4j will bring you grief.
You could change those classes and define them in a different jar/module which should be included as a dependency before the jar that supplies the dependency where your class to be excluded resides (Marker.class).
Maven remembers the classpath ordering from version 2.0.9.
Related
I saw other similar questions but none of them had the answer I was looking for.
My question is related to the Log4j2 vulnerability recently.
I have a Maven Spring boot project where I did not switch the default logging system to Log4j2. When I run mvn dependency:tree I only see the log4j-to-slf4j jar and log4j-api jar but not the log4j-core jar, so according to https://spring.io/blog/2021/12/10/log4j2-vulnerability-and-spring-boot I assume my app is not affected.
But when i generate the effective POM I see the following
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core<artifactId>
<version>2.14.0</version>
</dependency>
I see many other dependencies in the effective POM like log4j-couchdb which the app is definitely not using (the app is not using database), so my thinking is a dependency that is in effective POM does not mean it is packaged to the app jar and used?
When I read up on definitions of effective POM, I got the feeling that whatever is in effective POM is being packaged and used by the app, so I am confused. Hope someone can help me on this. Thanks!
I made custom dependency which uses spring 4.x version and I include it in a project which uses spring 3.x version. When a method from this dependency is called it uses classes from spring 3.x version not from 4.x. Is it possible to force this dependency to use spring 4.x whereas the project itself will use spring 3.x ?
I don't think that is possible due to the fact that, when finally project is running, the dependencies are resolved on the basis of group id and artifact id and not on their version. Which is why your application is using 3.x dependency as it is overriding the one mentioned in the parent project. Hope this helps.
Yes, you can if you separate your application (which you probably don't want to). Another approach: You might think about using another class loader within the same JVM. This, however, leads to a probably bigger bunch of problems, especially using Spring.
Dzone article about loading the same class from libs with different versions.
As pvpkiran noted, you want to exclude the spring v3 transitive dependency from your custom artifact. From the maven documentation - Optional Dependencies and Dependency Exclusions:
<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>
Whhy is Spring published under two systems of artifact names?
For example, the spring core is (usually?) used as
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
(see: http://mvnrepository.com/artifact/org.springframework/spring-core/3.1.1.RELEASE )
but it is also published as
<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.core</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
(see: http://ebr.springsource.com/repository/app/bundle/version/detail?name=org.springframework.core&version=3.1.1.RELEASE )
Questions:
Why do they publish the same (?) jar as two different artifacts?
Which one should I use?
Why can I find the first jar in the maven central repository, but not the second jar? In which repository can I find the second jar?
The first is the standard packaging, the second is the OSGI-conforming version.
Check out Obtaining Spring 3 Artifacts with Maven on SpringSource Blog. It should answer all your questions:
In general, Spring publishes its artifacts to two different places:
Maven Central, which is the default repository Maven queries, and does not require any special configuration to use
The Enterprise Bundle Repository (EBR), which is run by SpringSource and also hosts all the libraries that integrate with Spring
So the first thing you need to decide when obtaining Spring with Maven is which place you'll get it from. In general, if you care about OSGi, use the EBR, since it houses OSGi compatible artifacts for all of Spring's dependencies, such as Hibernate and Freemarker. If OSGi does not matter to you, either place works, though there are some pros and cons between them. In general, pick one place or the other for your project; do not mix them. This is particularly important since EBR artifacts use a different naming convention than Maven Central artifacts.
... ...
Maven is a bit over my head sometimes... I have created a library which has an optional dependency on slf4j and on log4j. By optional, I mean:
My library needs those logging frameworks at compile time
My library doesn't need them at runtime, but if it "discovers" them, it will use them
Currently, I have marked that dependency as "optional" and "provided":
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<type>jar</type>
<scope>provided</scope>
<optional>true</optional>
</dependency>
But some of my users have reported issues, because they don't need log4 / slf4j. Is my dependency correct? Unfortunately, I find the official documentation a bit too abstract to understand this problem.
Did you check this documentation. It describes your use case very good. Marking dependencies as optional will not resolve them as transitive dependencies in the application which use your library (even if the scope is compile).
In difference to <scope>provided</scope> which is used for required dependencies which will be provided by the runtime environment an <optional>true</optional> dependency is not necessarily meant to be required (The idea is that some of the dependencies are only used for certain features in the project, and will not be needed if that feature isn't used.).
If a project which uses your library will use any functionallity provided by the optional dependencies the project has to declare these dependencies for their own.
As your configuration seems to be correct for me I do not know the reason what probles occur. Maybe your optional dependencies get resolved by other libraries in versions you do not expect. That of course might cause problems.
What is the meaning of "bundle" e.g in this dependency:
<dependency>
<groupId>org.apache.abdera</groupId>
<artifactId>abdera-core</artifactId>
<version>1.1.2</version>
<type>bundle</type>
<scope>compile</scope>
</dependency>
This kind of artifact is an OSGi bundle, typically produced using the maven-bundle-plugin which is part of Apache Felix.
The plugin treats all the classes available to your module (the module's own classes, classes provided by dependencies, other classes on the classpath) as one giant set, then lets you select a subset of those classes to bundle into a jar. It also creates the necessary manifest information to make the artifact an OSGi bundle.
So the artifact you're pulling in by using this dependency is a jar, however it's a jar built by choosing a subset from a much larger set of classes, not just the classes that were defined inside the abdera-core module.
If you have a look at the pom for the abdera project you'll see the maven-bundle-plugin configuration which will give you an idea of which classes have been added to the bundle, and which have been held back.