I have gradle scala project(Lets say "A") which uses the library(Lets say "X"). And i have used this Library-"X" in the build.gradle of Project-A as shown below and i'm using the Library-X classes to perform some operations.
build.gradle of Project-"A"
implementation "com.x.y.z.stone:central-dl-spark-common-integration-logging:0.4.0-SNAPSHOT"
Now Project-"A" is itself a library which is used in the Project-"B" and this Project-B is maven build. Now when i call the Project-A function which is acting as library in-turn uses Library-X function. But Project-B is complaining that class not found error as shown below. This is the Library-X class
java.lang.NoClassDefFoundError: com/x/y/z/integrationlogging/IntegrationLogging$
My question is do we even need to declare the Library-X in the pom.xml of Project-B as well?
No: if Project-B imports Project-A, and Project-A has an internal dependency on Library-X, you usually don't need to do anything and it will resolve automatically.
Some exceptions may include conflicts and libraries that exist in a private nexus. For the former, you need to resolve the conflict in the pom.xml. For the latter, you need to make sure your repo is accessible from wherever you're compiling.
No.
Dependencies are transitive "by default" unless the opposite is specificied (either with exclusions or scopes (a test scoped dependency won't be transitively propagated for instance)).
EDIT: you can use mvn dependency:tree to get a better understanding of your dependencies.
One possibility is that library X is pulled in different incompatible versions.
Thank you for the having look at my post. By adding the Library-X under tag in the Project-B pom.xml, worked.Something shown below
<artifactSet>
<include>x.y.stone:central-dl-spark-common-integration-logging</include>
</artifactSet>
Related
We have a multi-module maven project. I have a use case where I want to know to get a list of all the dependencies which is being used in code with version:
If its declared in pom and being used.
Not declared in pom but still being used (transitively imported).
Bonus would be if the approach can exclude the deps which are being declared in pom but not being used in the code.
Please suggest the best way to achieve this. TIA.
Just use the mvn dependency:tree command.
There's the Maven Dependency Plugin:
The dependency plugin provides the capability to manipulate artifacts. It can copy and/or unpack artifacts from local or remote repositories to a specified location.
with its tree goal:
Displays the dependency tree for this project.
Regarding your bonus there's the analyze goal:
analyzes the dependencies of this project and determines which are: used and declared; used and undeclared; unused and declared.
and the analyze-only goal:
is the same as analyze, but is meant to be bound in a pom. It does not fork the build and execute test-compile.
I am developing an application which will be published to nexus repository used as a dependency by other applications.
I am using gradle for the build, and have applied the maven plugin.
When i do a gradle install, the dependency scope in the generated pom is automatically applied as 'runtime' for the libraries that i have added as dependencies.
I am using "implementation" for adding my dependencies.
What is the recommended scope for the libraries i my case ?
I see compile would have been useful , but is now deprecated. Should i use compileClasspath ?
Thanks !
The scope of the dependencies is controlled by the configuration you define them in in the dependencies { } block.
Gradle has great table with descriptions as to when you should use them.
Most commonly, you'll use these two:
implementation - This is where you should declare dependencies which are purely internal and not meant to be exposed to consumers.
api - This is where you should declare dependencies which are transitively exported to consumers, for compile.
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.
We have several deployables, and have extracted common code into several libraries. Deployable app A has a (default-scoped) Maven dependency on library B, and a test-scoped dependency on library C.
I made a change to library B, which used a method from, and so created a dependency on, library C. This caused app A to fail at run-time with NoClassDefFoundErrors. App A's unit tests all passed, of course, so we only found this in our staging environment. (Other apps either had no direct dependency on library C, or had a default-scoped dependency on it, and so continued to work.)
The obvious fix worked, of course: I edited A's pom.xml to make the dependency on C default scope.
My question is: Are we doing something wrong? Or is this how things are supposed to work? Is anyone aware of an automated way of detecting the potential problem at build-time and failing the build?
You are not doing something wrong. Maven made a peculiar design choice here. See also
Maven: test vs. transitive compile, especially Tunakis comment on my question.
and
Maven dependency within dependency with different scope
My advice: Eliminate C from A's pom.xml. Only add test dependencies if these dependencies are not already on the dependency tree.
I've extended an abstract class and implemented a method that I will use with Mule over and over. I want to add it to a library that I will repo on Maven central. It depends on a JAR that's provided in the Mule connector devkit (sdk for Mule connectors). How do I formally publish or tell others publicly that my common library will not work without the earlier dependency too? The dependencies org.json and fasterXML...Jackson..etc.
My code module is an HttpProcessMessage and the over-used method returns a String of formatted JSON. The message POJO gets loaded and then ultimately my method is like a toString() method but more sophisticated.
I would like for this class to be part of a common library that would become part of the community. I wish that my code here would be the foundation and have no dependencies. Now, I'm looking for an answer to address the dependencies and inform the public.
That's one of the main benefits of Maven and other dependency management tools, when your dependency is added to their Maven project, Maven will automatically fetch transitive dependencies. So there is no need to let people know what dependencies you rely on. It will automatically be handled and they can use Maven command if they wish or inspect the maven artefact to determine what transitive dependencies you rely on.
You will need to add the com.faster.xml dependencies and org.json dependencies to your Maven pom.xml and all this information is packaged alongside your Maven artefact and will be stored in a Maven repo.
More info on Maven dependencies here: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
If they are manually installing the jar outside of Maven/Gradle etc. then theres not much you can do except provide them a detailed README on installation instructions.