I have a java maven project X which depends on project Y built by other team. That team provide us with new versions of y.jar. We wanted to dynamically load y.jar.
So, we provided path to y.jar in our project X and project X loads y.jar from that path whenever new version is available. We have specified dependency of project Y in project X's pom with provided scope (so that y.jar wont get bundled inside x.jar).
But then this does not include dependencies specified in project Y in project X. And during run time, we get NoClassDefFoundError error for those classes included in Y's dependencies.
How can I include project Y's dependencies in project X? Usually we import dependencies of other pom with import scope. But I have already specified project Y with provided scope. (Note that x.jar is fat jar and contains all dependencies specified in X's pom.)
What could be best approach to manage dependencies in this scenario. Should y.jar be fat jar?
If your scope for Y is marked as provided then yes Y should be on the classpath and be a fat jar especially if the POM is available and has its dependencies listed. If you are still getting NOCLASSDEFFOUND, I would explore the y.jar - I would assume its POM is faulty ie declaring dependencies not included in the jar. If Y is not a fat jar or its POM is faulty then you need to explicitly exclude its dependencies and then add them as a compile time dependency. Possibly shading them in. You can use exclusion statements under dependencies.
Read about that here
https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
Personally, I hate relying on derived dependencies and usually explicitly declare them in my POM. If they are provided by Y then I would scope them as provided, otherwise scope as compile and ensure they are shaded into my jar.
Related
I do not know if it is possible for maven to act in this way :
An artifact does not exist or is not accessible
Mark this artifact as optional
...I am trying to generate a dependency does not exist and mark it as optional and make a buil with Maven in Eclipse ... but it seems that it does not like ..:
<dependency>
<groupId>com.x.y</groupId>
<artifactId>myOptionalArtifact</artifactId>
<optional>true</optional>
</dependency>
..... but Maven crashes.... :
BUILD FAILURE
Could not find artifact com.x.y:myOptionalArtifact:jar:1.0
I'm starting to guess that the optional tag can NOT be used in this sense ???
Maven treats all dependencies you list in the <project><dependencies> section of your POM as required for your project to build; therefore, any failure to find one of those dependencies fails the build, and this is expected behavior.
The <optional> tag you reference is used for when your project is a dependency of another project, indicating to Maven that the optional dependency should be automatically excluded when resolving the transitive dependencies in your main project.
From https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html:
Optional dependencies - If project Y depends on project Z, the owner of project can mark project Z as an optional dependency, using the "optional" element. When project X depends on project Y, X will depend only on Y and not on Y's optional dependency Z. The owner of project X may then explicitly add a dependency on Z, at her option. (It may be helpful to think of optional dependencies as "excluded by default.")
If you really want to remove a dependency from the dependency tree, you need to figure out all transitive place where it is used and add exclusions to the respective dependencies.
Optional or provided won't help. The artifact remains on the classpath and therefore, Maven tries to load it.
I am not very much experienced with Maven and it's compilation and packaging logic gets me confused.
I have some dependencies declares as :
<dependency>
<groupId>com.dependency_group</groupId>
<artifactId>dependency_1</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.dependency_group</groupId>
<artifactId>dependency_2</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
So as far as I understand, dependency_1 will be added to the classpath of my program as something that comes along with my jar, and dependency_2 on the other hand, will be added to the classpath as something that the system runtime will provide upon deployment.
Then I run the package goal of Maven and none of my dependencies are packed with my code (I am using the shade plugin, but even without it nothing changes).
I expected that when some dependency is set as compile scope, it will be exported with my compiled code, since AFAICS, there's no point in setting the classpath saying a dependency will come along with my code, and Maven just don't package that dependency with it. It looks to me as if Maven is not obeying it's contract.
So:
1 - What's the logic behind this?
2 - Do I have to always use the Assembly plugin?
3 - Are there cases where people will define a dependency as compile and will not want it packaged within a jar?
Let me shed some light on the main point here. There are fundamentally two kinds of java artifacts:
Applications, i.e. ears, wars, executable jars
Libraries, i.e. jars that are meant to be used as dependencies for other artifacts.
For Applications your reasoning makes perfectly sense. Wars and Ears automatically package all their compile dependencies and you need no assembly plugin for that. For libraries, you do not pack the dependencies into the library. Maven handles transitive dependency resolution and would be confused if you put a fat jar on the classpath.
The thing is that packaging jar can be both a libary or an application. If you want a standalone application, you need to tell Maven to package everything, e.g. by using the assembly plugin or shade plugin.
You use compile scope when you want some dependencies to come along with your code. For example you want Jackson to be a part of your application if you are using it for json serialization.
You use provided scope, if you want dependency to be on the classpath during the compilation but wont be included within your application. It must be provided by running environment. For example you want Lombok as it is compile only library, or you want to have Servlet Api dependency as provided when you are writing servlet application because such app will be ran on servlet container thus there is no need to pack it within your application (it will be available in container runtime)
Do I have to always use the Assembly plugin
Nobody forces you to do so.
I have project X containing modules Y and Z. Module Y relies on module Z (a third party library which I maintain a private fork of).
On a maven build module Z relocates it's very version specific packages to a seperate package e.g "com.example.z.internal.MyClass" becomes "com.example.z.internal.v23.MyClass".
When I didn't have module Z in my project it was fine as IntelliJ resolved to the maven dependency which contained the remappings however now I have module Z within the project, IntelliJ keeps being clever and using the module as the dependency not the artifact.
Is there a way to force IntelliJ to only use the artifact as the dependency?
First option: remove the module of your project, intellij will not recompile all the time this module, and make a separated project for it when you want to modify this module.
Second option: build a released version X of your module (not a snapshot) and make your module to depend on this released version. Doing that, intellij will continue to make your fork, but under a snapshot version which you don't depend on.
I have the following dependency in my gradle file.
compile 'org.A:A:1.0'
which automatically pulls in
'org.B:B:1.0'
and many other jars which it depends on.
But,my project requires repackaged A.jar (let's call it A*.jar which I installed in a local maven repository as custom version).
So now I change the dependency as below
compile 'org.A:A:custom'
which doesn't pull in any of the dependencies mentioned in the pom.xml file present inside the A.
jar file (which it would, had it been org.A:A:1.0)
My questions are:
1) Based on what does the statement compile org.A:A:1.0 pull other jars ? Is it pom.xml file present inside the jar?
2) What are the changes required if I want to automatically pull in both 'org.B:B:custom' and regular versions of other jars which are dependee of org.A:A:1.0
Maven will read the pom file for the artifact it resolves as well. In there the dependencies are found and resolved.
You simply need to also upload the pom of A*.jar and modify the version of it accordingly to A* - that should already do the trick.
I have a multi-module maven project that uses some dependencies from netflix. The trouble is that those dependencies are built using gradle and use a runtime scope. When I build my project I then have only the direct dependency loaded but not it's own dependencies.
To fix that I added dependencyManagement entries to transform all the runtime scopes to compile scopes. They usually go in pack of 10 to 20 entries so what I want is to be able to make some pom that would only address this issue and be able to load it any time I need a dependency.
I know this can be done as i've read Maven pull dependencies via middle pom file and How to use POMs as a dependency in Maven? but I was wondering how I may carry those poms inside my current multi-module project.
I'd like to have those in my parent module and avoid needing to create one sub-module per pom. Like pom-dep1.xml, pom-dep2.xml... and have those bundled in my build. Is that possible ?
Thanks