Refresh not working when using spring cloud starter and fabric8 - spring

I think that there is an issue when using these two dependencies in the same projet. I'm talking about spring-cloud-starter and spring-cloud-starter-kubernetes-fabric8-config.
I'm using
Spring Boot : 2.7.7
Spring Cloud : 2021.0.5
What i'm trying to build is a spring boot application on kubernetes. Each time a configmap or a sercret get changed, the app context should be updated with the new values. To achieve this, i'm using the spring cloud watcher.
https://docs.spring.io/spring-cloud-kubernetes/docs/current/reference/html/#spring-cloud-kubernetes-configuration-watcher
For the configmap part, everything works fine but when i tried to use a secret i noticed a strange behavior. The spring watcher calls my pods on the /actuator/refresh endpoint but nothing get updated. Actually, even on my local machine, the /refresh endpoint returns 200_OK but nothing is updated.
Here's the code snippet :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
#Configuration
#ConfigurationProperties(prefix = "metadata")
#PropertySource(value = "classpath:acl-default.yaml", factory = YamlPropertySourceFactory.class)
#PropertySource(value = "file:${user.home}/acls/acl.yaml", factory = YamlPropertySourceFactory.class, ignoreResourceNotFound = true)
#Slf4j
#Getter
#Setter
public class ACLConfig implements InitializingBean {
private List<User> users;
The ACLConfig class will load our users credentials let's say based on a file from the files system under ${user.home}/acls/acl.yaml otherwise it will get loaded from the classpath.
The content of ${user.home}/acls/acl.yaml is :
metadata:
users:
- name: Richard
password: kjqsd78jkdq-local
- name: Richard
password: jqsd98ds78-local
- name: Richard
password: kSkjqf887qsd-local
bootstrap.properties
server.port=8080
spring.application.name=demo
spring.cloud.kubernetes.config.sources[0].name=${spring.application.name}
spring.cloud.kubernetes.config.sources[0].namespace=spring-cloud-watcher
application.properties
logging.level.root=INFO
logging.level.com.example.demo=DEBUG
management.endpoints.web.exposure.include=info,health,refresh
spring.config.import=optional:file:${user.home}/acls/acl.yaml
So as i said, this example does not work (the acl file update will not trigger the spring context refresh).
To make it work, you have to :
delete the spring-cloud-starter-kubernetes-fabric8-config dependency from pom.xml,
change the content of ${user.home}/acls/acl.yaml,
call the /actuator/refresh,
check the logs : you'll see that ACLConfig -> users List will be updated
You can find the example on my repo : https://github.com/mamdouni/spring-watcher-example
Delete the fabric8 dependency is not an option for me because i need to run this on kubernetes but i don't understand why it blocks the context refresh !!!
Any help will be appreciated.

Related

Spring boot application with Spring-boot-starter-data-jpa and spring-boot-starter-test makes spring does not find application properties

I have created a small application with spring boot that access to a database (mySql) using spring data:
spring-boot-starter-parent: 2.4.2
spring-boot-starter-web: 2.4.2
spring-boot-starter-data-jpa: 2.4.2
mysql-connector-java: 8.0.22
spring-boot-starter-test: 2.4.2
org.junit.jupiter: 5.7.0
junit-jupiter-engine: 5.7.0
I have configured my application.properties, inside src/main/resources, and I have configured the properties for url, username, password, driver, ..., like this:
spring.datasource.url=jdbc:mysql://localhost:3306/BBDD
spring.datasource.username=XXX
spring.datasource.password=XXXX
spring.datasource.driver=com.mysql.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect:org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
I have an interface for my repository for access to my database:
#Repository
public interface ArticleRepository extends PagingAndSortingRepository<ArticuloEntity, Integer> {
}
also, I have defined my entity.
The issue consists on when I start my webapp, I get an error because it does not read the parameters for configuring the datasource from the application.properties:
Description:
Failed to configure a DataSource: 'url' attribute is not specified and
no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following: If you want an embedded database (H2, HSQL or
Derby), please put it on the classpath. If you have database settings
to be loaded from a particular profile you may need to activate it (no
profiles are currently active).
If I remove the dependencies for spring-boot-starter-test and junit, the application loads fine, and it access to database. But if I add the dependency for adding my junits, it does not read my application.properties file and I get the previous error.
How can I have my application configured with junits and reading the configuration for my application with the application.properties file?
Thank you in advance!
Your test/application.properties needs to be configured as well. Try adding this to your test application properties file
spring.datasource.url=jdbc:h2:mem:BBDD;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
and this to your pom if you don't already support h2.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
check your application.properties
changing
spring.datasource.driver=com.mysql.jdbc.Driver
to
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

Azure AppConfiguration with Spring Boot 2.5.x

Question
How to integrate an Azure AppConfiguration with SpringBoot 2.5.x or higher?
Info
Im trying to use an Azure AppConfiguration resource with a Spring Boot 2.5.4 project. Unfortunately I cant get it to read a setting from the AppConfiguration or even connect to it as far as I can tell.
The project is newly created with the Spring Initializr where I only added
Spring Boot Starter Web
Spring Boot Starter Security
Spring Boot Starter WebSocket
Afterwards I tried following the Microsoft Quickstart documentation with no success. The documentation mentions that its using Spring 2.4.x so I assume some changes broke it.
I also tried to identify the issue by looking through some Azure Spring Boot Code Samples.
All the examples so far use the bootstrap.properties file which I learned during my search so far is deprecated. Moving the settings to the application.yml or enabling use-legacy-processing: true did not work either. Any ideas?
pom.xml
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-cloud-appconfiguration-config</artifactId>
<version>2.0.0</version>
</dependency>
...
application.yml
spring:
config:
use-legacy-processing: true
profiles:
active: "develop"
application:
name: "MySampleService"
cloud:
azure:
appconfiguration:
stores:
- connection-string: "SomeAzureAppConfigurationResourceConnectionString"
label: ${spring.profiles.active}
#mysampleservice:
# message: "this is a message from file"
AppConfiguration Resource
Im not entirely sure about the format for the setting name. I tried to build the format based on this documentation.
The configuration classes should be fine since commenting in the mysampleservice causes the value of message beeing used.
Any hints are appreciated!
Some more info to elaborate on the accepted answer
The documentation linked in the answer refers to two different packages. The one linked right at the start in the maven repository is spring-cloud-azure-appconfiguration-config while the one used further down is azure-spring-cloud-appconfiguration-config. The second one works with the bootstrap.properties file.
Working pom.xml and bootstrap.properties:
...
<dependencies>
<!-- Dependency to load configuration from azure app configuration resource. Note that additional settings are required in bootstrap.properties
Documentation of settings: https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/appconfiguration/azure-spring-cloud-starter-appconfiguration-config
-->
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-cloud-appconfiguration-config-web</artifactId>
<version>2.1.0</version>
</dependency>
...
# Use this to enable or disable the cloud config, disabling it results in application.yaml beeing used.
spring.cloud.azure.appconfiguration.enabled=true
# Connection string to azure app configuration resource
spring.cloud.azure.appconfiguration.stores[0].connection-string= Endpoint=https://myofficeconfiguration.azconfig.io;Id=zUcT-l9-s0:PFYfW7WM0/Pz7WZOnH3v;Secret=JTB9myJqGekDAJ5m8Z1vjmkJZrPd88JbOEE3EqoqJYs=
# Configured filters for settings in the previous defined app configuration resource
spring.cloud.azure.appconfiguration.stores[0].selects[0].key-filter = /mysampleservice/
spring.cloud.azure.appconfiguration.stores[0].selects[0].label-filter = Sample
spring.cloud.azure.appconfiguration.stores[0].selects[1].key-filter = /notificationservice/
spring.cloud.azure.appconfiguration.stores[0].selects[1].label-filter = Sample2
bootstrap.yml/bootstrap.properties can still be used, they are no longer part of the base Spring packages.
Also, you want to use this doc for 2.0.0 and newer https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/appconfiguration/azure-spring-cloud-starter-appconfiguration-config.

Spring Cloud not picking up configured profile in cloud.aws.credentials.profile-name

I have a spring boot application where I've been using Spring Cloud AWS.
I'm trying to add a new profile to my ~/.aws/credentials file like so:
[local-dev]
aws_access_key_id=localkey
aws_secret_access_key=localkey
in my application.yml file I've specified which profile to use.
cloud:
aws:
credentials:
profile-name: local-dev
region:
static: us-east-1
whenever I start up my Application I get a error saying:
No AWS profile named 'default', com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper#1b26fac2: Failed to connect to service endpoint:
When I set the profile name to "default" it does work though. It's like spring is ignoring the profile-name that I've given it in the configuration.
Currently I have set this version of spring cloud in my maven POM file.
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-aws -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
I faced the same issue when using the same Spring Cloud Libraries version - 2.2.1.RELEASE.
After updating the Spring Cloud libraries to 2.2.6.RELEASE everything works fine.

How to collect turbine stream from a Standalone Turbine Stream application

Similar with this post, I created another turbine stream based application to collect hystrix stream from other applications.
Spring Boot: 2.0.4.RELEASE, Spring Cloud: Finchley.SR1
The application class:
#SpringBootApplication
#EnableDiscoveryClient
#EnableTurbineStream
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
The maven dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
The application config file is:
server:
port: 8989
spring:
application:
name: hystrix-turbine-stream
management:
endpoints:
web.exposure.include: '*'
When I explore the source codes of #EanbleTurbineStream, and found TurbineController expose a Flux to the root '/' endpiont.
But when I tried to explore http://localhost:8989 in the Hystrix Dashboard, found it did not work as expected.
Update: When I tried to access the turbine stream application, and got:
curl http://localhost:8989
data:{"type":"ping"}
data:{"type":"ping"}
data:{"type":"ping"}
data:{"type":"ping"}
In the application console(logging), there is some log shown as:
: Registering MessageChannel turbineStreamInput
But I can not see the there are some message sent to this channel in my client app.
Here is the sample codes of my turbine stream application
Update2: Got it worked, I used a outdated spring-cloud-starter-netflix-hystrix-stream (which is existed in v2.0.0M2, but not existed in the final RELEASE version) in my client app, when I used spring-cloud-starter-netflix-hystrix and spring-cloud-netflix-hystrix-stream combination in the client app, it worked well.
#Hantsy We would need more details regarding what your failures are here. I have a running Spring Boot: 2.0.4.RELEASE, Spring Cloud: Finchley.SR1 turbine stream app so I can help if you need further clarification.
For #EnableTurbineStream to work properly,
you'll need to add the below dependencies in your app according to documentation here
https://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#_turbine_stream
spring-cloud-starter-netflix-turbine-stream
spring-boot-starter-webflux
spring-cloud-stream-binder-rabbit
(any spring-cloud-stream-* would do, raabitmq worked for me)
On the client, add a dependency to spring-cloud-netflix-hystrix-stream and the spring-cloud-starter-stream-* of your choice.
Add the rabbitmq (in my case) configuration on your application.properties/application.yml file of your client and the turbine-stream app:
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
Hope this helps.
You should set properties on client app project: spring.cloud.stream.bindings.hystrixStreamOutput.destination=springCloudHystrixStream

Add JSON provider for CXF JAX-RS in Spring Boot properties or YAML file

How to move endpoint.setProvider(new JacksonJsonProvider()); into an application properties file?
#Bean
public Server rsServer() {
JAXRSServerFactoryBean endpoint = new JAXRSServerFactoryBean();
endpoint.setBus(bus);
endpoint.setProvider(new JacksonJsonProvider());
endpoint.setServiceBeans(asList(new CustomerServiceDefault()));
endpoint.setAddress("/");
endpoint.setFeatures(asList(new Swagger2Feature()));
return endpoint.create();
}
First if you haven't done so already, you have to add the dependency with the provider:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.0</version>
</dependency>
Then you need to add the package with Jackson entity providers for JAX-RS scanning (org.codehaus.jackson.jaxrs in this case), together with other packages you created. I'm using yaml configuration and class scanning as opposed to component scanning, and here is how it looks:
cxf:
path: /services
servlet.init:
service-list-path: /info
jaxrs:
classes-scan: true
classes-scan-packages: com.yourcompany.package.with.your.handlers,org.codehaus.jackson.jaxrs

Resources