22

By default, all gradle java projects have a version property. Typically, this looks something like:

allprojects {
    apply plugin: 'java'
    // ...

    // configure the group and version for this project
    group = 'org.example'
    version = '0.2-SNAPSHOT'
}

Is there a way to make the "version" property defined here available to the built java code? What I would like to have is a class like this in the project:

public class BuildVersion {

    public static String getBuildVersion(){
        return // ... what was configured in gradle when project was built
    }

}

I imagine that this could be done through some kind of source code generation. Or by letting gradle write the variable to some sort of config file in src/main/resources. Is there a "standard" (i.e. generally accepted) way to do this in Gradle?

Martin Häusler
  • 6,544
  • 8
  • 39
  • 66

1 Answers1

46

Assuming your Gradle script inserts the version into the jar manifest correctly, as shown here:

version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Gradle Quickstart',
                   'Implementation-Version': version
    }
}

Your code will be able to pick up the version from that jar manifest file:

public class BuildVersion {

    public static String getBuildVersion(){
        return BuildVersion.class.getPackage().getImplementationVersion();
    }

}

Alternatively, write a Gradle task for creating a property file with the version in it, and include that generated property file in the jar file, then access it using getResouceAsStream().

You could of course also generate the BuildVersion.java file from a Gradle task, with the version directly embedded as a string literal, and make sure the task runs before the compile task.

But I'd suggest just using the version number you're going to include already (manifest file), which has full support from both Gradle for writing it and Java Runtime for reading it, without any custom Gradle task or Java file reading.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • 2
    Make sure the package is located in one jar only: https://stackoverflow.com/questions/38204059/how-to-obtain-a-package-version-from-the-jars-manifest-using-the-getimplementa/47442055#47442055 – Tom Nov 22 '17 at 18:59
  • 2
    IntelliJ complains that `version` in `build.gradle` is deprecated, and prefers `project.version`. – toolforger Oct 16 '19 at 05:15
  • 2
    This answer helped me a lot over the years. However, a small word of warning: not all packaging variations will actually include a `MANIFEST.MF` file. In particular in the "serverless" world, or when building distroless containers, the packaging is often different and doesn't necessarily involve building a `*.jar` file in the first place. In such cases, it can be smarter to include a `build.properties` file as a resource instead of using `MANIFEST.MF`. – Martin Häusler Feb 14 '20 at 08:39