How to list all dependencies of a library? - java

When I have an aar library how to list all the dependencies of this aar ? for exemple i have facebook-core-5.15.1.aar and the dependencies are :
+--- com.facebook.android:facebook-core:5.15.1
| +--- com.parse.bolts:bolts-android:1.4.0
| | +--- com.parse.bolts:bolts-tasks:1.4.0
| | \--- com.parse.bolts:bolts-applinks:1.4.0
| | \--- com.parse.bolts:bolts-tasks:1.4.0
| +--- com.android.support:support-annotations:27.0.2
| +--- com.android.support:support-core-utils:27.0.2
| | +--- com.android.support:support-annotations:27.0.2
| | \--- com.android.support:support-compat:27.0.2
| | +--- com.android.support:support-annotations:27.0.2
| | \--- android.arch.lifecycle:runtime:1.0.3
| | +--- android.arch.lifecycle:common:1.0.3
| | \--- android.arch.core:common:1.0.0
| \--- com.android.installreferrer:installreferrer:1.1
How to retrieve this dependencies tree from a command line? and accessory how to know where to download all thoses dependencies?
I need to know this because as far as I know If I add com.facebook.android:facebook-core:5.15.1.aar in my project without adding com.parse.bolts:bolts-android:1.4.0.aar (for exemple), then my project will not work.
In the research I did I found this way to know all the dependencies needed by a libraries, I must create a android studio project, add the dependencies like this:
dependencies {
implementation 'com.facebook.android:facebook-core:5.15.1'
}
and then run: gradlew app:dependencies But I want to avoid to create an android project and I need to automate the task from a command line

AFAIK, when you run ./gradlew app:dependencies command, it will report all dependencies of the app module, no command for specific library's dependencies report. However, Android Studio have the resolved dependencies report (after synced project), you may check if it is your need.
File > Project Structure > Dependencies menu > Your modules (app) > Resolved dependencies.

You might be looking for something already existing, for example:
https://github.com/status-im/go-maven-resolver. Usage:
$ echo commons-io:commons-io:2.4 | ./go-maven-resolver
https://repo.maven.apache.org/maven2/commons-io/commons-io/2.4/commons-io-2.4.pom
https://repo.maven.apache.org/maven2/org/apache/commons/commons-parent/25/commons-parent-25.pom
https://repo.maven.apache.org/maven2/org/apache/apache/9/apache-9.pom
Although it gives you dependency URLs, but you can easily parse them to get GAV coordinates, or modify the script to print out the tree-like structure.

List of dependencies can be found on mvnrepository.com or search.maven.org
You can write a program that will parse these sites and give out data in the desired format
P.S.
Resolving child dependencies is one of the main purposes of gradle. The fact that you have to manually write child dependencies indicates that you have some kind of error in the configuration (maybe a newer version of the dependency is already included)

A library (aar or jar) does not contain any dependency informations by itself. However, libraries are
generally available in Maven repositories, and such repositories provide dependency informations via
POM files (which are XML files).
The URL where a POM file is available can be constructed from the following elements:
Repository URL
groupId
artifactId
version
The main repository is Maven Central. Its URL is https://repo1.maven.org/maven2/. Most libraries are
available there.
For com.facebook.android:facebook-core:5.15.1, the POM URL is:
https://repo1.maven.org/maven2/com/facebook/android/facebook-core/5.15.1/facebook-core-5.15.1.pom
The file contains a <dependencies> element:
<dependencies>
<dependency>
<groupId>com.parse.bolts</groupId>
<artifactId>bolts-android</artifactId>
<version>1.4.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.android.support</groupId>
<artifactId>support-annotations</artifactId>
<version>27.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.android.support</groupId>
<artifactId>support-core-utils</artifactId>
<version>27.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.android.installreferrer</groupId>
<artifactId>installreferrer</artifactId>
<version>1.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
Only the direct dependencies are listed. To get the so-called "transitive dependencies", you need to iterate
the process and fetch the POM files of the dependencies.
Note that Google publishes its Android libraries in its own Maven repository, at this URL:
https://maven.google.com/
So, for com.google.firebase:firebase-messaging:12.0.1, the POM URL is:
https://maven.google.com/com/google/firebase/firebase-messaging/12.0.1/firebase-messaging-12.0.1.pom

Related

Maven: How to update transitive dependency (snakeyaml)?

I scanned my Spring Boot app using Synk and there are some vulnerabilities after scan. For this reason, I needed to update snakeyaml, but as far as I know, it is a dependency below spring-boot-starter-web.
Here is the dependency tree for my project:
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.7.5:compile
[INFO] | +- org.springframework.boot:spring-boot-starter:jar:2.7.5:compile
[INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:2.7.5:compile
[INFO] | | | +- ch.qos.logback:logback-classic:jar:1.2.11:compile
[INFO] | | | | \- ch.qos.logback:logback-core:jar:1.2.11:compile
[INFO] | | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.17.2:compile
[INFO] | | | | \- org.apache.logging.log4j:log4j-api:jar:2.17.2:compile
[INFO] | | | \- org.slf4j:jul-to-slf4j:jar:1.7.36:compile
[INFO] | | +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] | | \- org.yaml:snakeyaml:jar:1.30:compile
In this scene, how can I update snakeyaml? Should I add a remove annotation below the spring-boot-starter-web and then add the following dependency in pom.xml?
I know the last version also has a vulnerability, but I just wanted to know what should I do for this kind of situations (assume that the last version has no vulnerability)? Any idea?
<!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
</dependency>
First off all don't panic and step back. Although the dependency mentioned has a vulnerability, if you don't actually use it (i.e. no YAML in your application) it actually doesn't apply. Those dependency scans are pretty dumb as they can only see dependencies not the fact that you are or aren't using them.
That being said, to fix you should upgrade the Spring Boot version for your application. For this, assuming you are using a Spring Boot as a parent, update that version.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.8</version>
</parent>
NOTE: Don't mix modules of different versions of Spring Boot (or any framework/library for that matter) as that will lead to problems. So don't put a version tag in your dependencies (at least not the spring-boot-starter-* ones!).
This has Snake YAML 1.30, if you can you could also upgrade to 3.0.2 which actually includes the 1.33 version.
To upgrade only Snake YAML you can just override the version property used by Spring Boot to manage the dependencies. The version properties are documented in the Spring Boot Documentation. How to override those versions is documented in the Spring Boot Plugin Documentation.
In short you would need to override the snakeyaml.version property with the version you wish to use (that is only for 2.7.x) if you upgrade to 3.02 you don't need this.
<properties>
<snakeyaml.version>1.33</snakeyaml.version>
</properties>
This will pull in that version. You don't need to exclude anything or use dependency management for this. Drawback when a new version of Snake YAML comes out and Spring Boot pulls that in, this will override it. So take care when updating after this.
This all being said, as mentioned in the beginning the fact that a certain jar/dependency is included doesn't mean it is a risk. If not used it won't pose a risk, so instead of panicking on Snyk warnings you should properly investigate them.
Try to update whatever brings you the dependency (here: spring-boot-starter-web)
If not possible: Add an entry to <dependencyManagement> with the newer version and put a comment into the pom.xml why you do this (Vulnerability XY).

Cannot import nested Maven project into eclipse

I am trying to import a Maven project into eclipse but I am having difficulty getting Eclipse to see the java files as source files and not as resource files.
I am able to clean/build the project via eclipse however.
The project has parent pom.xml which lists several sub projects as modules.
If I directly import any of the subprojects it will see the java files as source files, but this will make it difficult to manage different versions of the project if each version will require multiple interrelated projects.
I would ideally like a way to import just the parent project and have all sub projects managed under it.
Project file tree:
ProjectFoo
+.settings
+base
+lib
+SubProjectFooA
| +.settings\
| +scs
| +target
| +.classpath
| +.project
| +pom.xml
+SubProjectFooB
| +.settings\
| +scs
| +target
| +.classpath
| +.project
| +pom.xml
+SubProjectFooC
| +.settings\
| +scs
| +target
| +.classpath
| +.project
| +pom.xml
+SubProjectFooD
| +.settings\
| +scs
| +target
| +.classpath
| +.project
| +pom.xml
+SubProjectFooE
| +.settings\
| +scs
| +target
| +.classpath
| +.project
| +pom.xml
+SubProjectFooF
+.settings\
+scs
+target
+.classpath
+.project
+pom.xml
In the parent pom.xml this is how all the sub projects are added. I am not very familiar with maven and think part of the problem could be the sub projects are added as modules, but I am not certain yet.
<modules>
<module>SubProjectFooA</module>
<module>SubProjectFooB</module>
<module>SubProjectFooC</module>
<module>SubProjectFooD</module>
<module>SubProjectFooE</module>
<module>SubProjectFooF</module>
</modules>
Things I have tried:
Pull copy of project from git, run mvn eclipse:clean eclipse:eclipse, then import into Eclipse
Directly adding javabuilder and javanature to .project file
Agree: this can be cumbersome, especially with a large number of sub-projects.
The parent pom will typically be its own project. Other projects that use the parent pom will also be their own projects, and linked to the parent pom using Maven.
Files/directories such as .settings, .classpath, .project and pom.xml must be at the top level of an Eclipse project (nesting sub-projects inside another related project will probably not work).
While there may be settings for <modules> in Eclipse & Maven that I am not aware of, everything you have with a src/target folder should be in its own Eclipse project. They can then be setup as dependencies of each other (either in Eclipse, Maven, or both).
In the end I followed khmarbaise instructions. (There was a .project file in the root in the repo that needed to be deleted)
After deleting all .classpath, .project and .settings files, I was able to use the import wizard without any issues.
The only other thing I will add is before I primarily used the package explore in eclipse, this will show each of the sub projects as sperate entities. If you go to the Project explorer it will show the root project in the working set you added it to with the sub projects nested underneath.

Find all dependencies and their resolved versions in Gradle

I am looking for a way to display all the dependencies and their resolved versions in a Gradle project. I want the result to be flat.
Gradle has the dependencies task which prints the dependency tree, however, it is not flat and hard to read. For e.g. logback-classic has the following dependency tree.
| | | +--- ch.qos.logback:logback-classic:1.2.3
| | | | +--- ch.qos.logback:logback-core:1.2.3
| | | | \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.30
Instead of this tree structure, I want the result to be following(dependencies with their resolved versions):
ch.qos.logback:logback-classic:1.2.3
ch.qos.logback:logback-core:1.2.3
org.slf4j:slf4j-api:1.7.30
This way it would be easy for me to find out the vulnerable libraries(for e.g. log4j), and it would also give me insights on dependent jars even if I don't directly use them.

Java | Multiple POM files in single project

I'm building an Automation Tool using Java Automation Framework under the hood, to which users will not have access to the main POM.xml file. Sometimes users require to add a custom Java function which requires additional depedencies / repositories. Presently I have to make changes to the main POM file to accommodate the user request. User has access only to "src/test/java/com/script/custom" folder to write custom scripts / functions. I have explored options like Parent/Child POM, Plugin Management, Profile, etc. but examples are mainly for multiple projects. I'm a NodeJs/Angular person, so I'm a beginner at Java.
Project
|
|--src/test/java/com/script/custom
| |
| custom_code.java
| |
| custom_pom.xml
|
--pom.xml
Users should only enter additional dependencies / repos in custom_pom.xml. Parent pom.xml will still hold the main dependencies/repos of the project.
Running code (apart from tests) is against the core concept of Maven as a build tool. There are ways, however, to excute arbitrary code at build time:
Exec Maven Plugin
without an additional plugin (and with cleanly separated projects):
+- project
| +- pom.xml
+- custom
+- src/main/java/com/script/custom
| +- CustomCode.java ... convention for Java class names is CamelCase
+- src/test/java/com/script/custom
| +- CustomCodeTest.java ... instantiates and runs CustomCode
+- pom.xml ... containing <parent><relativePath>../project
For <parent> see Introduction to the POM #Project Inheritance. See also Maven: Lifecycle vs. Phase vs. Plugin vs. Goal for further basics.

Add modules to a maven multi-module project with different relative paths

In the project I am currently working we have different maven projects in different SVN directories, something like this:
(simplified)
...service/rest-api/trunk/project1
...service/common/trunk/project2
...service/common/trunk/parent-aggregator
The last one (parent-aggregator) is a maven pom project that contains the shared dependencies and the multi-module configuration.
So as I am using Eclipse svn (subclipse) client, it allows me to import all those projects into my eclipse workspace, having all the projects in the same directory, therefore the configuration I created can use the relative paths:
parent-aggregator pom.xml:
<modules>
<module>../project1</module>
<module>../project2</module>
</modules>
The issue came when one of my colleagues got the projects using tortoise svn client and then imported the projects to eclipse, tortoise is replicating the svn directory structure in his local file system.
So whenever he tries to do a mvn clean install to the parent-aggregator, it fails due to project1 not being reachable. Which makes sense as in his machine the projects are not in the same directory.
Is there a way to reference modules so both structures can work?
I tried so far to use the artifactId:
<module>artifactId</module>
it doesn't work.
Also tried adding project name, by first defining a:
<name>project1</name>
inside project1 pom.xml
And then referencing it in module:
<module>project1</module>
But it keeps telling me that it cannot find the child module.
The temporary solution that we are using is having different relative path in his local machine:
<modules>
<module>../../../rest-api/trunk/project1</module>
<module>../project2</module>
</modules>
Which I don't like at all as we should have a single approach that we can keep in SVN.
The first thing you should do is to change your structure as well as in SVN..cause if you have multi-module build you express that those modules belong togehter so you should represent in your structure.
+--- root (pom.xml)
+--- mod-rest-api (pom.xml)
+--- mod-war (pom.xml)
+--- mod-p1 (pom.xml)
If you change your project according to the above you only have entries like this:
<modules>
<module>mod-rest-api</module>
<module>mod-war</module>
<module>mod-p1</module>
</modules>
This will simplify your entries and you don't need to have relativePath entries for your parents.
Furthermore you can have the structure in SVN as well:
URL/project/trunk
+--- root (pom.xml)
+--- mod-rest-api (pom.xml)
+--- mod-war (pom.xml)
+--- mod-p1 (pom.xml)
So you have URL/project/tags and URL/project/branches
Having entries in your modules like .. is from my point of view a build smell which indicates something is wrong with your folder structure in relationship to the project architecture.

Categories