Spring Boot use separate user for flywaydb and JPA - spring-boot

flyway.password=pwd2 #does not take effect
flyway.user=user2 #does not take effect
spring.datasource.username=user1
spring.datasource.password=pwd1
user1/pwd1 is used to run flyway db migrations as well as DML operations via JPA. Is there a way to get flyway db to use another credentials?

I got it to work by specifying flyway.url too.

It seems you are mixing the Spring config file with the Flyway config file. Try putting the Flyway config in a flyway.conf file instead of Spring's application.yml config file.
Alternatively, you can use Flyway environment variables like SPRING_FLYWAY_USER and SPRING_FLYWAY_PASSWORD. This is usually a good practice (secured) on cloud environments, as it can be filled from so-called secrets.

Related

How can use an in-memory H2 database when testing my Quarkus application?

I plan to use PostgreSQL as the database for my Quarkus application but I would like the convenience of using H2 in my tests.
Is there a way I can accomplish such a feat?
Quarkus provides the H2DatabaseTestResource which starts an in memory H2 database as part of the test process.
You will need to add io.quarkus:quarkus-test-h2 as a test scoped dependency and annotate your test with #QuarkusTestResource(H2DatabaseTestResource.class).
You will also need to have something like:
quarkus.datasource.url=jdbc:h2:tcp://localhost/mem:test
quarkus.datasource.driver=org.h2.Driver
in src/test/resources/application.properties
In order for the application use PostgreSQL as part of its regular run, quarkus-jdbc-postgresql should be a dependency and
quarkus.datasource.url=jdbc:postgresql://mypostgres:5432
quarkus.datasource.driver=org.postgresql.Driver
should be set in src/main/resources/application.properties
Update
As of version 1.13, Quarkus can launch H2 automatically in dev and test mode when quarkus-jdbc-h2 is on the classpath and no URL configuration is provided.
See this for more information.
You can use the below configurations in the application.properties file to use h2 database
quarkus.datasource.jdbc.url=jdbc:h2:mem:default
quarkus.datasource.driver=org.h2.Driver
quarkus.datasource.username=admin
quarkus.hibernate-orm.database.generation=drop-and-create

Setting up multiple database with Flyway

I am trying to setup two different database with Flyway 5.0.7, MySQL for development and H2 for testing. I have configured both databases in respective files.
For Development, src/main/resource/application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/moment
spring.datasource.username=root
spring.datasource.password=root
flyway.locations=db/migration,db/specific/mysql
For Testing, src/test/resource/application.properties
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
flyway.locations=db/migration,db/specific/h2
Below is the folder structure for Flyway migration files
In this case Flyway is not able to find migration files under specific folder and throws error when applying V1.1__Insert_Records.sql for table not found.
If I move the specific folder inside db/migration, I am getting error for duplicate files of same version.
Any suggestions how should I configure migration files for multiple databases to work with Flyway?
I suspect you might be using Spring Boot 2.x here? If so, flyway.locations is no longer valid and will be ignored.
Flyway will then just use the default location (db/migration), which will find only the V1.1__Insert_Records.sql script but not the V1__Create_table.sql script.
With Spring Boot 2.x, flyway.locations must be prefixed with spring.:
spring.flyway.locations=db/migration,db/specific/h2
By the way, if you use the {vendor} placeholder in the location, Spring Boot will work out the directory from the lowercase of the database driver id (h2, mysql, oracle, etc), which is nice:
spring.flyway.locations=db/migration,db/specific/{vendor}

How to pass database name explicitly in Spring Boot Configuration?

I've a Spring Boot application of mine, which connects to a Postgres database. I've specified in application.properties the datasource url as -
spring.datasource.url=jdbc:postgresql://< server ip here >:5432/mydb
The jdbc url (jdbc:postgresql://< server ip here >:5432/) is actually stored in a separate external location which my application is able to read. Therefore, I want to specify only the database name in my properties file.
I don't want to pass the database name as some environment variable since it's not going to change.
I'm stuck at this point for quite some time now, how can I achieve the same?
Add this in your application.properties file
spring.jpa.hibernate.ddl-auto=create\update\none
spring.datasource.url=jdbc:postgresql://host:port/db
spring.datasource.username=username
spring.datasource.password=password
Have you tried using ${var} syntax like:
spring.datasource.url=jdbc:postgresql://${server-ip}:5432/mydb
See:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-placeholders-in-properties
I finally implemented it this way.
Specified only database name in my application and created Datasource bean in a separate Spring Boot application (so that it can be reused across other projects as well).

How to configure Spring Session Redis redisNamespace at runtime

I'm using Spring Boot 1.3.6 and Spring Session and Redis as the Session store. I need to be able to set the redisNamespace for the application a runtime, and not hard-code it in the code. That means I cannot use #EnableRedisHttpSession since that is not something I can set via the applaction.yml file.
I've updated Spring Session to 1.2.1.RELEASE to get the support I need, but I cannot seem to get the system to configure the namespace via configuration. I tried using a SPEL in the #EnableRedisHttpSession(redisNamespace) call, but that doesn't work. I tried to have the RedisHttpSessionConfiguration injected via Autowired to set it as well, and that seemed to have been ignored. There was also another reference in another SO post about using spring.session.redis.namespace as a property in application.yml but that doesn't work.
Any suggestions/tips would be greatly appreciated!
Declaring spring.redis.namespace per the documentation is not enough.
After setting #EnableRedisHttpSession() to #EnableRedisHttpSession(redisNamespace = "${spring.redis.namespace}") it worked.
Per the normal functionality to externalise configuration you can use system environment variables as well, instead of spring.redis.namespace.
Note: In this case spring.redis.namespace corresponds to the application.yaml file that looks like:
spring:
redis:
namespace: ${REDIS_NAMESPACE:foobar}
I simply put a -Dspring.session.redis.namespace=myKeyName to VM arguments.
and it is working fine.
and I'm using spring boot v1.3.5.RELEASE and spring session 1.2.0.RELEASE.

No plain text passwords in Spring Boot’s application.properties

Having something like
security.user.password = plainTextPassword
inside Spring Boot’s application.properties is obviously an anti-pattern as it prevents the code from being pushed to a public SCM. In my non-Spring Boot projects I use
security.user.password = ${myPasswordFromMavenSettingsXML}
and put a corresponding <properties/> reference inside my pom.xml.
Using Maven’s resource filter plugin the passwords are replaced at build time so the application have access to actual plain text passwords after it has been build and deployed.
For some reason Maven’s resource filter plugin does not work in this case. Is there a way to not commit plain text passwords to an SCM and let Spring Boot to insert them at build time?
Spring boot has multiple mechanisms to provided externalized configuration. Some examples are command line arguments, environment variables and also application properties outside of your packaged JAR.
What I usually do:
Locally we configured several environment variables. Most (if not all) IDE's allow you to configure environment variables from within the run configuration.
For example if you don't want to expose the spring.datasource.password property you could set an environment variable called SPRING_DATASOURCE_PASSWORD.
When we deploy on another environment, we usually choose to add another application.properties or application.yml file within the same folder as the application JAR/WAR, since Spring boot picks that up as well.
Another solution is to use Spring cloud since it has a config service which can be used as a microservice to provide configuration. The configuration can be versioned using SCM as well, but you can put it on a separate system that is not connected to your source code.

Resources