I'm trying to upgrade my Spring Boot 2.3.4 app to use Flyway 7.0.0 (the latest version). Previously it was using Flyway 6.5.6. The relevant entries in build.gradle are shown below.
buildscript {
ext {
flywayVersion = "7.0.0" // changed from 6.5.6
}
}
plugins {
id "org.flywaydb.flyway" version "${flywayVersion}"
}
dependencies {
implementation "org.flywaydb:flyway-core:${flywayVersion}"
}
flyway {
url = "jdbc:postgresql://0.0.0.0:5432/postgres"
user = "postgres"
password = "secret"
}
The following error occurs when I start the app e.g. with ./gradlew bootRun
APPLICATION FAILED TO START
Description:
An attempt was made to call a method that does not exist. The attempt
was made from the following location:
org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer.afterPropertiesSet(FlywayMigrationInitializer.java:65)
The following method did not exist:
'int org.flywaydb.core.Flyway.migrate()'
The method's class, org.flywaydb.core.Flyway, is available from the
following locations:
jar:file:/Users/antonio/.gradle/caches/modules-2/files-2.1/org.flywaydb/flyway-core/7.0.0/623494c303c62080ca1bc5886098ee65d1a5528a/flyway-core-7.0.0.jar!/org/flywaydb/core/Flyway.class
The class hierarchy was loaded from the following locations:
org.flywaydb.core.Flyway: file:/Users/antonio/.gradle/caches/modules-2/files-2.1/org.flywaydb/flyway-core/7.0.0/623494c303c62080ca1bc5886098ee65d1a5528a/flyway-core-7.0.0.jar
Action:
Correct the classpath of your application so that it contains a
single, compatible version of org.flywaydb.core.Flyway
Basically, see Philip's comment on your question.
Flyway 7.x.x is not currently compatible with Spring Boot 2.3.4
Temporary solution is to just downgrade to Flyway 6.5.7 (the last 6.x.x version) until Spring Boot 2.3.5 is released.
Read more and follow the issue here: https://github.com/spring-projects/spring-boot/issues/23514
Support for Flyway's new configuration options: https://github.com/spring-projects/spring-boot/issues/23579
In Flyway 7 the signature of migrate changed.
To get Flyway 7.x.x working with Spring Boot 2.3.x you can provide a custom FlywayMigrationStrategy implementation, which calls the the right migrate method.
import org.flywaydb.core.Flyway;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy;
import org.springframework.stereotype.Component;
#Component
public class FlywayMigrationStrategyImpl implements FlywayMigrationStrategy {
#Override
public void migrate(Flyway flyway) {
flyway.migrate();
}
}
downgrade to Flyway 6.5.7 works.
Related
I have a Kotlin Spring Boot application and tried to integrate the JobRunr Spring Boot Starter dependency, along with the Kotlin JobRunr Support Module. Dependencies:
// Jackson JSON Serialization
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.3")
// Spring Boot Version is 2.7.1 (latest)
// Jobs
implementation("org.jobrunr:jobrunr-spring-boot-starter:5.1.6")
implementation("org.jobrunr:jobrunr-kotlin-1.7-support:5.1.6")
I configured JobRunr like this:
#Configuration
class JobRunrConfiguration {
#Bean
fun jobMapper(): JobMapper {
return JobMapper(JacksonJsonMapper(jacksonObjectMapper()))
}
}
I'm using Postgres as my database.
Application properties are as follows:
# JobRunr
org.jobrunr.background_job_server=true
org.jobrunr.dashboard=true
It is quite basic stuff after following the documentation, but when I try to start the application I get the error:
Failed to bind properties under 'org.jobrunr.background-job-server' to
org.jobrunr.spring.autoconfigure.JobRunrProperties$BackgroundJobServer".
Reason: org.springframework.core.convert.ConverterNotFoundException:
No converter found capable of converting from type [java.lang.String]
to type
[org.jobrunr.spring.autoconfigure.JobRunrProperties$BackgroundJobServer]
I tried different object mappers and configurations, swapping out dependencies, but nothing is working. Anyone have some pointers or ideas in the right direction?
It fails to parse the configuration below:
# JobRunr
org.jobrunr.background_job_server=true
org.jobrunr.dashboard=true
according to the source code the configuration should look like:
org.jobrunr.background-job-server.enabled=true
org.jobrunr.dashboard.enabled=true
I am using spring parent version 2.4.5 and spring mongodb data module 3.1.8 version and this module internally uses 'mongodb-driver-core version 4.1.2' which seems to be the java mongo driver version being used by the dependency. My problem is I am trying to connect to mongo db cluster on my local using the latest spring boot version and my project uses maven but my intelliJ and eclipse(tried in both) shows import com.mongodb.client.MongoClient; as red meaning both the IDEs are not able to detect this class and find it.
Sharing Code snippet (for giving an idea where the error is) that I am using to create the mongotemplate bean
#Bean public MongoClientFactoryBean getMongoFactoryBean(){ return new MongoClientFactoryBean();}
#Bean public MongoTemplate getTemplate(MongoClientFactoryBean factory){ return new MongoTemplate(factory.getObject(), "some database name")}
I get an error in above method while doing a build java cannot access com.mongodb.client.MongoClient class file for com.mongodb.client.MongoClient not found
Any Idea what is going wrong here and any suggestions to solve this issue?
I've built my own starter and the autoconfigure step fails with dependency conflict.
These are the spring boot versions both my starter and upstream project are using
'spring-boot-gradle-plugin', version2.1.8.RELEASE
'spring-boot-autoconfigure', version: '2.4.1'
***************************
APPLICATION FAILED TO START
***************************
Description:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration.lambda$addResourceHandlers$0(W
ebMvcAutoConfiguration.java:411)
The following method did not exist:
'org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration org.springframework.web.servlet.config.annotation.Re
sourceHandlerRegistration.addResourceLocations(org.springframework.core.io.Resource[])'
The method's class, org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration, is available from the following loca
tions:
jar:file:/opt/eureka/app.jar!/BOOT-INF/lib/spring-webmvc-5.3.2.jar!/org/springframework/web/servlet/config/annotation/ResourceHandl
erRegistration.class
The class hierarchy was loaded from the following locations:
org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration: jar:file:/opt/eureka/app.jar!/BOOT-INF/lib/spring-we
bmvc-5.3.2.jar!/
Action:
Correct the classpath of your application so that it contains a single, compatible version of org.springframework.web.servlet.config.an
notation.ResourceHandlerRegistration
From your log I see one of two possible problems:
Somewhere you override spring-webmvc-5.3.2 to a higher or lower version
Problem in your starter code (if it configure your WebMvc)
Try mvn dependency:tree or gradle dependencies to explore dependencies.
Attached your starter code.
I had to use spring boot 2.4.1 to avoid the conflict.
I am using Spring Boot 2.2.2 with Flyway 5.2.4 and I tried to configure flyway to use a differente location for the scripts, but spring.flyway.locations=filesystem:db_other/migration/{vendor} neither flyway.locations=filesystem:db_other/migration/{vendor} configurations on application.properties worked.
When running the program, the following exception appear in the log:
FlywayMigrationScriptMissingException: Cannot find migration scripts in: [classpath:db/migration]
I already tried using Spring Boot 2.2.1, 2.2.0, 2.1.11 and Flyway 6.1.0 and 6.1.3, but the result is the same.
The default value for that property is classpath:db/migration as shown here (search for flyway).
Since you're using a different folder in the resources directory you should only need to change "filesystem" to "classpath" in your application.properties value.
Actually if was my fault: as I used to work with just spring (not spring boot) I configured my test class with the annotations #ExtendWith(SpringExtension.class) AND #ContextConfiguration(classes = { MyConfiguration.class }) instead of just use #SpringBootTest. When making this change the test worked.
I'm trying to display the application version of my Spring Boot application in a view. I'm sure I can access this version information, I just don't know how.
I tried following this information: https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html, and put this in my application.properties:
info.build.version=${version}
And then loading it #Value("${version.test}") in my controller, but that doesn't work, I only get errors like:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'version' in string value "${version}"
Any suggestions on what the proper way to get information like my app version, the spring boot version, etc into my controller?
You can also add this in build.gradle :
springBoot {
buildInfo()
}
Then, you can use BuildProperties bean :
#Autowired
private BuildProperties buildProperties;
And get the version with buildProperties.getVersion()
As described in the reference documentation, you need to instruct Gradle to process you application's resources so that it will replace the ${version} placeholder with the project's version:
processResources {
expand(project.properties)
}
To be safe, you may want to narrow things down so that only application.properties is processed:
processResources {
filesMatching('application.properties') {
expand(project.properties)
}
}
Now, assuming that your property is named info.build.version, it'll be available via #Value:
#Value("${info.build.version}")
I've resolved this by adding into application.yml the following:
${version?:unknown}
It also work from cli:gradle bootRun and also from IntelliJ and you don't have to call the Gradle task processResources before launching in IntelliJ or use spring profiles.
This work with Gradle ver:4.6 and also Spring Boot ver: 2.0.1.RELEASE.
Hope it helps ;)
I have solved it this way:
Define your info.build.version in application.properties:
info.build.version=whatever
use it in your component with
#Value("${info.build.version}")
private String version;
now add your version info to your build.gradle file like this:
version = '0.0.2-SNAPSHOT'
then add a method to replace your application.properties with a regex to update your version information there:
def updateApplicationProperties() {
def configFile = new File('src/main/resources/application.properties')
println "updating version to '${version}' in ${configFile}"
String configContent = configFile.getText('UTF-8')
configContent = configContent.replaceAll(/info\.build\.version=.*/, "info.build.version=${version}")
configFile.write(configContent, 'UTF-8')
}
finally, ensure the method is called when you trigger build or bootRun:
allprojects {
updateVersion()
}
that's it. This solution works if you let Gradle compile your app as well as if you run your Spring Boot app from the IDE. The value will not get updated but won't throw an exception and as soon as you run Gradle it will be updated again.
I hope this helps others as well as it solved the problem for me. I couldn't find a more proper solution so I scripted it by myself.
For Kotlin user, what works for me was :
application.properties
In the application.properties you add a placeholder that will be replace with your value by gradle.
project.version= ${version}
build.gradle.kts
Add a task so gradle will replace the value
tasks.processResources { filesMatching("**/application.properties") { expand(project.properties) } }
Service.kt
Inject the value in your services
#Value("\${project.version}") lateinit var version: String