I have a #Configuration class like below. I need to initialize configs from zookeeper znode's values on start of spring boot application and update config variables dynamically whenever their value gets updated in zookeeper.
#Component
#ConfigurationProperties("prefix")
class Props {
private String property1;
private String property2;
// getters & setters...
}
application.properties
prefix.property1=${PROPERTY1}
prefix.property2=${PROPERTY2}
bootstrap.properties
spring.cloud.zookeeper.connectString=localhost:2181
spring.cloud.zookeeper.config.watcher.enabled=true
The value of zNodes on zookeeper.
/config/application-name/context/property1: p1
/config/application-name/context/property2: p2
Not able to find any docs which defines how to bind the znode
values to the config values in spring-boot application.
Related
I am creating a spring boot app which has multiple data sources (7 in total) and whilst properties like dbUrl, username and password are data source specific, a great many are common. I obviously don't want to duplicate the properties for each data source and am trying to work out how I can create a HikariConfig instance for each datasource using a blended set of common properties.
The properties have the following format
spring.oracle.datasource.driverClassName
spring.oracle.datasource.autoCommit
spring.oracle.datasource.instance[0].dbUrl
spring.oracle.datasource.instance[0].username
spring.oracle.datasource.instance[0].password
spring.oracle.datasource.instance[1].dbUrl
spring.oracle.datasource.instance[1].username
spring.oracle.datasource.instance[1].password
spring.oracle.datasource.instance[2].dbUrl
spring.oracle.datasource.instance[2].username
spring.oracle.datasource.instance[2].password
spring.oracle.datasource.instance[n].dbUrl
spring.oracle.datasource.instance[n].username
spring.oracle.datasource.instance[n].password
I did try using configuration properties with a class that had the format below (lombok annotations ommitted)
public class DataSourceProperties extends HikariConfig {
public List<Instance> instance;
public static class Instance {
public String dbUrl;
public String username;
public String password;
}
}
But although the object is populated correctly I cannot figure out how I then create the n HikariConfig instances using the properties in the pojo. Clone or BeanUtils does not work, as it copies across all of the null fields which are rejected by the HikarConfig setters.
Anyone know a possible solution without duplicating the common properties and resorting to manual creation of the HikariConfig instances?
In the end, I used Spring's BeanUtils and wrote a function which found the null fields so they could be excluded.
Spring BeanUtils API Doc
Is there any way to refresh spring beans/properties w/o actuator and config server?
In my case, there is only one app/instance which reads the properties from the local file system
myapp.sample.prop1=1
myapp.sample.prop2=2
#ConfigurationProperties("myapp.sample")
public class Prop{
private int prop1;
private int prop2;
}
I autowire and i use it,
#Autowired
private Prop prop;
Occasionally the value might change in the file system. In that case,I just want to call my custom endpoint /reload which should refresh the values by reading the file.
I have a singleton configuration class where I want to store all the properties for our web application.
How do we read in the application.properies file like any other properties file without using annotations?
What is the the fully qualified filename for application.properies i.e. /application.properies?
We only want to read application.properties once.
Spring boot already reads all the properties stored in application.properties and much more, read Externalized Configuration documentation.
If you want to map one property named server.port you can just use #Value("${server.port}") Integer port.
If you want to access to all the properties loaded by Spring Boot, you can use the Environment object and access to all loaded PropertySources and retrieve all values from each property source.
In this this answer shows how. However, to avoid losing the precedence order of loaded properties, you have to reverse the property source list. Here you can find the code to load all the properties without losing the spring precedence order:
#Configuration
public class AppConfiguration {
#Autowired
Environment env;
public void loadProperties() {
Map<String, Object> map = new HashMap();
for (Iterator it = ((AbstractEnvironment) env).getPropertySources().iterator().reverse(); it.hasNext(); ) {
PropertySource propertySource = (PropertySource) it.next();
if (propertySource instanceof MapPropertySource) {
map.putAll(((MapPropertySource) propertySource).getSource());
}
}
}
}
I'm working on the REST API with spring boot. I want to use git in my project. in the file application.properties I have the database Url, username and password that I do not want to push on git. I don't know how can I create a file which contains my database configuration and how to inject those configurations in the application.properties .
application.properties
## Server Properties
server.port= 5000
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url= jdbc:mysql://localhost:3306/MyApp?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
spring.datasource.username= user
spring.datasource.password= pass
Spring picks up configuration properties not only from the application.properties but also from command line arguments, JAVA System-properties or from environmental-variables.
See complete list here: Spring Externalized Configuration.
So - for reference - you can keep the properties in the application.properties file with some default values (like in your example) in order to let other users know what kind of properties they can set for your application.
But instead of setting your real values there, you can either pass the variable to your application as arguments, like
-Dspring.datasource.username=user -Dspring.datasource.password= pass
or you can set them as environmental variables.
You can even create multiple configuration with different settings. If Spring cannot find a variable in the current configuration, then it will pick it up from application.properties (or from the other sources - see above)
first you should add application.properties to .ignore file like this
application.properties
if you will just connect to database you won't need to inject values by hand you just write it in application.properties
but if you want to put values in properties file and use it in Application
package com.microservice.test.limitservice;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
#Component
#ConfigurationProperties("limit-service")
public class Configuration {
private int minimum;
private int maximum;
public int getMinimum() {
return minimum;
}
public void setMinimum(int minimum) {
this.minimum = minimum;
}
public int getMaximum() {
return maximum;
}
public void setMaximum(int maximum) {
this.maximum = maximum;
}
}
and how to inject it simply
#Autowired
private Configuration configuration;
the application.properties file could be like this
limit-service.minimum=56333445
limit-service.maximum=6500
you should notice that it start with as example limit-service
and #ConfigurationProperties("**limit-service**")
And if you want to store your configuration in application.properties secure
you can see this link Spring Boot how to hide passwords in properties file
I have a Spring boot project, in which I use Cassandra as a database.
Currently, I am getting Cassandra instance by auto-wiring CassandraOperations.
My question is:
How can we set MaxRequestsPerConnection using a property file?
# spring.data.cassandra.keyspace-name=event
# spring.data.cassandra.contact-points=localhost
# spring.data.cassandra.port=9042
Currently, I have these properties on my property file, but I didn't found any property for setting MaxRequestsPerConnection
Spring Boot does not offer a configuration of all properties. You can define a ClusterBuilderCustomizer bean to customize Cluster instances.
Try the following code to declare a customizer bean which gets properties injected that can be provided via a properties file (more generally speaking, any property source available to Spring Boot):
#Configuration
public class MyConfiguration {
#Bean
ClusterBuilderCustomizer clusterBuilderCustomizer(
#Value("${spring.data.cassandra.pool.max-requests-local:10}") int local,
#Value("${spring.data.cassandra.pool.max-requests-remote:5}") int remote) {
PoolingOptions options = new PoolingOptions();
options.setMaxRequestsPerConnection(HostDistance.LOCAL, local);
options.setMaxRequestsPerConnection(HostDistance.REMOTE, remote);
return builder -> builder.withPoolingOptions(options);
}
}
An alternative to #Value is using a configuration class (annotated with #ConfigurationProperties which gives you IDE support (such as property-name auto-completion).
Step No : 1
In application.properties file we have to declare local and remote pool size (required size value )
# spring.data.cassandra.keyspace-name=event
# spring.data.cassandra.contact-points=localhost
# spring.data.cassandra.port=9042
# spring.data.cassandra.pool.max-requests-local:20
# spring.data.cassandra.pool.max-requests-remote:10
Step No:2
in the Bean Configuration :
#Bean
ClusterBuilderCustomizer please get the values by using the following code (using #value annotation):
#Value("${spring.data.cassandra.pool.max-requests-local}")
private int localPool;
#Value("${spring.data.cassandra.pool.max-requests-remote}")
private int remotePool;
By using this PoolingOptions class set the setMaxRequestsPerConnections for local and remote
HostDistance.LOCAL -- localPool
HostDistance.REMOTE -- remotePool
As per Spring Boot 2.3.0 release notes, ClusterBuilderCustomizer has been replaced with DriverConfigLoaderBuilderCustomizer and CqlSessionBuilderCustomizer. As said in anwser, You just need to declare two beans having these types:
#Bean
public CqlSessionBuilderCustomizer cqlSessionBuilderCustomizer() {
return cqlSessionBuilder -> cqlSessionBuilder
.withNodeStateListener(new MyNodeStateListener())
.withSchemaChangeListener(new MySchemChangeListener());
}
#Bean
public DriverConfigLoaderBuilderCustomizer driverConfigLoaderBuilderCustomizer() {
return loaderBuilder -> loaderBuilder
.withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(10));
}
}