Spring Boot application.yml set datasource property globally, being ignored - java

I have a Spring Boot 1.5 app which is configured with an application.yml file.
I need to manage the connection pool which is default - Tomcat.
The problem is that the application.yml has a datasources property for several datasources.
My global datasource.max-active=10 (UPDATE: datasource.tomcat.max-active=10 is ignored too) is being completely ignored (I created a test to see what datasource is being injected, and default maxActive in them is set to 100). I have to add it to every datasource separately to make the pool work the way I need it to.
The application.yml looks like this (this is only part of it), and it creates datasource with maxActive=10, but there is bunch of repetitions:
spring:
.... #bunch of stuff, deleted for simplicity
datasource: #Added by me, ignored by Spring
max-active: 10 #Added by me, ignored by Spring
datasources:
datasource1:
url: jdbc:mysql://url:port1
max-active: 10 #Added by me, works
datasource2:
url: jdbc:mysql://url:port2
max-active: 10 #Added by me, works
Question: what is the correct way to set the max-active property globally to avoid this repetition?
Thanks.

When you are using multiple data sources, spring boot does not provide a default data source auto-configuration. This also means you have to provide connection pool properties for each data source. I don't think it's possible to set it globally.
Instead, you can use the placeholder to set it once and use it everywhere.
custom:
max-active: 10
spring:
datasources:
datasource1:
url: jdbc:mysql://url:port1
max-active: ${custom.max-active}
datasource2:
url: jdbc:mysql://url:port2
max-active: ${custom.max-active}
You can find more info here: How to setup multiple connection pools when multiple datasources are used in Spring Boot?

Related

Spring Boot: how to disable (or remove) property in application.properties using externalized configuration

I'm working on a Spring Boot project (v2.3.x) connected to a MongoDB instance.
The connection is configured using the property spring.data.mongodb.uri.
Now, for local development I'd like to configure the connection using host/port, i.e. using these properties (I'm configuring these via ENV VARs):
spring.data.mongodb.host
spring.data.mongodb.port
Adding these properties, while leaving spring.data.mongodb.uri, obviously results in an error on application run:
java.lang.IllegalStateException: Invalid mongo configuration, either uri or host/port/credentials/replicaSet must be specified
So I'm wondering if there is a way to disable the spring.data.mongodb.uri configuration using properties override (externalized configuraion) provided by Spring Boot.
Is this possible? I tried setting spring.data.mongodb.uri=null but the startup error remains.
How can I achieve this without directly modifying the application.properties file?
NOTE: I also considered using profiles, but also using this feature I cannot find a way to override the "main" configuration.
You could use "application-default.properties" file and put spring.data.mongodb.uri in there. The "default" Spring profile will be active when no other profiles are selected. So you can start locally with any profile ("dev" or whatever) and "application-default.properties" file will not be loaded.
Of course, keep in mind that adding any profile in production would also disable spring.data.mongodb.uri in this case.

Can't Discovery-Locate Config Upon Transition to Spring 2.4

Versions
Spring Parent: 2.7.4, Spring Cloud Version: 2021.0.4, Java Version: 11
Issue
My Spring service has been using Eureka to connect to the config server for a long time, but I want to upgrade to Spring 2.7.4. I understand that as of Spring 2.4, the bootstrap context has been deprecated (source) and I need to make some adjustments to the old bootstrap properties and move them over to application.properties.
The documentation for Spring Cloud specifies that in order for me to continue to use discovery-first config lookup, I need to define a spring.config.import property with an optional configserver entry (source). Since I'm also using Vault, I define the property as follows:
spring.config.import = optional:configserver:placeholder,vault://<my-generic-backend>/dev
Next, I need to define the following properties (source). These properties were already defined in my old bootstrap.properties, so all I need to do is copy and paste.
spring.cloud.config.discovery.enabled = true
spring.cloud.config.discovery.serviceId = config-server
eureka.client.serviceUrl.defaultZone = <my-eureka-url>
Unless I'm missing something, these are all the steps I need to take in order to upgrade to 2.7.4. However, when I run the Spring service, it complains that it can't find the config server (via Eureka, or via URL), then it registers successfully with Eureka, and then continues trying and failing to find the config server.
Here is some of the output of the program:
> Running with Spring Boot v2.7.4, Spring v5.3.23
> Could not locate configserver via discovery: No instances found of configserver (config-server)
> Could not locate PropertySource ([ConfigServerConfigDataResource#2aa6311a uris = array<String>['placeholder'], optional = true, profiles = list['local']]): Invalid URL: placeholder
...
> DiscoveryClient_<my-project-name>/local - registration status: 204
I understand why it's failing to find a config server at URL: placeholder since that's not a valid URL, but I don't understand how the service can successfully register with Eureka yet not be able to find the config server. I know the service is registered because the output of the program says it registered correctly (and I can see it in the registry), and I know that the config server has the correct entity ID (config-server) because it was copied and pasted from the old bootstrap (and I can see config-server in the registry).
Workaround with Hardcoded URL
When I hardcode the config server URL like this (and set spring.cloud.config.discovery.enabled to false), the config is loaded properly from the server:
spring.config.import=configserver:https://<my-hardcoded-config-url>.com,vault://<my-generic-backend>/dev
Workaround with Bootstrap
It's possible to return to using the bootstrap context and still use Spring 2.7.4 with discovery-first config lookup by adding the "spring-cloud-starter-bootstrap" dependency. So I added the dependency to my POM and moved these properties back to bootstrap.properties from application.properties.
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=config-server
I moved the Vault and Eureka properties back into bootstrap.properties as well. The new application.properties now contains no values relating to Eureka, Vault, and Cloud Config.
When I run the service, it does indeed find the address for the config server through Eureka, as expected (although it fails to connect because it's the internal address and I'm running locally).
Conclusion
While these are valid workarounds, it's frustrating to not be able to have a dynamic URL for the config server (as is the entire point of using Eureka). Right now, it looks like my choices are either to use a hard-coded URL and risk having to change every property file, or use a deprecated behavior that Spring documentation specifically disfavors (source).
I would appreciate any guidance you have on the issue, and I thank you in advance.

Reuse spring boot properties for liquibase configuration

I want to start use liquibase in my Spring Boot app. Now I already have db configuration, something like:
abc.datasource.jdbc-url=
abc.datasource.username=
abc.datasource.password=
For liquibase usage I also added the parameters to the same file with a same values:
spring.liquibase.url=
spring.liquibase.user=
spring.liquibase.password=
The question is: is it possible to configure it somehow to avoid duplication of the configuration values?
If you want to do it the same file declare shared properties and reference them below
shared.datasource.jdbc-url=
shared.datasource.username=
shared.datasource.password=
abc.datasource.jdbc-url=${shared.datasource.jdbc-url}
abc.datasource.username=${shared.datasource.username}
abc.datasource.password=${shared.datasource.password}
spring.liquibase.url=${shared.datasource.jdbc-url}
spring.liquibase.user=${shared.datasource.username}
spring.liquibase.password=${shared.datasource.password}
You can access defined properties in application.yaml:
spring:
application:
name: application-name
some-value: ${spring.application.name} # will be equal to 'application-name'
The order of the properties is not important.
I believe you do not need to repeat the same parameters, as those will be automatically picked up for Liquibase.
See example here:
https://github.com/juliuskrah/spring-boot-liquibase/blob/main/src/main/resources/application.properties

How to correctly configure Spring Data JPA into the application.properties configuration file of a Spring Boot 2.X application?

I am finding the following difficulties trying to configure Spring Data JPA into my Spring Boot project.
I have the following problem related to the application.properties file. This is my original application.properties file content:
spring:
application:
name: Spring Boot Excel API
datasource:
driverClassName: org.mariadb.jdbc.Driver
url: jdbc:mariadb://localhost:3306/SOC_Dashboard
username: admin
password: password
timeBetweenEvictionRunsMillis: 1000
testWhileIdle: true
validationQuery: SELECT 1
in which I configured the database connection for my project (I used JdbcTemplate to interact with my databse since now and I am replacing with Spring Data JPA).
I am not so into Spring Boot but it seems to me that exist 2 ways to set the configuration into my application.properties file: one is as done in my configuration (using something like a tree structure) and another one use a "flast" structure.
Searching online I only found this "flat" configuration for JPA:
spring.jpa.hibernate.ddl-auto=none
that is not working in my case. Putting it into my application.properties file I obtain a syntax error due to the fact that it is using the other tree style.
So I am trying to change my original file in this way:
spring:
application:
name: Spring Boot Excel API
datasource:
driverClassName: org.mariadb.jdbc.Driver
url: jdbc:mariadb://localhost:3306/SOC_Dashboard
username: admin
password: password
timeBetweenEvictionRunsMillis: 1000
testWhileIdle: true
validationQuery: SELECT 1
jpa:
hibernate:
ddl-auto: none
Is it the right way to proceed?
Another doubt is related to the ddl-auto configuration. My development is database driven. I design the DB tables and JPA entity have to map these tables. I don't want to create\modify tables starting from my entity. Is it the right configuration?
To answer your first question, YES. It is the right way of configuring spring.jpa.hibernate.ddl-auto configuration in YAML files. And the properties file which you've mention in YAML format. So, the file name should be application.yml. In spring boot, spring-boot-starter-web dependency will automatically include snakeyaml dependency to read YAML files.
For the second question, you can mention none for ddl-auto if you don't want to create tables automatically or you can simply avoid the configuration. Please refer : How does spring.jpa.hibernate.ddl-auto property exactly work in Spring?

Change number of connection to database generated by a spring boot project

I have generated a spring boot project using jHipster. I want to reduce the number of connections to the database so I have modified the application-prod.yml file by adding the maximumPoolSize tag like this
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8&useSSL=false
username: root
password:
maximumPoolSize: 2
But when I try deploying the application I have 10 connections to the database. What am I doing wrong?
Thanks
With Spring Boot 1.4 the general properties have been reduced and moved to specific properties per DataSource provider (which is also explained in the reference guide and the release notes).
So instead of using spring.datasource.maximumPoolSize you should be using spring.datasource.hikari.maximumPoolSize
For a list of properties see the appendix.

Categories