Spring flyway configuration: cannot find placeholders when running sql - spring

I am trying to run gradlew flywayMigrate, and the application chrashes when running a recurring migration with the error
Caused by: org.flywaydb.core.api.FlywayException: No value provided for placeholder expressions: ${dbLinkHost}, ${dbLinkPassword}, ${dbLinkSid}, ${dbLinkUser}. Check your configuration!
The variables are configured like this in application.yml:
flyway:
placeholders:
dbLinkHost: ...
dbLinkSid: ...
dbLinkUser: ...
dbLinkPassword: ...
And I try to access them like this in the sql file:
'${dbLinkHost}'
Does anyone know why the declarations in application.yml don`t seem to be accessible here?

As a result of Spring Boot Issue #9896 - Move Flyway configuration properties to spring.flyway and commit f9e3163, starting with v2.0.0.M4, Flyway configuration properties in your application properties start with spring.flyway. To configure Flyway placeholders, for example:
spring:
flyway:
placeholders:
dbLinkHost: ...
dbLinkSid: ...
dbLinkUser: ...
dbLinkPassword: ...
In Spring Boot versions before v2.0.0.M4 such as the recently-released v1.5.14.RELEASE, Flyway configuration properties start with flyway.

Related

Running 'mvn clean install' on Spring Boot application using env variables in application.properties

Hello I am trying to package my Spring Boot app into a jar.
I want to deploy this app to AWS Beanstalk and so I will be injecting some variables into application.properties using Environment variables.
spring.data.mongodb.uri=${MONGODB_URI}
spring.data.mongodb.auto-index-creation=true
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1
CLOUDINARY_URL=${CLOUDINARY_URL}
jwt-secret=${JWT_SECRET}
server.port=5000
However when I run the maven command (mvn clean install), during the package process the code is executed and it is failing stating that
BeanCreationException: Error creating bean with name 'customBeansConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'CLOUDINARY_URL' in value "${CLOUDINARY_URL}"
I have a class CustomBeansConfig:
#Configuration
public class CustomBeansConfig {
#Value("${CLOUDINARY_URL}")
private String cloudinaryUrl;
#Bean
public Cloudinary cloudinary(){
System.out.println("cloudinaryUrl = " + cloudinaryUrl);
return new Cloudinary(cloudinaryUrl);
}
}
Please help me to create the jar file
If I have understood you correctly, one approach may be to use different application.properties files for different environments. For example application-dev.properties for the Dev environment and application-prod.properties for the Prod environment. Then your CLOUDINARY_URL may be assigned different literal values appropriate to each.
Then when deploying to each environment, bundle your JAR with the -Denv option, as in
mvn -Denv=dev clean install
OR
mvn -Denv=prod clean install
... and upload the resulting JAR file to the corresponding AWS environment.
Running the Spring Boot application with a such config property, got me the following error:
Caused by: java.lang.IllegalArgumentException: Circular placeholder reference 'CLOUDINARY_URL' in property definitions
Changing the name of your Spring property from CLOUDINARY_URL to, for example, cloudinary.service.url will resolve the issue.
In such case, your config file should look like this:
spring.data.mongodb.uri=${MONGODB_URI}
spring.data.mongodb.auto-index-creation=true
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1
cloudinary.service.url=${CLOUDINARY_URL}
jwt-secret=${JWT_SECRET}
server.port=5000
And your configuration file like this:
#Configuration
public class CustomBeansConfig {
#Value("${cloudinary.service.url}")
private String cloudinaryUrl;
#Bean
public Cloudinary cloudinary(){
System.out.println("cloudinaryUrl = " + cloudinaryUrl);
return new Cloudinary(cloudinaryUrl);
}
}
Also, I would advise you to avoid creating Spring configuration properties using the underscore format, since it usually used for the environment variables, maybe be confusing and may cause such interesting issues.

spring-boot 2.5.5 property "spring.config.import" not defined?

after upgrade spring-boot:2.3.11.RELEASE to spring-boot:2.5.5 and spring-cloud:Hoxton.SR11 to spring-cloud:2020.0.4, spring-boot:run is failing with:
***************************
APPLICATION FAILED TO START
***************************
Description:
No spring.config.import property has been defined
Action:
Add a spring.config.import=configserver: property to your configuration.
If configuration is not required add spring.config.import=optional:configserver: instead.
To disable this check, set spring.cloud.config.enabled=false or
spring.cloud.config.import-check.enabled=false.
Advices are pretty clear so I added
spring.cloud.config.enabled=false
spring.cloud.config.import-check.enabled=false
spring.config.import=optional:configserver:
to both application.properties and bootstrap.properties files
In application.properties I had to comment out line spring.config.import=optional:configserver: otherwise it failed with java.lang.IllegalStateException: Unable to load config data from 'optional:configserver:' ......... Caused by: java.lang.IllegalStateException: File extension is not known to any PropertySourceLoader
As I didn't need to comment it out in bootstrap.properties, values are ignored completely there probably
However application itself failed the same way as without any new properties added.
Any ideas what is the problem? What is correct format for spring.config.import=... ?
EDIT:
after adding dependency
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
it doesn't ignore properties in bootstrap.properties anymore so I had to comment out "spring.config.import=optional:configserver:" there as well. However application still failing with "No spring.config.import property has been defined"
In Spring Cloud 2020 you dont need bootstrap.properties anymore, importing spring-cloud-starter-bootstrap enable only a legacy way to use it.
Just remove it...
You need to add
spring.config.import=optional:configserver:http://your.config.server.com
into your application.properties. Howerver I not sure what you try to achieve, because of your
spring.cloud.config.enabled=false
More Info

SpringBoot: dinamically set properties in application.yaml

application.yaml containts (for example) the settings:
spring.cloud.stream:
kafka.streams.binder.functions.filter:
applicationId: zk
I want "applicationId" to be set dinamically.
For this aim I tried to use SpEl. But turn out SpEl could not be applicable to apllication.yaml.
I read about 2 ways of dinamically settings of yaml:
Using pom.xml
Using environment variables
But this ways not applicable to my situation: its a gradle-project. All instances of application deployed from one container.
spring.cloud.stream:
kafka.streams.binder.functions.filter:
applicationId: ${zk_prop:zk}
Where zk_prop is the env variable and zk the default value.
To pass arguments while running your application using Gradle Plugin, you need to configure the bootRun task in build.gradle file like:
bootRun {
if (project.hasProperty('args')) {
args project.args.split(',')
}
}
Now, you can pass the command-line arguments as follows:
./gradlew bootRun -Pargs=--zk_prop=custom-zk,--other_props=...

(Spring properties) jdbc-url vs url

I programaticaly configured my DataSource and I'm encountering an error saying:
dataSource or dataSourceClassName or jdbcUrl is required.
I managed to make it work by just changing spring.datasource.url in my .properties file.
Having errors: spring.datasource.url
No errors: spring.datasource.jdbc-url
What I don't know is how does it make it work by just specifying jdbc-url instead of url?
This is how the properties are defined in my project:
spring.datasource.url=jdbc:mysql://localhost:3306/mySchema
spring.datasource.username=theUserName
spring.datasource.password=123456

Spring boot external configuration in standalone jetty

I am building a spring boot application. I want to configure my database properties externally, so anyone can run war file from any machine. How do I configure application.properties externally? I am following this documentation http://docs.spring.io/autorepo/docs/spring-boot/1.0.1.RELEASE/reference/html/boot-features-external-config.html
So I created a app.properties file in jetty's home directory.
spring.datasource.url=jdbc:sqlserver://mymachine:1433;databasename=TESTDB
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.username=someuser
spring.datasource.password=somepass
And trying to run war file through jetty, but it is not detecting application.properties for some reason.
java -jar ../start.jar --spring.config.location=file:///E:/Tools/jetty-distribution-9.3.12.v20160915/demo-base/webapps/app.properties
When I run above command, I get following error in jetty
Caused by:
java.lang.IllegalArgumentException: Property 'driverClassName' must not be empty
at org.springframework.util.Assert.hasText(Assert.java:168)
at org.springframework.jdbc.datasource.DriverManagerDataSource.setDriverClassName(DriverManagerDataSource.java:1
24)
at com.abc.mycompany.sts.config.settings.PersistenceContext.dataSource(PersistenceContext.java:55)
at com.abc.mycompany.sts.config.settings.PersistenceContext$$EnhancerBySpringCGLIB$$368bb66a.CGLIB$dataSource$2
(<generated>)
at com.abc.mycompany.sts.config.settings.PersistenceContext$$EnhancerBySpringCGLIB$$368bb66a$$FastClassBySpring
CGLIB$$25ca0903.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(Configurati
onClassEnhancer.java:356)
at com.abc.mycompany.sts.config.settings.PersistenceContext$$EnhancerBySpringCGLIB$$368bb66a.dataSource(<genera
ted>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy
.java:162)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolv
er.java:588)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(Ab
stractAutowireCapableBeanFactory.java:1128)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutow
ireCapableBeanFactory.java:1022)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCap
ableBeanFactory.java:512)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapab
leBeanFactory.java:482)
This is my jetty's directory structure
E:\Tools\jetty-distribution-9.3.12.v20160915\demo-base\webapps
On command line I am starting jetty by going to demo-base and running command
java -jar ../start.jar --spring.config.location=file:///E:/Tools/jetty-distribution-9.3.12.v20160915/demo-base/webapps/app.properties
The bean looks like below where I am trying to access properties from external application.properties file
#Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty(ConfigConstants.DATABASE_DRIVER_CLASS_NAME));
dataSource.setUrl(env.getProperty(ConfigConstants.DATABASE_URL));
dataSource.setUsername(env.getProperty(ConfigConstants.DATABASE_USERNAME));
dataSource.setPassword(env.getProperty(ConfigConstants.DATABASE_PASSWORD));
return dataSource;
}
This doesn't find my app.properties file. What am I missing?
I see you use env properties to initialize datasource and I would suggest another one solution for you.
Proposition one: it is possible to set properties value on startup like:
java -jar ../start.jar --spring.datasource.url=jdbc:sqlserver://mymachine:1433;databasename=TESTDB --spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver --spring.datasource.username=someuser --spring.datasource.password=somepass
Or if you want mask property names, define your own properties. You have to pack following application.properties file into you jar:
spring.datasource.url=${APP_DB_URL}
spring.datasource.driver-class-name=${APP_DB_DRIVER_CLASS}
spring.datasource.username=${APP_DB_USERNAME}
spring.datasource.password=${APP_DB_PASSWORD}
Next. Before run application set env properties. On *nix platform:
export APP_DB_URL=jdbc:sqlserver://mymachine:1433;databasename=TESTDB
export APP_DB_DRIVER_CLASS=com.microsoft.sqlserver.jdbc.SQLServerDriver
export APP_DB_USERNAME=someuser
export APP_DB_PASSWORD=somepass
On windows platform:
set APP_DB_URL=jdbc:sqlserver://mymachine:1433;databasename=TESTDB
set APP_DB_DRIVER_CLASS=com.microsoft.sqlserver.jdbc.SQLServerDriver
set APP_DB_USERNAME=someuser
set APP_DB_PASSWORD=somepass
And finally, just run your jar without any params:
java ../start.jar
I hope this post could be helpful for you.
Put your application.properties file under JETTY_HOME/resources folder and add
--module=resources
line to start.ini file.
Second one add resources folder to classpath, so every file under that directory will be in the classpath of your webapp.
This should work.
--spring-config-location
is not the correct property name. The property uses dot-notation, not hyphens.
Try:
--spring.config.location
For more information, see section 24.3 in the documentation: http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Additionally, you should point to the directory where the application.properties will be located instead of to the specific file. That may help, but is more useful when you later want to specify profiles. Spring Boot can then select the correct properties file base on profile. For example:
--spring.config.location=file:///E:/jetty/demo-base/webapps/
If you had multiple files in this directory like:
application.properties
application-dev.properties
application-prod.properties
You could add the
--spring.profiles.active=prod
To select the prod properties.
You have too many slashes in the path to the file after "file:" protocol and backslashes should be used too:
--spring.config.location=file:E:\Tools\jetty-distribution-9.3.12.v20160915\demo-base\webapps\app.properties

Resources