Inject Gradle properties into Spring Boot application.yml, not working in IntelliJ IDEA - spring-boot

I've managed to inject the Gradle proj.ver into application.yml and after that injected it into service application.
My application.yml looks like this:
project:
version: ${version}
But it works only if I started the app from cli with:
gradle bootRun
If I'm trying to start the app from IntelliJ, it didn't work and it failed with:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'version' in value "${version}"
I read all the answers from Stackoverflow and they suggested two solutions:
Use spring profiles
Modify run configuration and run before launch the gradle task: processResources
I'd prefer something like a default value for proj.ver when I'm running from IntelliJ. Is that possible? Or are any better solutions for this situation ?
Thanks

As M. Deinum said above in the comment, I managed to run the app from IntelliJ, but now the gradle bootRun started to fail with:
Caused by: groovy.lang.MissingPropertyException: No such property: unknown for class: SimpleTemplateScript2
After some more research it seems that ${version?:unknown}(with the question mark) it works either from the IDE or from cli.
I've updated the response, in order for others to know how to inject Gradle build info into Spring-boot:
1) Tell Gradle to pass the build data towards a Spring yml file like this:
processResources {
filesMatching('appInfo.yml') {
expand(project.properties)
}}
2) The appInfo.yml will look like:
project:
version: ${version?:unknown}
3) Inject the version of the build into Spring services like:
#Value("${project.version}")
private String applicationVersion;

Just to complete for Kotlin user, what works for me was :
build.gradle.kts
tasks.processResources { filesMatching("**/application.properties") { expand(project.properties) } }
application.properties
project.version= ${version}
Service.kt
#Value("\${project.version}") lateinit var version: String

Related

Changing Spring Boot application version through gradle.properties while using Spring Boot gradle-plugin

I'm using the Spring boot gradle plugin and have put this in my application.yml:
spring:
application:
name: myapp
version: ${version}
I process the resource file for tokens using:
processResources {
filesMatching('application.yml') {
expand(project.properties)
}
}
And I use this annotation in my controller:
public class MyController {
#Value("${spring.application.version}")
private String appversion
...
And it all works, yay! The problem is that I can't figure out what is actually controlling the version because this reports version 0.0.1-SNAPSHOT even though I specify a different version in gradle.properties.
I tried updating the springBoot DSL thusly:
springBoot {
buildInfo {
properties {
version = "${project.version}"
}
}
}
But it has no effect. Could someone help me understand the proper way to increment/manage the version using the Spring Boot gradle plugin?
As said in my comment, the way you have set the version in gradle.properties and how you configured the application.yml is correct.
I guess you still have a version property defined in your main build.gradle, which overrides the value set in the gradle.properties with value 0.0.1-SNAPSHOT

Spring-boot and spring boot dev tools integration not showing the updated class changes

I am trying to follow this example to do spring boot and spring boot dev tools integration to do automatic restart. The classes in the build folder are getting updated when i run build --continuous task but the application still talks to the old classes. In the example the bootRun task is as below. My project has its custom task for running the application. Right now with build -continuous when I make a change the application it is rebuilding the classes but the running application is not showing the changes. How to change my custom h2Run task so that it loads the changed classes? Thank you.
The boot run task in the example
bootRun {
classpath = sourceSets.main.runtimeClasspath + configurations.dev
}
My custom task for bootRun
class Run extends JavaExec {
Run() {
group "application"
dependsOn project.tasks.classes, project.tasks.pathingJar
classpath = project.files("$project.buildDir/classes/main", "$project.buildDir/resources/main", project.tasks.pathingJar.archivePath)
main = "com.mycompany.Application"
}
}
task h2Run(type: Run) {
classpath = sourceSets.main.runtimeClasspath + configurations.dev // this is not working
description "Start $appName using H2 database"
args "--spring.profiles.active=dev"
mustRunAfter 'cleanH2'
dependsOn copyContentTypeLibraries
}
I walked through the DZone article you linked to. I didn't add your custom Run class or task, I just grabbed the bootRun task right out of the article. Even without any of your custom code, I initially experienced the same behavior you do.
The article states:
At the first terminal, start Gradle build as a continuous task:
gradle build --continuous
At the second terminal, start the Gradle bootRun task: gradle
bootRun
If I do these things, in this order, I also see my classes recompile, but the servlet container doesn't pick the changes up. Just like you describe.
However, if I do gradle bootRun first, and gradle build --continuous second, after the application is running, the application restarts as expected whenever I edit a java file.
Have you tried executing the commands in the two terminal windows in reverse order?

Using Gradle property expansion in kotlin/spring boot

I am currently building a Kotlin, Spring Boot service using gradle as the build tool. I am attempting to automatically expand properties found in my application.properties file, using the steps found here:
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html#howto-automatic-expansion-gradle
My versions are as follows:
- kotlin: 1.1.4-3
- spring boot: 1.5.6.RELEASE
- gradle: 3.5.1
When I run a ./gradlew bootRun, I get the following error:
java.lang.IllegalArgumentException: Could not resolve placeholder 'myServiceName' in value "${myServiceName}"
Followed by:
java.lang.IllegalStateException: LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#510aeb93: startup date [Fri Sep 15 10:59:51 AEST 2017]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext#68edf5bb
build.gradle:
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'org.springframework.boot'
processResources {
filesMatching('application.properties') {
expand(project.properties)
}
}
gradle.properties:
myServiceName=potato-service
application.properties:
info.app.name=${myServiceName}
These errors appear after the app has started, and spring is trying to load the property file.
The interesting thing is that if I change the variable that I am trying to substitute in the application.properties, to myServiceName123 for example, gradle fails at the processResources stage.
So, there was a small part of my build.gradle that I did not include above as I did not know about it:
bootRun {
addResources = true
}
According to the Spring Boot Docs having the addResources flag set to true will ignore the application.properties file created in the processResources step, and instead use the one in your projects sources. This is to allow you to dynamically change the file without needing to restart the application.
The correct fix for this (if you need variable expansion when running with the bootRun task) is to set:
bootRun {
addResources = false
}
Otherwise, if you just need expansion when building your jar, leaving this flag as true should be fine.

gradle bootRun > Use test classpath

The problem I was having, was that I wanted to include test classpath resources in SpringBoot's bootRun gradle task. Why? So that I could use a test profile with test resources, to mock integration points.
What I tried:
The spring boot documentation only offers the addResources = true option (I tried using customConfiguration as per the similar bootRepackage configuration, to no avail)
No additional options are visible by looking at the BootRunTask source code
The equivalent maven plugin has a plethora of options, including useTestClasspath (which isn't mirrored in the gradle version)
I came across the following solution, which solved this issue for me.
Basically, the BootRunTask extends the standard JavaExec task, which offers a classpath option. So, you can add the test classpath resources by using the following gradle configuration:
bootRun {
classpath = sourceSets.test.runtimeClasspath
}

How do I run FlyWay clean with Spring Boot?

I'm using Spring Boot and FlyWay together. I added the FlyWay dependency to my Gradle build file like this:
dependencies {
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.postgresql:postgresql:9.4-1202-jdbc42")
compile("org.flywaydb:flyway-core")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
I also added a db/migrations folder with an initial migration file. The migration works as expected. But now I want to clean by using the gradle flywayClean task. However, when I run this, I get an error saying the task can't be found. Is there another way I'm supposed to do this with Spring Boot?
To run gradle flywayClean, you have to apply the plugin: 'org.flywaydb.flyway'
See http://flywaydb.org/getstarted/firststeps/gradle.html

Resources