Spring not picking up changes to ConfigMap - java

I have an application that is using Springboot, I am trying to allow on the fly configuration updates using the following.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.1-RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-config</artifactId>
<version>1.1.4.RELEASE</version>
</dependency>
I have tried to follow this article https://medium.com/swlh/kubernetes-configmap-confuguration-and-reload-strategy-9f8a286f3a44, and have managed to get Spring pulling the config from the ConfigMap, however, if I update the ConfigMap when the application is running, spring does not pick it up. This is my bootstrap.yml
spring:
cloud:
kubernetes:
config:
enabled: true
sources:
- namespace: default
name: hello-world
reload:
enabled: true
mode: event
strategy: refresh
I have also tried using mode: polling, but still no change. And I have added the view role.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "hello-world.fullname" . }}-view
roleRef:
kind: ClusterRole
name: view
apiGroup: rbac.authorization.k8s.io
subjects:
# Authorize specific service accounts:
- kind: ServiceAccount
name: {{ include "hello-world.serviceAccountName" . }}
namespace: default
I am thinking maybe it's the way I am loading my configuration in Java?
#ConfigurationProperties(prefix = "spring.app")
#Bean
public Properties appProperties() {
return new Properties();
}
#Autowired
#Qualifier("appProperties")
private Properties props;
My ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: hello-world
data:
application.yml: |-
spring:
app:
message: Hello
I am then accessing values like props.getProperty("message")
UPDATE:
So I managed to get the changes picked up, by enabling the actuator refresh endpoint:
management:
endpoint:
restart:
enabled: true
But now I have a new question, is this necessary? Is there any way to get this to work without including the actuator?

Please make sure you have the following dependency in your POM with a version.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
I had similar issue, which is resolved after adding this.

make sure to add #RefreshScope to the bean that you want to hot reload with inject with values from config maps.

Related

Profile Groups in Spring Boot 3 not working

After the migration to Spring Boot 3 it's not possible to activate multiple profiles in profile specific files. Instead Profile Groups should be used.
Unfortunately I can't get them to work, here is the snippet from my yml config:
spring:
profiles:
group:
local: debuglogin, profile_a, profile_b, profile_c
I have tried this in application-local.yml. Did anyone had the same experience?
I've just found the issue. I was adding this code block in the profile specific file like application-local.yml instead it should be added in the application.yml:
spring:
profiles:
group:
local: debuglogin, profile_a
integration-test: debuglogin, profile_b
this should work if added in the application.yml but not in profile specific files.

Springboot ServerConfig Client

I have the following in my app properties
spring:
main:
banner-mode: off
allow-bean-definition-overriding: true
config:
uri: http://localhost:8890
I have this class:
#RefreshScope
#Configuration
#Getter
public class Service {
#Value("${Some Value}")
Boolean val;
}
The problem, is that my app does not grab the configuration from the localhost running configuration server. I can tell you that my local config server is working fine and that the config is visible in a browser
Have you added 'Spring cloud config client' dependency ?
And also add some properties in client service to make connection with config server ,
spring.cloud.config.uri=http://localhost:8888(Port of your
server)
spring.cloud.config.name=user-service-ws(properties file
name in your remote)
I have found the solution.
Since spring boot 2.4 everything has changed. We must specify to bootstrap the cloud config. This is done using the dependency such as:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>3.1.4</version>
</dependency>
spring:
main:
banner-mode: off
allow-bean-definition-overriding: true
application:
name: myApp
config:
import: optional:configserver:http://localhost:8890/
cloud:
config:
name: some name
Very important to do this: optional:configserver:
Thanks everyone and hope it is useful to everyone.

Spring config server cannot be disabled for local development

I was updating microservice to the newest Springboot - for now it is 2.5.5 with cloud version 2020.0.4. However there were some changes related to connection with config server. Previously config server configuration looked like this:
spring:
cloud:
config:
uri: ${CONFIG_SERVER_URI:http://localhost:8888}
fail-fast: ${CONFIG_FAIL_FAST:true}
However now it's required to provide it this way:
spring:
config:
import: configserver:${CONFIG_SERVER_URI:http://localhost:8888}
And that would be perfectly fine, except I am not able to run microservice locally without connecting to config server.
Previously I did it like this:
spring:
cloud:
config:
enabled: false
And it was perfectly fine, I had separate application-local.yaml file and had what I wanted.
Now I tried this (according to what is said in documentation):
spring:
cloud:
config:
import-check:
enabled: false
enabled: false
config:
import: "optional:configserver:http://localhost:8888"
But once I run microservice locally, I get only single log like this:
Connected to the target VM, address: '127.0.0.1:59759', transport: 'socket'
And basically nothing more, seems like it keeps trying to connect to config server, because if I run config server and after this try to run my microservice, it's working fine. Additional weird thing is that IntelliJ is showing me that it doesn't recognize this import-check property.
As for dependencies I have only implementation 'org.springframework.cloud:spring-cloud-starter-config:3.0.5' related to config server.
Is there some way to run microservice locally so that it's not connecting to config server using Spring Boot 2.4+? I don't want to use bootstrapping and providing additional dependency, since there is no point to use legacy stuff.
Here is the configuration I have for application.yaml in /src/main/resources folder.
---
spring:
config:
activate:
on-profile: "!config-local"
import: configserver:http://config-server.example.com:8888/
cloud:
config.fail-fast: true
---
spring:
config:
activate:
on-profile: "config-local"
import: optional:configserver:http://localhost:8888/
cloud:
config:
enabled: false
And in Intellij IDEA Run config, I set the active Profile as config-local this works with Springboot 2.5.5 and
ext {
set('springCloudVersion', "2020.0.4")
}

Spring Boot read environment variables inside application-properties

So I have been trying to figure out how to use environment-variables in either application.properties or application.yaml. Since this works in countless frameworks (such as Laravel for example), I assumed this would also work in Spring Boot. Now as I have found out, this is not the case.
I saw a post about Spring Environment API, that started that the environment-variable SPRING_DATASOURCE_URL would be equivalent to setting spring.datasource.url inside my application. However, this also didn't work for me.
Is there any quick way that allows using variables that are declared inside a .env file?
I'd like to use it like this inside the application.properties if possible.
spring.datasource.url=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
.env is way of Python. If you use spring cloud, you can read env variable from configServer then inject them into application.properties.
add some dependency into pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
define a yml to locate config-server. for example, called myBootstrap.yml
spring:
cloud:
config:
fail-fast: true
uri: http://[config-server-git]
name: cc
profile: config
label: maste
define a file named cc-config.properties and push it into config-server git. The env variables are written in this properties.
use below way to run application jar
java -jar [your-application-jar] --spring.cloud.bootstrap.location=myBootstrap.yml

Spring boot ignores datasource url in application.yml

I've discovered that spring boot silently ignores all datasource properties loaded through org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.
My application.yml contains:
spring:
datasource:
name: this is not ignored
url: this is ignored
During startup i see line:
o.s.j.d.e.EmbeddedDatabaseFactory : Creating embedded database 'this is not ignored'
Debugging shows that DataSourceProperties object has not any properties set during call to getUrl (debugging also shows that exception is thrown but it is silently ignored because it is not visible in logs).
Url is obvoiusly invalid but database is somehow initialized.
Tested on 1.2.7 version.
What can cause such strange behaviour? How can I debug it further?
Adding
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</dependency>
to dependencies solved problem.
Problem was caused by Spring Boot autoconfiguration magic - I was not using correct spring boot starter.

Categories

Resources