Maven: How to find artifacts which depend on another artifact - java

Let us say, ArtifactA depends on ArtifactB and ArtifactC also depends on ArtifactB
I understand that "mvn dependency plugin" can help list the dependencies of a project/artifact.
But how about the reverse? If I want to find the list of projects/artifacts which depend on a given artifact?
From the above example, given ArtifactB, I would like to get ArtifactA and ArtifactC
How can I achieve this?

Maven can only operate on the current project, so it can only detect dependencies between from the current project (or sub-modules) to other projects (including sub-modules of the current project).
So what you can do is search for specific submodules depending on other submodules:
mycompany:parent
/ \
mycompany:child1 mycompany:child2
/ / \
mycompany:grandchild1 mycompany:grandchild2 mycompany:grandchild3
This is how you can find all subprojects that have dependencies to grandchild3:
mvn validate -pl child2/grandchild3 -amd
This will run the validate phase on all projects within the current project that depend on grandchild3.

It is not easy at all. One option is using m2eclipse which has a feature called Class search. In the maven repositories view, right click a repository and enable full index.
Then Navigate > Open type from maven - there you can look through all artifacts available based on java package convention.
Another option is to develop your own tool based on JarAnalyzer for instance, that will accept a JAR file and search through your local maven repository, looking for the most appropriate artifacts that satisfy the the imported packages/classes from the JAR.

Related

get partial maven dependency tree in offline mode

I'm trying to run some unit tests with Apache Maven. I hoped this would be as simple as running the test "goal". But when I did that, maven complained that it could not download some dependencies and thus can't run my tests. This sounds fine, except that I have no idea why it decided I need those dependencies; they are not in my pom.xml, and I doubt they're in my transitive dependencies either. (I'm not sure about that last part; they very well might be in my transitive dependencies.)
Luckily, maven has the perfect tool for this: dependency:tree will tell us exactly which dependency is getting pulled in by what. Except for the small problem that maven thinks to itself "in order to build the tree, I have to resolve the dependencies first" so it tries (and fails) to download those very same dependencies so that it can build the part of the tree that's under them.
So now I don't have a tree, and I have no idea how to proceed from here.
How exactly would you think that maven could resolve transitive dependencies (= dependencies of dependencies) without resolving the dependencies first? Escpecially for the goal "test" also the dependency scope "test" has to be used, which is more then the default scope "compile".
You can use the goal dependency:go-offline to prepare for the offline mode. Maven downloads then all required dependencies. Find the detailed docs for that on https://maven.apache.org/plugins/maven-dependency-plugin/go-offline-mojo.html
You could also have a look at this answer to get another opinion on going online.
The main problem is maven downloads dependencies by demand, you may just check that by triggering different lifecycle phases like mvn initialize, mvn validate, mvn compile, mvn package and checking what maven is trying to download. Sometimes it is possible to figure out project dependencies via analysing project object model (pom), sometimes it is not, especially when plugins define their own dependencies either implicitly or explicitly, some examples below:
we may ask maven-dependency-plugin to download something via dependency:copy-dependencies
exec-maven-plugin has similar functionality: Running Java programs with the exec goal
maven-invoker-plugin may run poms which are part of project but not a part of reactor.
In short: neither maven plugin will able to download all required dependencies. The only "reliable" way to go offline is to run target goal and only then go offline, unfortunately even in this cases some weird things may happen, especially when you or dependency authors are using snapshot versions, version ranges, third-party repositories, etc (my own preference is to run maven with -llr flag to make it more reliable).

Get all 3rd Party dependencies module is using in Maven

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.

Gradle Plugin dependency

What is the exact dependency I need to develop a Gradle Plugin in Java? Ideally I would like to get it from a well-known repository such as Maven Central or similar.
I have a Maven project with a core functionality and I just added two extra plugins, one for Ant, one for Maven. They are already tested and working; easy! Now, I wanted to add a third module for a Gradle plugin to make this functionality also available from any Gradle project.
However, I can't find the exact dependencies I need to develop a Gradle plugin.
The Gradle docs (such as https://docs.gradle.org/current/userguide/java_gradle_plugin.html) are not very well written to say the least. They mention:
the gradleAPI() dependency
or the java-gradle-plugin dependency
But they are quite unclear... no group, no version (really?).
If anyone can enlighten me to where I can get these dependencies from, I would be very thankful.
Gradle's public and internal APIs, aka gradleApi(), are bundled with the Gradle distribution and not independently published and therefore not easily consumable by Maven builds. There's the pending epic #1156 (Ensure plugin cross-version compatibility by allowing a user to depend on gradlePublicApi()) that might help here.
Since Gradle plugins are best to be built with Gradle, a pragmatic solution is to invoke the Gradle build from Maven and attach the produced artifact to the Maven build. Andres Almiray (aalmiray) once described this in the blog post Running Gradle Inside Maven (Web Archive Link). He describes the following high level steps:
Create a new Maven module (e.g. gradle-plugin) and add attach it to the parent POM
In the POM of gradle-plugin add a dependency to your core module. Use the maven-dependency-plugin to store dependencies to the Maven build folder, e.g. target/dependencies.
Create the build.gradle, add a Maven repository that points to target/dependencies (step 2) and let it depend on the core module as well as gradleApi(). Implement the Gradle plugin.
Use the exec-maven-plugin to invoke the Gradle build.
Use the maven-resources-plugin to copy the Gradle built plugin jars to the standard Maven build folder.
Use the build-helper-maven-plugin to attach the copied jars to the Maven build.
Sample project to be found here (gradle-in-maven).
https://docs.gradle.org/current/userguide/custom_plugins.html#sec:custom_plugins_standalone_project
In here it is mentioned that it is gradleApi() and I know that this works (from experience). The localGroovy() on that page is only needed if your plugin code uses groovy (does not apply if you only use groovy in the build.gradle of your plugin).
java-gradle-plugin is a library that makes it a bit simpler to make plugins, it is not required though. I personally prefer using gradleApi only.
EDIT:
It appears I've misunderstood the question. Here are the steps to get gradleApi jar:
Create a Gradle project with your desired Gradle version.
Add implementation gradleApi() dependency.
Import/run the project once.
Go to your .gradle folder (located in home folder in Linux-based operating systems).
Open caches folder
Open the version folder you want, e.g. 6.0.1
Open generated-gradle-jars folder.
Copy the jar to wherever you want and use it.
For me the 6.0.1 jar is at ~/.gradle/caches/6.0.1/generated-gradle-jars/gradle-api-6.0.1.jar
Please note that I have not tested this, I know the jar is there but I haven't tried using it.

Deploying a maven sub-module to a repository for other projects to use (without parent)

The problem is, in our company we have a project with multiple sub-modules, however one of the sub-modules is just a collection of API declarations and is meant for other (3rd praty) projects to use. I want to keep it as a sub-module because is easier to maintain and build (dependency and property inheritance). Other sub-modules in this project are also dependant on it.
The question I have is, if there exist a good practice or a nice way to execute a deploy phase that will upload just this sub-module to a different repository (can be duplicated too) without it having a dependency to parent pom.
What I have already tried:
I have already checked the deploy:deploy-file, but the problem is when it comes to SNAPSHOT builds. We wish to be able to publish SNAPSHOTS and release builds, and snapshots have different repository than release ones, but deploy-file goal can only have one url parameter. I do not wish to use different profile for snapshot deploy. Than I tried to use maven build-helper and its regex-property to be able to change the repository url if the version is a SNAPSHOT, but was unable to do so because of the plugin and regex limitations.
The last option is I can make a plugin for this, but I wish to know if there is a more elegant way to solve this the "maven way".
You can deploy this module separately but only for SNAPSHOT's for a release it does not make sense. The deployment of a module can be done via:
mvn -pl TheModuleYouWouldLikeToDeploy deploy
may be you need to add the option -am (also make dependencies) like:
mvn -am -pl TheModuleYouWouldLikeToDeploy deploy
Apart from that your approach sounds wrong cause if you are using a multi-module build why not deploying the whole build via mvn deploy ? May be it would be better to let do the job via a CI tool like Jenkins.

Help me understand making maven project w/ non-maven jar dependencies usable by others

I'm in the process of learning maven (and java packaging & distribution) with a new oss project I'm making as practice. Here's my situation, all java of course:
My main project is ProjectA, maven-based in a github repository. I have also created one utility project, maven-based, in github: ProjectB. ProjectA depends on a project I have heavily modified that originally was from a google-code ant-based repository, ProjectC.
So, how do I set up the build for ProjectA such that someone can download ProjectA.jar and use it without needing to install jars for ProjectB and ProjectC, and also how do I set up the build such that someone could check out ProjectA and run only 'mvn package' for a full compile?
(Additionally, what should I do with my modified version of ProjectC? include the class files directly into ProjectA, or fork the project into something that could then be used by as a maven dependency?)
I've been reading around, links such as this SO question and this SO question, but I'm unclear how those relate to my particular circumstance. So, any help would be appreciated. Thanks!
So, how do I set up the build for ProjectA such that someone can download ProjectA.jar and use it without needing to install jars for ProjectB and ProjectC
Assuming ProjectA is a JAR, you can create an executable JAR that bundles the dependencies with the Maven Assembly Plugin (and the predefined jar-with-dependencies descriptor) or with the Maven Shade Plugin.
how do I set up the build such that someone could check out ProjectA and run only 'mvn package' for a full compile?
You have to deploy the dependencies to a repository that can be read over HTTP and to declare this repository in your pom.xml. AFAIK, git-hub doesn't offer any facility for that. But any web hosting service with FTP access (or better, scp) should do the trick. If your project is open source, another option would be to use Sonatype's OSS Repository Hosting service.
Just in case, you might want to read this blog post but you won't learn much more things.
The easiest would still be to organize the 3 projects as a multi-modules maven project and to build all modules.
Additionally, what should I do with my modified version of ProjectC?
From a modularization point of view (assuming you found a solution for the above part about repository), it would certainly make sense to have it as a separate module, especially if there is an opportunity someone can use ProjectC outside your project.
You have to publish the code from the additional dependencies. Two options:
Use the maven-shade-plugin to create a maven artifact containing all the content of the B and C jars, and publish that under your own G/A/V coordinates.
Publish copies of B and C under your own G/A/V coordinates using the maven-deploy-plugin to your forge just as you will publish your own code. Different forges have different policies; but if you abide by the licenses of B and C you should be OK.

Categories