Read values from yaml file - spring-boot

I have the following issue. I create a data source based on a value I read in the yaml file based on a given profile.
Here is my code
#Value("${my.db.serviceId}")
private String serviceId;
#Primary
#Bean(name = "prodDataSource")
#Profile("prod")
public DataSource prodDataSource() {
return getDataSource(serviceId);
}
#Bean(name = "devDataSource")
#Profile("dev")
public DataSource devDataSource() {
return getDataSource(serviceId);
}
Here is my yaml file
---
spring:
profile: dev
my:
db:
serviceId: 'my-dev-service'
---
spring:
profile: prod
my:
db:
serviceId: 'my-prod-service'
---
My current issue is that when I start my application with the "dev" profile,
the value of the serviceId is 'my-prod-service'.
What am I doing wrong here?

#Primary annotation enables a bean that gets preference when more than one bean is qualified to autowire a single valued dependency
So the bean with #Primary annotation will get more preference

so I finally realized that in the yaml file I put "profile" instead of "profiles". that's why it wasn't picking up my profile.
I endeded up changing to:
---
spring:
profiles: dev
my:
db:
serviceId: 'my-dev-service'
---
spring:
profiles: prod
my:
db:
serviceId: 'my-prod-service'
---

Related

Spring boot config server does not refresh if I update local

I have Spring cloud project which has below information:
Controller of address-service-1:
#RestController
#RequestMapping("/api/address")
#Slf4j
#RefreshScope
public class AddressController {
#Value("${scope-refresh-testing}")
private String message;
#RequestMapping("/scope-refresh-testing-message")
String getMessage() {
return this.message;
}
}
bootstrap.yml of address-service-1:
spring:
application:
name: address-service-1
# register to config server
cloud:
config:
discovery:
enabled: true
service-id: config-server-1
profile: default
management:
endpoints:
web:
exposure:
include:
- refresh
Properties of config-server-1:
server:
port: 8888
spring:
application:
name: config-server-1
cloud:
config:
server:
git:
default-label: master
uri: file:///E:/workspace/Spring-boot-microservices-config-server-study/
Properties which I stored in file:///E:/workspace/Spring-boot-microservices-config-server-study/ (address-service-1.yml):
scope-refresh-testing: testDefault
If I change scope-refresh-testing: testDefault222 then run url actuator/refresh, the properties file will rollback to scope-refresh-testing: testDefault
Did I miss something in configuration?
Thanks

Spring Security: Local profile is token based but Dev profile defaults to username password

I want to implement token-based authentication. I am able to do it by adding filters. This seems to work in local profile only, but when I go to dev profile I get defaulted to Using generated security password: xxx , and the logs also do not register filters in dev profile like they do for local profile.
application-local.yml :
spring:
profiles:
active: local
h2:
console:
enabled: true
main:
allow-bean-definition-overriding: true
# Configuration used to validate header
auth:
userid: gibberish213 # header key: header value
application-dev.yml :
spring:
profiles:
active: local
main:
allow-bean-definition-overriding: true
datasource:
# Datasource related configs
application:
name: token-auth
# Configuration used to validate
auth:
userid: gibberish213 # header key: header value
I have an empty SpringSecurityInitializer class, would I need to add some config in that class:
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
Check if you have #Profile("local") annotation at top of your filter beans. If you do, they only work at the specified profile.

Disable / remove spring boot datasource by profile

Using spring boot yaml config, I have a datasource that looks like this:
datasource:
url: jdbc:postgresql://somehost/somedb
username: username
password: password
hikari:
connection-timeout: 250
maximum-pool-size: 1
minimum-idle: 0
I can succesfully point to different DBs based on profile, but I'd like to setup a profile that does not use this datasource at all. When I use that profile, however, I get this:
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified and no embedded datasource could be auto-configured.
Reason: Failed to determine a suitable driver class
How do I use this datasource in some profiles, but not in others?
You can skip the bean for specific profiles using `#Profile("!dev") annotation
profile names can also be prefixed with a NOT operator e.g. “!dev” to exclude them from a profile
from docs here
If a given profile is prefixed with the NOT operator (!), the annotated component will be registered if the profile is not active — for example, given #Profile({"p1", "!p2"}), registration will occur if profile 'p1' is active or if profile 'p2' is not active.
Profiles can also be configured in XML – the tag has “profiles” attribute which takes comma separated values of the applicable profiles:here
<beans profile="dev">
<bean id="devDatasourceConfig"
 class="org.baeldung.profiles.DevDatasourceConfig" />
</beans>
Change to:
spring:
datasource:
url: jdbc:postgresql://somehost/somedb
username: username
password: password
hikari:
connection-timeout: 250
maximum-pool-size: 1
minimum-idle: 0
Springboot works with Autoconfiguration by default, but you can customize excluding some AutoConfiguration classes
Edit your configuration to skip AutoConfiguration:
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
Make your own datasource by profile
#Bean
#Profile("dev")
DataSource dataSourceDevProfile(org.springframework.core.env.Environment environment) throws Exception {
return DataSourceBuilder.create().url("").driverClassName("").password("").username("").build();
}
#Bean
#Profile("!dev")
DataSource dataSourceNoDev(org.springframework.core.env.Environment environment) throws Exception {
return DataSourceBuilder.create().url(environment.getProperty("spring.datasource.url")).driverClassName("").password(environment.getProperty("spring.datasource.password")).username(environment.getProperty("spring.datasource.username")).build();
}
Or Totally Programatically
#Bean
DataSource dataSource2(org.springframework.core.env.Environment environment) throws Exception {
if (environment.acceptsProfiles("dev")){
//return datasource dev
}else{
//return datasource prod
}

Spring Cloud Server Config only refreshing application.yml and not other properties files

I have a bunch of YAML and properties files in my Spring Boot project :
- application.yml
- application-dev.yml
- spring-integration.properties
- common.properties
- test.yml
- ...
I'm trying to understand how can I implement Spring Cloud Server Config for my project and I have a hard time figuring out why Spring Cloud Server Config is not picking up any of the changes on any of my other files (but application.yml & application-dev.yml).
For example, in my spring-integration.properties, after changing this value :
start.task.rate=500000
And POST to /management/refresh, nothing is detected by the actuator and I get an {} response.
However, when I change my datasource in application.yml, I get the expected result :
[
"spring.datasource.url"
]
Here is my Application.java :
#SpringBootApplication
#EnableConfigServer
#ImportResource("classpath:integration-config.xml")
#ConfigurationProperties
#EnableSwagger2
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And my bootstrap.yml :
spring:
application:
name: ${appName:tasky}
profiles:
include:
- native
cloud:
config:
failFast: true
server:
bootstrap: true
prefix: /config
native:
search-locations: file:///C:/workspace/tasky/config/
I'm using :
<spring-cloud.version>Edgware.SR1</spring-cloud.version>
<spring-boot-version>1.5.9.RELEASE</spring-boot-version>
From what I could gathered, on /refresh Spring Actuator (?) is only picking up properties files starting with ${appName} or application, in my case I had to regroup all my properties files under one file named : tasky-{profile}.properties.

Spring Cloud Config Server issue - Configuring multiple sources native and jdbc

I want to connect to multiple repositories i.e native (file system) and jdbc in spring cloud config. I created a spring cloud config server with below details
application.properties
server.port=8888
spring.profiles.include=native,jdbc
spring.cloud.config.server.native.search-locations=classpath:/config,classpath:/app1, classpath:/app2,classpath:/ep
encrypt.key=abcdef
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/configuration?useSSL=false
spring.cloud.config.server.jdbc.sql=SELECT properties.key, properties.value from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=?
spring.datasource.username=root
spring.datasource.password=root
spring.cloud.config.server.native.order=1
spring.cloud.config.server.jdbc.order=2
Irrespective of priority order it always fetches information from jdbc and not from native.
I tried adding the last 2 properties for order to bootstrap.properties still same behavior.
Am is missing anything ? Is my configuration correct ? Please suggest
in spring boostrap.yml loaded before application.yml so you declare server port,config search location and active profile configuration is good approach for this stack,so keep it simple boostrap.yml also spring cloud default profile is native
and in application-"profile".yml is have environment and other configuration properties
and your boostrap.yml or properites like that
server:
port: 8888
spring:
application:
name: appName
profiles:
active: native,jdbc
cloud:
config:
server:
native:
order: 1
searchLocations: classpath:/config,classpath:/app1, classpath:/app2,classpath:/ep
and create applicaiton-jdbc.properties or yml file in same layer in boostrap.yml or properties and declare jdbc properties
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: 'jdbc:mysql://localhost:3306/configuration?useSSL=false'
cloud:
config:
server:
jdbc:
order: 2
sql: 'SELECT properties.key, properties.value from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=?'
username: root
password: root
and your config server configuration like this
#SpringBootApplication
#EnableConfigServer
#Import({JdbcEnvironmentRepository.class})
public class ConfigServer {
#ConfigurationProperties(prefix = "spring.datasource")
#Bean
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
public static void main(String[] arguments) {
SpringApplication.run(ConfigServer.class, arguments);
}
}

Resources