Reputation: 4350
I have a webservice coded in kotlin and managed by gradle for the build/dependencies etc...
I want to do a simple thing: When someone call the version
REST endpoint of my webservice, it returns the version.
Since gradle already handle the version with the version
properties in build.gradle
, I thought it would be easy to get this value but it seems it is not... I've been searching google for hours and everything seems so complicated.
Any idea how to handle the version the good way?
Here is what I have right now:
build.gradle
version = "1.0.0"
...
StatusService.kt
class StatusService : IStatusService {
//TODO: Here I would like to get the version from the gradle
//file instead of maintaining 2 places for the version
//Something like Gradle.getProperties("version") for example
override fun getVersion() : String = "1.0.0"
}
I may be completely wrong about this so if you have another equivalent solution, I will accept it too! Thanks
Upvotes: 16
Views: 14754
Reputation: 869
In modern build.gradle.kts it is rather simpler. In the build file all you need is to add a task:
tasks.withType<ProcessResources>() {
doLast {
val propertiesFile = file("$buildDir/resources/main/version.properties")
propertiesFile.parentFile.mkdirs()
val properties = Properties()
properties.setProperty("version", rootProject.version.toString())
propertiesFile.writer().use { properties.store(it, null) }
}
}
Now you have it packed and can use it the way you want, I prefer a helper like:
object Config : LogTag("CONF") {
private val versionProps by lazy {
Properties().also {
it.load(this.javaClass.getResourceAsStream("/version.properties"))
}
}
val version by lazy {
versionProps.getProperty("version") ?: "no version"
}
}
Upvotes: 4
Reputation: 2298
It took some time to figure out how translate the accepted answer to build.gradle.kts
, but this works:
import java.io.FileOutputStream
import java.util.Properties
version = "your-version"
val generatedVersionDir = "$buildDir/generated-version"
sourceSets {
main {
kotlin {
output.dir(generatedVersionDir)
}
}
}
tasks.register("generateVersionProperties") {
doLast {
val propertiesFile = file("$generatedVersionDir/version.properties")
propertiesFile.parentFile.mkdirs()
val properties = Properties()
properties.setProperty("version", "$version")
val out = FileOutputStream(propertiesFile)
properties.store(out, null)
}
}
tasks.named("processResources") {
dependsOn("generateVersionProperties")
}
Upvotes: 6
Reputation: 3518
Consider simple Kotlin Spring Boot example:
@SpringBootApplication
@RestController
class DemoApplication {
@Value("\${version}")
private lateinit var version: String
@GetMapping("/version")
fun version() = version
}
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
Since the property could be taken from application.properties we need to generate that file with required version. To do so we could create a template properties file with following content:
version=###appVersion
Now lets tell Gradle to copy that template to the resource
folder and put the version instead of placeholder
import org.apache.tools.ant.filters.ReplaceTokens
task preprocessProperties(type: Copy) {
from 'src/main/resources/templates'
into 'src/main/resources'
include 'template.properties'
rename 'template.properties', 'application.properties'
filter(ReplaceTokens, beginToken: '###', endToken: '', tokens: [appVersion: '1.0.0'])
}
compileKotlin.dependsOn preprocessProperties
And, voilà, every time you compile Kotlin sources you will get a property file with the version you need.
Upvotes: 1
Reputation: 2945
One approach to this is to output a version file as part of your Gradle build to a location in your classpath that is accessible as a resource within your application.
For example:
You can add this to your build.gradle file which will generate a properties file containing the project version number and add it to your applications source set so that it is available in the classpath.
def generatedVersionDir = "${buildDir}/generated-version"
sourceSets {
main {
output.dir(generatedVersionDir, builtBy: 'generateVersionProperties')
}
}
task generateVersionProperties {
doLast {
def propertiesFile = file "$generatedVersionDir/version.properties"
propertiesFile.parentFile.mkdirs()
def properties = new Properties()
properties.setProperty("version", rootProject.version.toString())
propertiesFile.withWriter { properties.store(it, null) }
}
}
processResources.dependsOn generateVersionProperties
Then in your code you will be able to access it by reading in the properties file:
class StatusService : IStatusService {
private val versionProperties = Properties()
init {
versionProperties.load(this.javaClass.getResourceAsStream("/version.properties"))
}
override fun getVersion() : String = versionProperties.getProperty("version") ?: "no version"
}
Of course you might find it simpler and more appropriate to just output a String to the version file, and then read in the entire file as a String in your code instead of using a properties file.
Upvotes: 11
Reputation: 8386
Gradle is present only at the compilation, not at Runtime.
For doing this, you have to generate a class at the compilation time.
With Android
project, the file BuildConfig.java
is generated but I don't know if it's Gradle or Android.
For generating Kotlin code, you can check KotlinPoet.
Upvotes: 0