Is there a way to list all gradle dependencies programmatically?
Asked Answered
A

6

38

I know that doing:

gradle dependencies

Lists the full dependency tree. Now, I'm looking for a way to manipulate that dependencies tree programmatically so that I can print the same hierarchy but in JSON instead of the format the gradle cli uses right now in the console.

Which are the groovy classes I should use to achieve that?

EDITED

I would like to obtain (in JSON) some like this:

"dependencies" : [
  {
    "groupId" : "com.something",
    "artifactId" : "somethingArtifact",
    "version" : "1.0",
    "dependencies" : [
      "groupId" : "com.leaf",
      "artifactId" : "standaloneArtifact",
      "version" : "2.0",
    ]
  },
  {
    "groupId" : "com.leaf",
    "artifactId" : "anotherStandaloneArtifact",
    "version" : "1.0",
    "dependencies" : []
  }
]

As you can see here with this I know which dependency depends on which other dependencies transitively.

Affenpinscher answered 10/4, 2016 at 23:1 Comment(0)
A
36

Hi all this is how I ended up archiving what I needed and hopefully will be useful for the rest of you.

First off I would like to thanks "pczeus" and "Björn Kautler" for their answers which helped me get to this solution.

So, this is how I solved my problem:

Given this build.gradle:

apply plugin:'java'

repositories {
    jcenter()
}

dependencies {
    compile 'org.javassist:javassist:3.13.0-GA'
    compile 'org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1.1'
    compile 'org.hibernate:hibernate-core:5.1.0.Final'
    compile 'org.springframework:spring-web:4.2.5.RELEASE'
}

If you do:

gradle -b build.gradle dependencies --configuration=compile

You'll get this output in the console:

:dependencies

------------------------------------------------------------
Root project
------------------------------------------------------------

compile - Compile classpath for source set 'main'.
+--- org.javassist:javassist:3.13.0-GA -> 3.20.0-GA
+--- org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1.1
+--- org.hibernate:hibernate-core:5.1.0.Final
|    +--- org.jboss.logging:jboss-logging:3.3.0.Final
|    +--- org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final
|    +--- org.javassist:javassist:3.20.0-GA
|    +--- antlr:antlr:2.7.7
|    +--- org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1.1
|    +--- org.jboss:jandex:2.0.0.Final
|    +--- com.fasterxml:classmate:1.3.0
|    +--- dom4j:dom4j:1.6.1
|    |    \--- xml-apis:xml-apis:1.0.b2
|    \--- org.hibernate.common:hibernate-commons-annotations:5.0.1.Final
|         \--- org.jboss.logging:jboss-logging:3.3.0.Final
\--- org.springframework:spring-web:4.2.5.RELEASE
     +--- org.springframework:spring-aop:4.2.5.RELEASE
     |    +--- aopalliance:aopalliance:1.0
     |    +--- org.springframework:spring-beans:4.2.5.RELEASE
     |    |    \--- org.springframework:spring-core:4.2.5.RELEASE
     |    |         \--- commons-logging:commons-logging:1.2
     |    \--- org.springframework:spring-core:4.2.5.RELEASE (*)
     +--- org.springframework:spring-beans:4.2.5.RELEASE (*)
     +--- org.springframework:spring-context:4.2.5.RELEASE
     |    +--- org.springframework:spring-aop:4.2.5.RELEASE (*)
     |    +--- org.springframework:spring-beans:4.2.5.RELEASE (*)
     |    +--- org.springframework:spring-core:4.2.5.RELEASE (*)
     |    \--- org.springframework:spring-expression:4.2.5.RELEASE
     |         \--- org.springframework:spring-core:4.2.5.RELEASE (*)
     \--- org.springframework:spring-core:4.2.5.RELEASE (*)

(*) - dependencies omitted (listed previously)

What I wanted was to obtained a the same "dependency tree" but in JSON format. So this is the "task" I created for doing that:


task printSolvedDepsTreeInJson {
  doLast {
    def jsonOutput = "["
    configurations.compile.resolvedConfiguration.firstLevelModuleDependencies.each { dep ->
      def addToJson 
      addToJson = { resolvedDep -> 
        jsonOutput += "\n{"
        jsonOutput += "\"groupId\":\"${resolvedDep.module.id.group}\",\"artifactId\":\"${resolvedDep.module.id.name}\",\"version\":\"${resolvedDep.module.id.version}\",\"file\":\"${resolvedDep.getModuleArtifacts()[0].file}\""
        jsonOutput += ",\"dependencies\":["
        if(resolvedDep.children.size()!=0){
          resolvedDep.children.each { childResolvedDep ->
            if(resolvedDep in childResolvedDep.getParents() && childResolvedDep.getConfiguration() == 'compile'){
              addToJson(childResolvedDep)
            }
          }
          if(jsonOutput[-1] == ','){
            jsonOutput = jsonOutput[0..-2]
          }
        }
        jsonOutput += "]},"
      }
      addToJson(dep)
    }
    if(jsonOutput[-1] == ','){
      jsonOutput = jsonOutput[0..-2]
    }
    jsonOutput += "]"
    println jsonOutput
  }
}

If you ran this task:

gradle -b build.gradle printSolvedDepsTreeInJson

You'll get this:

[
  {
    "groupId": "org.apache.geronimo.specs",
    "artifactId": "geronimo-jta_1.1_spec",
    "version": "1.1.1",
    "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1/aabab3165b8ea936b9360abbf448459c0d04a5a4/geronimo-jta_1.1_spec-1.1.1.jar",
    "dependencies": []
  },
  {
    "groupId": "org.hibernate",
    "artifactId": "hibernate-core",
    "version": "5.1.0.Final",
    "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.hibernate/hibernate-core/5.1.0.Final/1b5ac619df76cfd67222ca7cddcee6b0a5db8d0c/hibernate-core-5.1.0.Final.jar",
    "dependencies": [
      {
        "groupId": "org.jboss.logging",
        "artifactId": "jboss-logging",
        "version": "3.3.0.Final",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.jboss.logging/jboss-logging/3.3.0.Final/3616bb87707910296e2c195dc016287080bba5af/jboss-logging-3.3.0.Final.jar",
        "dependencies": []
      },
      {
        "groupId": "org.hibernate.javax.persistence",
        "artifactId": "hibernate-jpa-2.1-api",
        "version": "1.0.0.Final",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.hibernate.javax.persistence/hibernate-jpa-2.1-api/1.0.0.Final/5e731d961297e5a07290bfaf3db1fbc8bbbf405a/hibernate-jpa-2.1-api-1.0.0.Final.jar",
        "dependencies": []
      },
      {
        "groupId": "antlr",
        "artifactId": "antlr",
        "version": "2.7.7",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/antlr/antlr/2.7.7/83cd2cd674a217ade95a4bb83a8a14f351f48bd0/antlr-2.7.7.jar",
        "dependencies": []
      },
      {
        "groupId": "org.apache.geronimo.specs",
        "artifactId": "geronimo-jta_1.1_spec",
        "version": "1.1.1",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1/aabab3165b8ea936b9360abbf448459c0d04a5a4/geronimo-jta_1.1_spec-1.1.1.jar",
        "dependencies": []
      },
      {
        "groupId": "org.jboss",
        "artifactId": "jandex",
        "version": "2.0.0.Final",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.jboss/jandex/2.0.0.Final/3e899258936f94649c777193e1be846387ed54b3/jandex-2.0.0.Final.jar",
        "dependencies": []
      },
      {
        "groupId": "com.fasterxml",
        "artifactId": "classmate",
        "version": "1.3.0",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/com.fasterxml/classmate/1.3.0/183407ff982e9375f1a1c4a51ed0a9307c598fc7/classmate-1.3.0.jar",
        "dependencies": []
      },
      {
        "groupId": "dom4j",
        "artifactId": "dom4j",
        "version": "1.6.1",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/dom4j/dom4j/1.6.1/5d3ccc056b6f056dbf0dddfdf43894b9065a8f94/dom4j-1.6.1.jar",
        "dependencies": [
          {
            "groupId": "xml-apis",
            "artifactId": "xml-apis",
            "version": "1.0.b2",
            "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/xml-apis/xml-apis/1.0.b2/3136ca936f64c9d68529f048c2618bd356bf85c9/xml-apis-1.0.b2.jar",
            "dependencies": []
          }]
      },
      {
        "groupId": "org.hibernate.common",
        "artifactId": "hibernate-commons-annotations",
        "version": "5.0.1.Final",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.hibernate.common/hibernate-commons-annotations/5.0.1.Final/71e1cff3fcb20d3b3af4f3363c3ddb24d33c6879/hibernate-commons-annotations-5.0.1.Final.jar",
        "dependencies": [
          {
            "groupId": "org.jboss.logging",
            "artifactId": "jboss-logging",
            "version": "3.3.0.Final",
            "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.jboss.logging/jboss-logging/3.3.0.Final/3616bb87707910296e2c195dc016287080bba5af/jboss-logging-3.3.0.Final.jar",
            "dependencies": []
          }]
      },
      {
        "groupId": "org.javassist",
        "artifactId": "javassist",
        "version": "3.20.0-GA",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.javassist/javassist/3.20.0-GA/a9cbcdfb7e9f86fbc74d3afae65f2248bfbf82a0/javassist-3.20.0-GA.jar",
        "dependencies": []
      }]
  },
  {
    "groupId": "org.springframework",
    "artifactId": "spring-web",
    "version": "4.2.5.RELEASE",
    "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-web/4.2.5.RELEASE/49cd2430884b77172aa81e3fc33ef668ea1dab30/spring-web-4.2.5.RELEASE.jar",
    "dependencies": [
      {
        "groupId": "org.springframework",
        "artifactId": "spring-aop",
        "version": "4.2.5.RELEASE",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-aop/4.2.5.RELEASE/858d6c70909b3ce7e07b59fc936f8ccfcd81c0aa/spring-aop-4.2.5.RELEASE.jar",
        "dependencies": [
          {
            "groupId": "org.springframework",
            "artifactId": "spring-beans",
            "version": "4.2.5.RELEASE",
            "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-beans/4.2.5.RELEASE/fa992ae40f6fc47117282164e0433b71da385e94/spring-beans-4.2.5.RELEASE.jar",
            "dependencies": [
              {
                "groupId": "org.springframework",
                "artifactId": "spring-core",
                "version": "4.2.5.RELEASE",
                "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/4.2.5.RELEASE/251207b29f0f38f61e3495a2f7fb053cf1bfe8c/spring-core-4.2.5.RELEASE.jar",
                "dependencies": [
                  {
                    "groupId": "commons-logging",
                    "artifactId": "commons-logging",
                    "version": "1.2",
                    "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.2/4bfc12adfe4842bf07b657f0369c4cb522955686/commons-logging-1.2.jar",
                    "dependencies": []
                  }]
              }]
          },
          {
            "groupId": "org.springframework",
            "artifactId": "spring-core",
            "version": "4.2.5.RELEASE",
            "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/4.2.5.RELEASE/251207b29f0f38f61e3495a2f7fb053cf1bfe8c/spring-core-4.2.5.RELEASE.jar",
            "dependencies": [
              {
                "groupId": "commons-logging",
                "artifactId": "commons-logging",
                "version": "1.2",
                "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.2/4bfc12adfe4842bf07b657f0369c4cb522955686/commons-logging-1.2.jar",
                "dependencies": []
              }]
          },
          {
            "groupId": "aopalliance",
            "artifactId": "aopalliance",
            "version": "1.0",
            "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/aopalliance/aopalliance/1.0/235ba8b489512805ac13a8f9ea77a1ca5ebe3e8/aopalliance-1.0.jar",
            "dependencies": []
          }]
      },
      {
        "groupId": "org.springframework",
        "artifactId": "spring-beans",
        "version": "4.2.5.RELEASE",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-beans/4.2.5.RELEASE/fa992ae40f6fc47117282164e0433b71da385e94/spring-beans-4.2.5.RELEASE.jar",
        "dependencies": [
          {
            "groupId": "org.springframework",
            "artifactId": "spring-core",
            "version": "4.2.5.RELEASE",
            "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/4.2.5.RELEASE/251207b29f0f38f61e3495a2f7fb053cf1bfe8c/spring-core-4.2.5.RELEASE.jar",
            "dependencies": [
              {
                "groupId": "commons-logging",
                "artifactId": "commons-logging",
                "version": "1.2",
                "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.2/4bfc12adfe4842bf07b657f0369c4cb522955686/commons-logging-1.2.jar",
                "dependencies": []
              }]
          }]
      },
      {
        "groupId": "org.springframework",
        "artifactId": "spring-context",
        "version": "4.2.5.RELEASE",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-context/4.2.5.RELEASE/a75e18322c7b362fe1daa26a245ae672ec0f3138/spring-context-4.2.5.RELEASE.jar",
        "dependencies": [
          {
            "groupId": "org.springframework",
            "artifactId": "spring-aop",
            "version": "4.2.5.RELEASE",
            "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-aop/4.2.5.RELEASE/858d6c70909b3ce7e07b59fc936f8ccfcd81c0aa/spring-aop-4.2.5.RELEASE.jar",
            "dependencies": [
              {
                "groupId": "org.springframework",
                "artifactId": "spring-beans",
                "version": "4.2.5.RELEASE",
                "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-beans/4.2.5.RELEASE/fa992ae40f6fc47117282164e0433b71da385e94/spring-beans-4.2.5.RELEASE.jar",
                "dependencies": [
                  {
                    "groupId": "org.springframework",
                    "artifactId": "spring-core",
                    "version": "4.2.5.RELEASE",
                    "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/4.2.5.RELEASE/251207b29f0f38f61e3495a2f7fb053cf1bfe8c/spring-core-4.2.5.RELEASE.jar",
                    "dependencies": [
                      {
                        "groupId": "commons-logging",
                        "artifactId": "commons-logging",
                        "version": "1.2",
                        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.2/4bfc12adfe4842bf07b657f0369c4cb522955686/commons-logging-1.2.jar",
                        "dependencies": []
                      }]
                  }]
              },
              {
                "groupId": "org.springframework",
                "artifactId": "spring-core",
                "version": "4.2.5.RELEASE",
                "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/4.2.5.RELEASE/251207b29f0f38f61e3495a2f7fb053cf1bfe8c/spring-core-4.2.5.RELEASE.jar",
                "dependencies": [
                  {
                    "groupId": "commons-logging",
                    "artifactId": "commons-logging",
                    "version": "1.2",
                    "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.2/4bfc12adfe4842bf07b657f0369c4cb522955686/commons-logging-1.2.jar",
                    "dependencies": []
                  }]
              },
              {
                "groupId": "aopalliance",
                "artifactId": "aopalliance",
                "version": "1.0",
                "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/aopalliance/aopalliance/1.0/235ba8b489512805ac13a8f9ea77a1ca5ebe3e8/aopalliance-1.0.jar",
                "dependencies": []
              }]
          },
          {
            "groupId": "org.springframework",
            "artifactId": "spring-beans",
            "version": "4.2.5.RELEASE",
            "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-beans/4.2.5.RELEASE/fa992ae40f6fc47117282164e0433b71da385e94/spring-beans-4.2.5.RELEASE.jar",
            "dependencies": [
              {
                "groupId": "org.springframework",
                "artifactId": "spring-core",
                "version": "4.2.5.RELEASE",
                "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/4.2.5.RELEASE/251207b29f0f38f61e3495a2f7fb053cf1bfe8c/spring-core-4.2.5.RELEASE.jar",
                "dependencies": [
                  {
                    "groupId": "commons-logging",
                    "artifactId": "commons-logging",
                    "version": "1.2",
                    "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.2/4bfc12adfe4842bf07b657f0369c4cb522955686/commons-logging-1.2.jar",
                    "dependencies": []
                  }]
              }]
          },
          {
            "groupId": "org.springframework",
            "artifactId": "spring-core",
            "version": "4.2.5.RELEASE",
            "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/4.2.5.RELEASE/251207b29f0f38f61e3495a2f7fb053cf1bfe8c/spring-core-4.2.5.RELEASE.jar",
            "dependencies": [
              {
                "groupId": "commons-logging",
                "artifactId": "commons-logging",
                "version": "1.2",
                "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.2/4bfc12adfe4842bf07b657f0369c4cb522955686/commons-logging-1.2.jar",
                "dependencies": []
              }]
          },
          {
            "groupId": "org.springframework",
            "artifactId": "spring-expression",
            "version": "4.2.5.RELEASE",
            "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-expression/4.2.5.RELEASE/a42bdfb833d0be6c18429aea3fb0fba81f85c6e8/spring-expression-4.2.5.RELEASE.jar",
            "dependencies": [
              {
                "groupId": "org.springframework",
                "artifactId": "spring-core",
                "version": "4.2.5.RELEASE",
                "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/4.2.5.RELEASE/251207b29f0f38f61e3495a2f7fb053cf1bfe8c/spring-core-4.2.5.RELEASE.jar",
                "dependencies": [
                  {
                    "groupId": "commons-logging",
                    "artifactId": "commons-logging",
                    "version": "1.2",
                    "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.2/4bfc12adfe4842bf07b657f0369c4cb522955686/commons-logging-1.2.jar",
                    "dependencies": []
                  }]
              }]
          }]
      },
      {
        "groupId": "org.springframework",
        "artifactId": "spring-core",
        "version": "4.2.5.RELEASE",
        "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/4.2.5.RELEASE/251207b29f0f38f61e3495a2f7fb053cf1bfe8c/spring-core-4.2.5.RELEASE.jar",
        "dependencies": [
          {
            "groupId": "commons-logging",
            "artifactId": "commons-logging",
            "version": "1.2",
            "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.2/4bfc12adfe4842bf07b657f0369c4cb522955686/commons-logging-1.2.jar",
            "dependencies": []
          }]
      }]
  }, 
  {
    "groupId": "org.javassist",
    "artifactId": "javassist",
    "version": "3.20.0-GA",
    "file": "/Users/cgadam/.gradle/caches/modules-2/files-2.1/org.javassist/javassist/3.20.0-GA/a9cbcdfb7e9f86fbc74d3afae65f2248bfbf82a0/javassist-3.20.0-GA.jar",
    "dependencies": []
  }
]

Which is the JSON representation of the dependency tree I needed. Now, if you look closer you'll notice that this is not the actual list of dependencies we defined in the build.gradle. This is the RESOLVED dependency tree. This means that some dependencies have changed.

For example the firstLevel dependency:

org.javassist:javassist:3.13.0-GA

Has been changed for:

org.javassist:javassist:3.20.0-GA

As

org.hibernate:hibernate-core:5.1.0.Final

depends on:

org.javassist:javassist:3.20.0-GA

which is a higher version than:

org.javassist:javassist:3.13.0-GA

And Gradle by-default conflict resolution algorithm chooses always the "latest" version.

Actually this is what:

+--- org.javassist:javassist:3.13.0-GA -> 3.20.0-GA

Means in the console output. 3.13.0-GA was override by 3.20.0-GA version.

Now, this is a problem because I'm not getting the actual "dependency tree". I'm getting the "resolved" one.

I ended up fixing this situation by defining another TASK:

task printDepsTreeInJson {
  doLast {
    configurations.compile.incoming.getResolutionResult().getAllDependencies().each { depResult  ->
      println "{\"from\":\"" + depResult.getFrom() + "\"," + "\"requested\":\"" + depResult.getRequested() + "\"}"
    }
  }
}

If you execute this:

gradle -b build.gradle printDepsTreeInJson

You'll now get this:

:printDepsTreeInJson
{"from":"project :","requested":"org.javassist:javassist:3.13.0-GA"}
{"from":"project :","requested":"org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1.1"}
{"from":"project :","requested":"org.hibernate:hibernate-core:5.1.0.Final"}
{"from":"org.hibernate:hibernate-core:5.1.0.Final","requested":"org.jboss.logging:jboss-logging:3.3.0.Final"}
{"from":"org.hibernate:hibernate-core:5.1.0.Final","requested":"org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final"}
{"from":"org.hibernate:hibernate-core:5.1.0.Final","requested":"org.javassist:javassist:3.20.0-GA"}
{"from":"org.hibernate:hibernate-core:5.1.0.Final","requested":"antlr:antlr:2.7.7"}
{"from":"org.hibernate:hibernate-core:5.1.0.Final","requested":"org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1.1"}
{"from":"org.hibernate:hibernate-core:5.1.0.Final","requested":"org.jboss:jandex:2.0.0.Final"}
{"from":"org.hibernate:hibernate-core:5.1.0.Final","requested":"com.fasterxml:classmate:1.3.0"}
{"from":"org.hibernate:hibernate-core:5.1.0.Final","requested":"dom4j:dom4j:1.6.1"}
{"from":"dom4j:dom4j:1.6.1","requested":"xml-apis:xml-apis:1.0.b2"}
{"from":"org.hibernate:hibernate-core:5.1.0.Final","requested":"org.hibernate.common:hibernate-commons-annotations:5.0.1.Final"}
{"from":"org.hibernate.common:hibernate-commons-annotations:5.0.1.Final","requested":"org.jboss.logging:jboss-logging:3.3.0.Final"}
{"from":"project :","requested":"org.springframework:spring-web:4.2.5.RELEASE"}
{"from":"org.springframework:spring-web:4.2.5.RELEASE","requested":"org.springframework:spring-aop:4.2.5.RELEASE"}
{"from":"org.springframework:spring-aop:4.2.5.RELEASE","requested":"aopalliance:aopalliance:1.0"}
{"from":"org.springframework:spring-aop:4.2.5.RELEASE","requested":"org.springframework:spring-beans:4.2.5.RELEASE"}
{"from":"org.springframework:spring-beans:4.2.5.RELEASE","requested":"org.springframework:spring-core:4.2.5.RELEASE"}
{"from":"org.springframework:spring-core:4.2.5.RELEASE","requested":"commons-logging:commons-logging:1.2"}
{"from":"org.springframework:spring-aop:4.2.5.RELEASE","requested":"org.springframework:spring-core:4.2.5.RELEASE"}
{"from":"org.springframework:spring-web:4.2.5.RELEASE","requested":"org.springframework:spring-beans:4.2.5.RELEASE"}
{"from":"org.springframework:spring-web:4.2.5.RELEASE","requested":"org.springframework:spring-context:4.2.5.RELEASE"}
{"from":"org.springframework:spring-context:4.2.5.RELEASE","requested":"org.springframework:spring-aop:4.2.5.RELEASE"}
{"from":"org.springframework:spring-context:4.2.5.RELEASE","requested":"org.springframework:spring-beans:4.2.5.RELEASE"}
{"from":"org.springframework:spring-context:4.2.5.RELEASE","requested":"org.springframework:spring-core:4.2.5.RELEASE"}
{"from":"org.springframework:spring-context:4.2.5.RELEASE","requested":"org.springframework:spring-expression:4.2.5.RELEASE"}
{"from":"org.springframework:spring-expression:4.2.5.RELEASE","requested":"org.springframework:spring-core:4.2.5.RELEASE"}
{"from":"org.springframework:spring-web:4.2.5.RELEASE","requested":"org.springframework:spring-core:4.2.5.RELEASE"}

This is not the final "dependency tree" (I ended up constructing it using javascript) but it's what you actually need to generate it!

The "from" is the dependency that requested another dependency and the "requested" is the actual dependency being requested! :)

If

"from":"project :"

That means that the dependency is a "first level" dependency. (A root)

All other dependencies will be like this:

{"from":"org.hibernate:hibernate-core:5.1.0.Final","requested":"org.jboss.logging:jboss-logging:3.3.0.Final"}

Notice that I do have now the two

org.javassist:javassist

Each one associated to the dependency that actually requested it. One is a "first level" dependency:

{"from":"project :","requested":"org.javassist:javassist:3.13.0-GA"}

and the other one was requested by hibernate:

{"from":"org.hibernate:hibernate-core:5.1.0.Final","requested":"org.javassist:javassist:3.20.0-GA"}

I was too lazy to generate the dependency tree in JSON in the same task :) But, it's clear that this is the way to go if you, for some reason, need to parse the "original"(former/not solved) dependency tree.

This is the content of the final build.gradle file in case you want to copy&paste and try it out:

apply plugin:'java'

repositories {
    jcenter()
}

dependencies {
    compile 'org.javassist:javassist:3.13.0-GA'
    compile 'org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1.1'
    compile 'org.hibernate:hibernate-core:5.1.0.Final'
    compile 'org.springframework:spring-web:4.2.5.RELEASE'
}

task printDepsTreeInJson {
  doLast {
    configurations.compile.incoming.getResolutionResult().getAllDependencies().each { depResult  ->
      println "{\"from\":\"" + depResult.getFrom() + "\"," + "\"requested\":\"" + depResult.getRequested() + "\"}"
    }
  }
}

task printSolvedDepsTreeInJson {
  doLast {
    def jsonOutput = "["
    configurations.compile.resolvedConfiguration.firstLevelModuleDependencies.each { dep ->
      def addToJson 
      addToJson = { resolvedDep -> 
        jsonOutput += "\n{"
        jsonOutput += "\"groupId\":\"${resolvedDep.module.id.group}\",\"artifactId\":\"${resolvedDep.module.id.name}\",\"version\":\"${resolvedDep.module.id.version}\",\"file\":\"${resolvedDep.getModuleArtifacts()[0].file}\""
        jsonOutput += ",\"dependencies\":["
        if(resolvedDep.children.size()!=0){
          resolvedDep.children.each { childResolvedDep ->
            if(resolvedDep in childResolvedDep.getParents() && childResolvedDep.getConfiguration() == 'compile'){
              addToJson(childResolvedDep)
            }
          }
          if(jsonOutput[-1] == ','){
            jsonOutput = jsonOutput[0..-2]
          }
        }
        jsonOutput += "]},"
      }
      addToJson(dep)
    }
    if(jsonOutput[-1] == ','){
      jsonOutput = jsonOutput[0..-2]
    }
    jsonOutput += "]"
    println jsonOutput
  }
}
Affenpinscher answered 14/4, 2016 at 14:45 Comment(1)
this is not working anymore with new gradle versions I'm using 7.3.3 @Affenpinscher is there any update available for thisWalley
O
22

You could create a task within your Gradle file to iterate over all dependencies and generate the JSON as you see fit. Here is an example task that will pretty print the JSON for you:

task printDependencies << {
    def json = '"dependencies": ['

    configurations.runtime.resolvedConfiguration.resolvedArtifacts.each { artifact ->
        def id = artifact.moduleVersion.id
       // println "group: ${id.group}, name: ${id.name}, version: ${id.version}"
        json += JsonOutput.toJson(id)
    }

    json += "]"
    json = JsonOutput.prettyPrint(json)
    println json
}

With sample output:

"dependencies": [
    {
        "group": "com.fasterxml.jackson.core",
        "version": "2.6.5",
        "name": "jackson-core",
        "module": {
            "group": "com.fasterxml.jackson.core",
            "name": "jackson-core"
        }
    }{
        "group": "org.springframework",
        "version": "4.2.5.RELEASE",
        "name": "spring-aop",
        "module": {
            "group": "org.springframework",
            "name": "spring-aop"
        }
    }
]
Oder answered 11/4, 2016 at 0:35 Comment(7)
I updated the answer to show a nice example of printing all resolved dependencies in a JSON format.Oder
pczeus thank you very much for such detailed answer! I would need however, to know the dependencies of those dependencies so that I can manipulate the tree (which is the thing I'm interested in). Please see the question again. I've edited it to better describe what's the expected result I'm trying to obtain. Thanks once again!Affenpinscher
No problem. If you look at the Groovy docs for Configuration You can see the api tor even get allDependencies for all configurations. In addition, the resolvedConfiguration has an API to get First level dependencies and all children. So, you should be able to adjust the task to navigate the tree as desired.'Oder
By the way. The example I am showing is the 'flattened' out dependency tree that shows ALL dependencies, without the need to navigate the tree. If you want to nest child dependencies in JSON then my previous comment should help point you in the right direction.Oder
pczeus, that's even much straight forward than having to create my own reporter I guess. The API you pointed out has the getChildren() method :)Affenpinscher
I tried this. but got an error: "Could not get unknown property 'JsonOutput' for task". Any idea?Moir
It's groovy.json.JsonOutput @JianwuChenTatyanatau
E
9

The easiest would probably be to write your own DependencyReportRenderer implementation and then either configure the existing dependencies task to use it, or define a new task of type DependencyReportTask with your own renderer configured.

Epa answered 10/4, 2016 at 23:18 Comment(5)
Thank you! I'll take a look at the class you've described. Do you know of any good IDE to actually debug Gradle scripts?Affenpinscher
How do you configure a task to use a specific Render?Affenpinscher
I use IntelliJ IDEA. It is the best Java IDE under the sun and it is also excellent in writing and debugging Gradle scripts. Well, something like task jsonDeps(type: DependencyReportTask) { renderer new MyOwnRenderer() }. But that is right out of my mind, didn't try that yet.Epa
Any chance you can expand on this?Heidi
In what extend? Actually I'm on a US road trip without computer at hands, so I can probably not expand much, but what would you need besides actual implementation? I think you should have all info you need.Epa
A
0

I actually found the method mentioned here to be more straight-forward and use the JSON (embedded into a root.js file) that's already being generated as part of the project-report plugin's htmlDependencyReport task.

Agosto answered 6/9, 2022 at 9:48 Comment(0)
S
0

Someone has written a plugin to do just this: https://github.com/Azim/AzimDP

Add the azimdp plugin like so:

plugins {
    id 'java-library'
    id 'maven-publish'
    id 'war'
    id "com.github.Azim.azimdp" version "1.0.0"
}

Run the provided task:

gradle generate-dependency-list

See output in /build/AzimDP/AzimDP.json

Uses 'The Unlicense' so free for commercial use. It could do with this documenting in the readme.

Saum answered 27/2, 2023 at 16:5 Comment(0)
D
0

There's actually a standardized format for reporting dependencies -- SBOM, and a Gradle plugin to produce this format.

See cyclonedx-gradle-plugin.

It produces a bom.json and a bom.xml file in build/reports/.

There are also libraries for processing these files as well as lots of other tools. See here.

Daylong answered 5/4 at 15:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.