application.properties configuration for distributed database pattern - spring-boot

I am trying to develop a microservice by using sprin and spring boot with postgresql database. I am here using distributted datbase. So for particular region I am using one DB, and for other region I am using different DB. Currently I only tried with one database. I added datasource name , username and password in application.properties.
Here my doubt is that, if I am using multiple distributed database, how cam mention different DB source URL in configuration (application.properties)? I am using following structure to use one database currently,
spring.datasource.url=jdbc:postgresql://localhost/milleTech_users
spring.datasource.username=postgres
spring.datasource.password=postgresql
spring.jpa.generate-ddl=true
Like above.
So if I am using multiple DB for multiple region How I can give configuration conditionally here? I am new to microservice world and distributed database design pattern.

Multiple Database details cannot be managed within a single application.properties.
Consider using Spring Cloud Config where in you can create multiple application.properties with different profile names for every application.
In your case, the profile names could reflect the region. When you deploy to a particular region, launch the app with that profile name so that the required config would be loaded and appropriate database connection would be used
Edit :
Also in your case, if you can set environment variables, you can explore on the following option mentioned in this thread

Related

Spring Boot: Handle configuration in multitenant application

I am implementing a Spring Boot application which will be providing a multitenant environment. That is achieved in my case by using a database schema for each customer. Example see this project.
Now I am wondering how to implement tenant-specific configurations. I am using #ConfigurationProperties to bundle my property values, but these are getting instantiated once and not for each tenant.
What if I would like to use Spring Cloud Config with multiple tenant specific git repository as an configuration backend. Would it be possible when using a jdbc backend for Spring Cloud Config?
Is there any way with default Spring mechanisms or do I have to implement a database based configuration framework myself?
Edit: For example I have two tenants called Tenant1 and Tenant2. Both are running over the same application in the same context and are writing in the database schemes tenant_1 and tenant_2.
Identification of tenants is happening over keycloak (see Spring Keycloak multi tenant example). So I identify the tenantId from the jwt token and select the database connection like described here.
But now I would need the same mechanism for #Configuration beans. Since #Configuration beans are as far as I know Singletons, so there is always ONE configuration per application scope, and not ONE configuration per tenant.
So using Spring Cloud Config Tenant1 is using https://git-url/tenant1, Tenant2 is using Hashicorp Vault as backend and perhaps Tenant3 will be using a jdbc based configuration backend. And all of that in ONE (of course scalable) application.
In case your application uses tenant specific files (html templates etc), the following can be applied. As I have used the below approach for handling many tenants and works fine and easy to maintain.
I would suggest that you maintain a consistent configuration source (JDBC) for all of your tenant configurations. This helps you have a single source that is cacheable and scalable for your application. Also, you could have your tenants navigate to a configuration page to manage their settings and alter them to suit their needs at any point of time on the fly. (Example Settings: Records Per Page, Theme, Logo, Filters etc...)
Having the tenant configuration in files in git will be a difficult task when you wanted to auto-provision tenant's when they sign-up as it will involve couple of distributed services. Having them in a TenantSettings table with the tenantId as a column could help you get the data in no time and will be easy.
You can use Spring Cloud Config for your scenario and it is adoptable. It is easily configurable and provides out of the box features. For your specific scenario, you can have any number of microservices running yet all controlled by one Spring Cloud Config Server which is connected to one Git Repository. Your all microservices are asking configuration properties from Spring Cloud Config Server and it is directly fetching properties from Git Repository. That repository can have multiple property files. It can hold common properties for all the microservices or specific service based configuration properties. If you want to keep confidential properties more securely, that is also made possible via HashiCorp vault. I will leave an image below for you to get a better idea about this concept.
In the below image, you can see the Git Repository with common configuration property files and specific configuration property files for different services yet in same repository.
I will add another image for you to get a better idea how does this can be arranged with application profiles as well.
Finally I will add something additional to show the power of Spring Cloud Config and out of the box features it allows us to play with. You can automatically refresh configuration properties in running application as well. You can configure Spring Cloud Config to do that. I will add an architectural diagram to achieve that.
References for this answer is taken from Spring in Action, Fifth Edition
Craig Walls

Handling Global Settings In Microservices

Supposed we had a couple of services service-1,service-2, service-3, we can handle global configurations like DB configs,environment configs etc using an externalized service like spring cloud config server or consul. But what is the best way to handle admin related settings in Micro-services e.g Max funding amount, vat, transaction limit etc setting that don't need a programmer to change ? note multiple services can use these values.
one way of doing this would be creating a bean which loads the data at the start of the app from db. In db you can have a table with admin privileges provide simple insert/update queries to the user who can/wants execute them. This user can be admin of the app who is using your app.
Other way would be creating your own properties/attributes and providing them in application.properties file. You can load those properties any of the beans which you think will need them.
eg (for spring boot):-
spring.max.transaction.limit -- in application.poperties
#Value("${spring.max.transaction.limit}")
private String transactionLimit; -- in the bean

How can I make my flyway default DB pointing to different db and my actual Spring boot Application to some other DB

I am trying to integrate flyway to my existing Spring boot app. My requirement is, the default table created by flyway needs to be created on different DB schema and my applications actual table migration must happen on different schema. Reason being, no addition table must be created on the applications DB schema. Currently we are using Mysql
We had a Spring Boot app with the flyway configuration in application.properties file for different environments:
flyway.enabled=true
flyway.url=jdbc:postgresql://localhost:5432/finance
flyway.schemas=user
flyway.password=password
flyway.user=postgres
flyway.baseline-on-migrate=true
We had the application-dev.properties, application-local.properties and application-aws.properties with the configuration specific to the environment
Flyway provides a property flyway.schemas. When the flyway.schemas property is set (multi-schema mode), the schema history table is placed in the first schema of the list.
https://flywaydb.org/documentation/commandline/migrate.html
ex:flyway.schemas=schema1,schema2,schema3

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).

HSQL Unit Test -- How to Create Multiple In-Memory Schemas?

I would like to use hsql within my DAO unit tests for a web application. The web app is written against mysql and uses three different schemas within the same mysql database. Some schemas has FK relationships with data in the other schemas. If I'm to unit test, I must be able to execute against a database that can hold multiple schemas.
I know that HSQL supports multiple schemas, but I don't know how to configure hsql to have multiple schemas set up for an in-memory database. I read that I can define multiple schemas in the server.properties file, but the file needs to be in the location of where the java class was called -- the junit.jar location? If so, that would be hard to support in my Java Maven application. How can I:
Run an in-memory hsql database to start up with three databases?
Where would I place the server.properties file in my Maven app?
Could I point hsql to use a server.properties file in a location other than where the junit jar is (that's a showstopper for me)?
Is it possible to configure multiple schemas for an in-memory database just via a tricked out jdbc url?
I wish I could untangle the schemas from each other, but that's not possible at this time.
Thanks for your help!
HSQLDB supports multiple schemas in the same database. Foreign keys can reference tables from different schemas. The following apply to the very latest HSQLDB 2.2.6 snapshot available from http://hsqldb.org
Before running your tests, execute CREATE SCHEMA schemaname for each schema.
Doesn't matter where, you can specify the absolute path on the command line arguments when running. See the HSQLD Guide and JavaDoc on server.
Yes.
No. You use the SQL statement to create the schemas.
Note you have two options for running HSQLDB, one is as a server, the other is as an embedded database. In the case of server, it must be started before the test run. In both cases, you need to connect to the database and create the schemas before your tests.
It is possible to create different db by setting db name. By default, it creates the db name as testdb, but in case we want to create multiple db, then set the name explicitly.
new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL).setName("DB_NAME")
.addScript("DDL.SQL")
.addScript("DML.SQL")
.build();
If you run the below line mutiple time, you can see the databases:
DatabaseManagerSwing.main(new String[] { "--url", "jdbc:hsqldb:mem:" + dbnaes, "--user", "sa", "--password", "" });

Resources