I followed this documentation to get configs from application.properties in a quarkus service.
I am not using CDI, so here is what I am doing to get this config:
application.properties
redis.hosts=${REDIS_HOSTS}
redis.port=${REDIS_PORT}
redis.password=${REDIS_PASSWORD}
Note: I have set these environment variables.
RedisConfigInterface
import java.util.Set;
import io.smallrye.config.ConfigMapping;
#ConfigMapping(prefix = "redis")
interface RedisConfigInterface {
Set<String> hosts();
Integer port();
String password();
}
ConfigCreation
public class ConfigCreation {
public ConfigCreation() {
//Registering config
new SmallRyeConfigBuilder()
.withMapping(RedisConfigInterface.class)
.build();
// Getting config
RedisConfigInterface config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class).getConfigMapping(RedisConfigInterface.class);
Integer port = config.port();
System.out.println(port);
}
}
It builds correctly but I got this error when executing the service:
12:17:02 ERROR [io.qu.ru.Application] (Quarkus Main Thread) Failed to start application (with profile dev): io.smallrye.config.ConfigValidationException: Configuration validation failed:
java.util.NoSuchElementException: SRCFG00014: The config property redis.hosts is required but it could not be found in any config source
java.util.NoSuchElementException: SRCFG00014: The config property redis.password is required but it could not be found in any config source
java.util.NoSuchElementException: SRCFG00014: The config property redis.port is required but it could not be found in any config source
Am I missing something here? Everything seems to be set correctly.
Related
i've been working with Spring for some time and have a question regarding the very common configuration properties files (like the common application.properties that comes with every spring boot app you initialize). Recently, i also found that configurations like this can be done in yaml files. I have two questions:
When in a application.properties file, we write something like:
# application.properties
spring.debug = true
some-random-value = 15
does this mean that these values will be injected in the application context?
When we write something like:
# application.properties
spring.debug = true
does this mean, that somewhere, there is some class, that has an attribute that looks something like this? -->
#Component
class SomeClass{
#Value("spring.debug")
boolean shouldIRunInDebugMode;
...
}
2.a. If the answer to question 2 is yes, then how can I, looking at something like this:
# application.properties
spring.debug = true
find that class that is expecting that value. The same would apply to if i was looking at something like:
# application.yaml
someThidPartyLibraryName:
shouldWeLog: true
If i see a yaml configuration file, just looking at all the configuration there usually is not enough for me to know what is happening. How can i find the class that is being affected by this configuration, so that i can better understand what this config is doing?
Thank you!
The response is generally yes. If you declare a property in the application.properties or application.yaml is mainly, because you would use it later in the code, for example injecting in some bean with the support of #Value annotation. However, there are also many built-in properties (let's say for example server.port), which you usually don't have to declare and therefore you won't see explicitly in the code. Use an IDE to search the configuration properties and the manual to check the preconfigured ones in case of need.
Your understanding regarding spring value injections from application.properties is correct. #2 - is Yes. Any property from application.properties can be injected to any java class as #Value.
Regarding #2.a - Yaml is just another format on how you organize your variable hierarchy by indentations. That's a superset to the JSON structure.
For example,
in application.properties file you can add something like this
myapp.db.url=<dburl>
myapp.db.username=<dbuser>
myapp.db.password=<dbpassword>
the same can be represented in Yaml in a much efficient manner as below
myapp:
db:
url:<dburl>
username:<dbuser>
password:<dbpassword>
And in either case, for your Jave file you can inject as
#Value("myapp.db.url"
private String dbUrl;
Properties defined in yaml or a properties file may be accessed using the #Value annotation to inject, or using a #ConfigurationProperties class - see https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-typesafe-configuration-properties for complete details.
Finding the property usage is supported by some IDEs - IntelliJ allows you to click through. Otherwise it's a search through the source. For #ConfigurationProperties, once you find the class then just look for code that calls its accessor methods.
Properties files and yaml files are used in Spring Boot for configurations. The main difference between the two is yaml provides structuring/grouping of configurations where as Properties are usually flat and may be repeating the same information:
For example;
Properties file
server.port = 8080
server.host = localhost
yaml file
server:
port: 8080
host: localhost
But in a Spring Boot AutoConfiguration class regardless of yaml or Properties used, a following looking ConfigurationProperties class will be used which will map server.port and server.host
#ConfigurationProperties(prefix = "server")
public class ServerConfiguration {
private int port;
private String host;
}
#Configuration
#EnableConfigurationProperties(ServerConfiguration.class)
public class ServerAutoConfiguration {
}
Hope this answers your questions.
I'm having this problem with HikariCP and MySql in my maven project: a warning shows up saying:
Loading class 'com.mysql.jdbc.Driver'. This is deprecated. The new driver class is 'com.mysql.cj.jdbc.Driver'. The driver has automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
I want to get rid of this warning.
For that, I need to know why even having the maven MySql connector in its latest version and HikariCP configuration set to set the class com.mysql.cj.jdbc.Driver (which is the non-deprecated one) this warning still shows up.
Here it is the maven dependency in pom.xml:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
Then, I have this properties file called hikaricp-hibernate.properties
jdbcUrl=jdbc:mysql://localhost:3306/local_database
driverClassName=com.mysql.cj.jdbc.Driver
#user and password and other data omitted
Now, for the HibernateConfiguration I have:
package mypackage;
// ... imports
#Configuration
#EnableTransactionManagement
public class HibernateConfig {
private static final String HIBERNATE_PROPERTIES = "/hikaricp-hibernate.properties";
#Bean(name = "hikariDataSource")
public DataSource dataSource() {
HikariConfig config = new HikariConfig(HIBERNATE_PROPERTIES);
HikariDataSource dataSource = new HikariDataSource(config);
return dataSource;
}
}
In the same class, I register as beans the LocalSessionFactoryBean and the TransactionManager, but the code does not matter here.
I also already checked the configuration in debug mode to see if the driverClassName is the one I have put and the answer is yes.
Therefore, the logs are shown even if registered correctly.
Also, HikariCP docs tells me to use the jdbcUrl configuration:
The MySQL DataSource is known to be broken with respect to network timeout support. Use jdbcUrl configuration instead.
Why?
Does jdbcUrl configuration triggers automatically the old Class (if yes, how can I override and avoid this?)? And then it seems that it is deprecated and searches for another one? Does it ignore my driverClassName config?
There's no issue with the code that's here - the key points being:
You're listing a dependency on the 8.* branch of the mysql connector, which contains the new JDBC driver
You're listing the new driver under driverClassName in your properties file
You're instantiating the HikariConfig correctly, with the properties that you're defining.
If the old driver is being loaded, it therefore isn't in this code - it's either with a separate application, or somewhere else in this application.
I am following Spring documentation to use profile specific property files for my SpringBoot app. I have 2 property files under src/main/resources : datasource.properties for local development and datasource-prod.properties for server datasource config.
This is my DataSourceConfiguration.java config class :
#Configuration
#PropertySource("classpath:datasource-{profile}.properties")
#Slf4j
public class DataSourceConfiguration {
#Value("${flad.datasource.driver}")
private String dataSourceDriverClassName;
#Value("${flad.datasource.url}")
private String dataSourceUrl;
#Value("${flad.datasource.username}")
private String dataSourceUsername;
#Value("${flad.datasource.password}")
private String dataSourcePassword;
#Bean
public DataSource getDataBase(){
log.info("Datasource URL = {}", dataSourceUrl);
return DataSourceBuilder
.create()
.driverClassName(dataSourceDriverClassName)
.url(dataSourceUrl)
.username(dataSourceUsername)
.password(dataSourcePassword)
.build();
}
}
When I launch my SpringBootApplication main class I get the following error whether I use -Dspring.profiles.active=prod or not :
17:05:49.008 [restartedMain] ERROR org.springframework.boot.SpringApplication - Application run failed
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [fr.payet.flad.core.config.CoreConfig]; nested exception is java.io.FileNotFoundException: class path resource [datasource-{profile}.properties] cannot be opened because it does not exist
The solution that I found is to rename my property files datasource-local.properties and datasource-prod.properties, use #PropertySource this way #PropertySource("classpath:datasource-${profile}.properties") and when I launch my SpringBoot app I use -Dprofile=local as VM options
I am trying to configure the spring-boot application with yml and properties. I might have made mistakes at multiple places :)
I run my application as below with following contents :
java -jar /opt/elast-search-0.0.1-SNAPSHOT.jar --spring.config.location=. --spring.config.name=elast.properties,ere.yml
My YAML file looks like :
log:
count: 1
searchText: someText
services:
- um
- sa
minutesTime: 1
count: 2
searchText: someMoreText
services:
- um2
- sa2
minutesTime: 2
Without the elast.properties file and the second bean content (i.e. from count to the minutesTime section in yaml) I see the yml is loading and I am running it with :
java -jar elast-search-0.0.1-SNAPSHOT.jar --spring.config.location=ere.yml
I am running multiple properties file because I want to have a default configuration as well and the module is still evolving. I have #Autowired the class in the spring boot application.
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "log")
public class LogRule {
private int count;
private String searchText;
private String[] services;
private int minutesTime;
}
I want to read all YAML configuration as a list.
I want to read the configuration file if the file is changed or at regular intervals.
All examples I read related with activeMq and spring-boot has especial property to change the url of broker:
spring.activemq.broker-url=<SOME_URL>
By default it uses default settings: default url and default port.
But I use rabbirMq and I want to know how to change broker url
I've read this one
I've added application.properties to the src/main/resources
with following content(host absolutely wrong, I expected to see error):
spring.rabbitmq.host=olololo
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
But it doesn't affect application.
Looks like spring(boot) doesn't read these prioerties.
P.S.
Project structure looks like this:
Spring Boot does not have auto configuration support for rabbitmq-jms (the link you referenced is the native RabbitMQ AMQP auto configuration).
For the JMS connection factory, you will have to do the configuration yourself...
#Bean
public RMQConnectionFactory connectionFactory(#Value("${spring.rabbitmq.host}") String host,
#Value("${spring.rabbitmq.port}") int port) {
RMQConnectionFactory cf = new RMQConnectionFactory();
cf.setHost(host);
cf.setPort(port);
return cf;
}