Spring boot Get properties from consul server - spring

I have a spring boot application and I would like to get properties that I have on a consul agent.
#EnableDiscoveryClient
#SpringBootApplication(scanBasePackages={"com.commons"})
public class MainAppProxy implements CommandLineRunner {
#Value("${proxy.endpoint}")
private String endpointAddress;
My application.properties is under src/main/resources
spring.application.name=SOAPProxy
spring.cloud.consul.host=http://10.0.1.241
spring.cloud.consul.port=8500
spring.cloud.config.discovery.enabled=false
in pom.xml I have the following config (short version)
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR5</version>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
The properties are stored on consul in this format:
Business/SOAPProxy/proxy.endpoint
When the application boots, it seems that it finds consul but it cannot get the values as it could before trying consul #Value("${proxy.endpoint}")
How can I get the properties on consul?

You can use three way to load configuration from consul
key/value
yaml
file
I used in yaml to load configuration.
This is my bootstrap.yml file (you can use .property file also)
spring:
application:
name: SOAPProxy
---
spring:
profiles: default
cloud:
consul:
config:
data-key: data
prefix: config
format: yaml
host: localhost
port: 8500
discovery:
prefer-ip-address: true
my boot app Annotate like below
#EnableDiscoveryClient
#EnableAutoConfiguration
#SpringBootApplication
public class SpringBootConsulApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootConsulApplication.class, args);
}
}
maven dependancy add like this
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
this is configuration of consul agent key/value
now in startup all configuration load to the application

Related

Refresh not working when using spring cloud starter and fabric8

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.

spring eureka - Error resolving template [eureka/status], template might not exist or might not be accessible

I am following this tutorial to implement a microservice architecture within my project.
First I added the following dependencies to my project:
</dependencies>
...
<dependency>
<!-- Spring Cloud starter -->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<!-- Eureka service registration - CHANGED -->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
After that I added a registrationServer class to the project (as described in the tutorial) and set up my config.
The config of my registration server remain very basic:
# Ignore JDBC Dependency
# This demo puts 3 applicatons in the same project so they all pick up the
# JDBC Depdendency, but this application doesn't need it.
spring.autoconfigure.exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
# Configure this Discovery Server
eureka:
instance:
hostname: localhost
client: # Not a client, don't register with yourself
registerWithEureka: false
fetchRegistry: false
server:
port: 8761 # HTTP (Tomcat) port
Now as I understood it, at this point I should be able to access http://localhost:8761 and see my setup as tracked by the registration server.
Instead I get a Whitelabel Error Page containing the following error message:
Error resolving template [eureka/status], template might not exist or might not be accessible by any of the configured Template Resolvers
Note: Before adding Eureka, my project consisted of a REST application which I want now to transform into a microservice. The REST service contained a frontend which is organized in the project directories like this:
src
- main
- resources
- templates
- index.html
- static
- built
- bundle.js
Note 2: Also I tried to disable the thymeleaf template which led to an 404 error when trying to access http://localhost:8761.
# Discovery Server Dashboard uses FreeMarker. Don't want Thymeleaf templates
spring:
thymeleaf:
enabled: false # Disable Thymeleaf
datasource:
type: org.springframework.jdbc.datasource.SimpleDriverDataSource
As stated in this github issue:
If your project already uses Thymeleaf as its template engine, the Freemarker templates of the Eureka server may not be loaded correctly. In this case it is necessary to configure the template loader manually:
application.yml
spring:
freemarker:
template-loader-path: classpath:/templates/
prefer-file-system-access: false

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

Eureka Client running with name "UNKNOWN" in eureka server UI

I created a Eureka server spring boot application. It is properly loaded. After that I am trying to create a Eureka client.But it is not getting listed in eureka server UI. I am adding my client application details.
My main controller class file is as below,
#SpringBootApplication
#EnableDiscoveryClient
public class ZEurekaClientServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ZEurekaClientServiceApplication.class, args);
}
}
And my pom.xml contains the ,
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
And
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
And my application.properties file containing,
eureka.client.serviceUrl.defaultZone=http://localhost:8071/eureka
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
When It client is running , the eureka server UI not showing it's name. ONly showing UNKNOWN as application. I am adding its screenshot below.
What I need to display the application name instead of "UNKNOWN" in the eureka server UI? Is there is any additional settings to add application name?
You can specify the application name by setting it either in your application.yml or in your application.properties.
For application.yml:
spring:
application:
name: {YOUR_APPLICATION_NAME}
For application.properties:
spring.application.name={YOUR_APPLICATION_NAME}
In my case, the property (yml) file could not be copied to the target folder due to a build problem.
If this happens, none of the yml properties will load and the spring boot program will run with the default configuration.
For example, Tomcat started with 8080, not any port you specified in the yml file

Spring cloud config client properties are not getting resolved

I am very new to the concept of Spring Cloud and Spring external configurations, in fact started yesterday itself.
I have created one Config Server picking the configurations from a local Git repository, one micro service which is also the config client and one Eureka driven service discovery server.
Below is the code that i have mostly borrowed from various resources across internet -
Config Server - application.yml:
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: file:///${user.home}/config-repo
Config Server - Main class (bootstrap)
#EnableConfigServer
#SpringBootApplication
public class CloudConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(CloudConfigServerApplication.class, args);
}
}
config-repo is the local git repo on my machine and has got a .yml file with name of the config client application i.e. authmanager.yml
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:8761/eureka/
healthcheck:
enabled: true
lease:
duration: 5
spring:
application:
data:
mongodb:
host: localhost
port: 27017
database: edc_mc
logging:
level:
org.exampledriven.eureka.customer.shared.CustomerServiceFeignClient: FULL
Now after running the config server, below is the output of the end point http://localhost:8888/authmanager/default -
{"name":"authmanager","profiles":["default"],"label":"master","version":"0ca6ca7b4502b9bb6ce1bf8efeb25516682cf79a","propertySources":[{"name":"file:///C:\\Users\\username/config-repo/authmanager.yml","source":{"eureka.client.serviceUrl.defaultZone":"http://127.0.0.1:8761/eureka/","eureka.client.healthcheck.enabled":true,"eureka.client.lease.duration":5,"spring.application.data.mongodb.host":"localhost","spring.application.data.mongodb.port":27017,"spring.application.data.mongodb.database":"db_name","logging.level.org.exampledriven.eureka.customer.shared.CustomerServiceFeignClient":"FULL"}}]}
Micro service + Config client code -
bootstrap.yml -
server:
port: 9097
spring:
application:
name: authmanager
cloud:
config:
uri: http://localhost:8888
Client - Main class (bootstrap) -
#SpringBootApplication
#EnableDiscoveryClient
#EnableWebMvc
public class CloudLoginManagerApplication {
public static void main(String[] args) {
SpringApplication.run(CloudLoginManagerApplication.class, args);
}
}
Controller class in the config client, where i want to use the configuration file properties -
#RefreshScope
#RestController
#RequestMapping("/auth")
public class MyController {
#Value("${spring.application.data.mongodb.database}")
String env_var;
Skipping rest of the code for clarity sake.
This is the error i am getting -
Could not resolve placeholder 'spring.application.data.mongodb.database' in string value "${spring.application.data.mongodb.database}"
Other properties like server.port is not giving issues.
I have also tried the Environment interface way, but thats returning null as well.
Any pointers please, i have almost reached dead end now.
Thanks,
AJ
To enable cloud config you have to add the spring-cloud-starter-config to your dependencies. You can verify by checking the /env (might need to add actuator) to see which properties are available.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
In my case, I add the spring-cloud version in the properties section.
1 : Add spring cloud version:
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
</properties>
2 : dependencyManagement below of the <dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
1-if you using maven, add this dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2-if you using gradle, add this dependency:
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-config'
}
3- refrech

Resources