use gradle to embed dependency information into manifest
Asked Answered
V

1

8

I would like to embed dependency information into my manifest file, so that I can expose this information at runtime. i.e. I can see which version of a library is used by a particular running instance of my service.

I'm using gradle to build my 'fatjar':

shadowJar {
  mergeServiceFiles()
  archiveName "service.jar"
  exclude "META-INF/*.SF"
  exclude "META-INF/*.DSA"
  exclude "META-INF/*.RSA"
  manifest {
    attributes('Main-Class': "service.Service",
               'Built-By': System.getProperty('user.name'),
               'Built-Date': new Date(),
               'Built-JDK': System.getProperty('java.version'),
               'Implementation-Version': version,
               'Implementation-Title': project.name)
  }
}

And I have dependencies on various other libraries:

dependencies {
  compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.39'
  ...
}

How can I add the dependency information into my manifest file? For example:

Manifest-Version: 1.0
Implementation-Title: service
Implementation-Version: Local Build
Built-By: me
Built-Date: Wed Jun 22 14:13:53 BST 2016
Built-JDK: 1.8.0_91
Main-Class: service.Service
Dependency-mysql-connector-java: mysql:mysql-connector-java:5.1.39
Valentinavalentine answered 22/6, 2016 at 13:17 Comment(0)
V
4

It can be done in the following way:

buildscript {
  repositories {
    maven {
      url 'https://plugins.gradle.org/m2/'
    }
  }

  dependencies {
    classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3'
  }
}

apply plugin: 'java'
apply plugin: 'com.github.johnrengelman.shadow'

repositories {
  mavenCentral()
}

dependencies {
  compile 'com.google.guava:guava:19.0'
  compile 'com.google.inject:guice:4.1.0'
}

shadowJar {
  mergeServiceFiles()
  archiveName "service.jar"
  exclude "META-INF/*.SF"
  exclude "META-INF/*.DSA"
  exclude "META-INF/*.RSA"
  manifest {
    attributes(
               [
               'Main-Class': "service.Service",
               'Built-By': System.getProperty('user.name'),
               'Built-Date': new Date(),
               'Built-JDK': System.getProperty('java.version'),
               'Implementation-Version': 'version',
               'Implementation-Title': project.name,
               ] +
               project.configurations.compile.allDependencies.collect { d ->
                 [
                  ("dependency-${d.group.replaceAll('\\.','-')}".toString()):"$d.group:$d.name:$d.version"
                 ]
               }.sum()
    )
  }
}

The script above produces the following MANIFEST.MF:

Manifest-Version: 1.0
Main-Class: service.Service
Built-By: opal
Built-Date: Mon Jul 04 17:27:05 CEST 2016
Built-JDK: 1.8.0_91
Implementation-Version: version
Implementation-Title: 37969253
dependency-com-google-guava: com.google.guava:guava:19.0
dependency-com-google-inject: com.google.inject:guice:4.1.0

Since attributes takes Map as an argument, you need to collect them dependencies, transform them to Map and sum the maps.

Villiform answered 4/7, 2016 at 15:32 Comment(1)
That's looking great - is there also a way to include dependencies from my sub-modules too? That is, I have a 'core' module and a 'service' module, and my libraries are all in core - they're currently showing as dependency-core: service:Service:Local BuildValentinavalentine

© 2022 - 2024 — McMap. All rights reserved.