How to set spring bootstrap.properties at execution time - java

Is it possible to set the contents of Spring's bootstrap.properties at execution time?
I have a client application for Spring's cloud config which holds a line to point to the config server:
spring.cloud.config.url = http://localhost:8888
And I would like to set this config. I tried setting it like application.properties can be set:
java -jar ./config-client.jar --spring.cloud.config.url=http://localhost:8888
But it didn't work. So my question is, how can I set this property at execution time?

It seems to be caused by wrong properties name. url should be uri.
Try to change your property in bootstrap.properties like below.
spring.cloud.config.uri = http://localhost:8888
And then try again like below.
java -jar ./config-client.jar --spring.cloud.config.uri=<something else>
http://localhost:8888 is the default value of spring.cloud.config.uri. That's probably the reason why you didn't recognize the wrong property name.

Related

Spring boot - How to provide environment variables to app context to avoid unit test failure

I have a spring boot REST API app. I am using environment variables in application.properties file. Some settings are as shown below:
logging.level.springframework.web=${WEB_LOG_LEVEL}
logging.level.org.hibernate=${HIBERNATE_LOG_LEVEL}
In my unit test, I use annocation #TestPropertySource("classpath:application-test.properties"). However, when I run mvn clean install, build fails because of unit test failure. I provided the error log. When I ran in IDE, I can provide those environment vairables. Any suggestions on how to pass them in mvn clean install? Or any other approaches you would recommend? Thanks much in advance!
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to bind properties under 'logging.level.springframework.web' to org.springframework.boot.logging.LogLevel:
Property: logging.level.springframework.web
Value: ${WEB_LOG_LEVEL}
Origin: class path resource [application.properties] - 44:35
Reason: failed to convert java.lang.String to org.springframework.boot.logging.LogLevel (caused by java.lang.IllegalArgumentException: No enum constant org.springframework.boot.logging.LogLevel.${WEB_LOG_LEVEL})
Action:
Update your application's configuration. The following values are valid:
DEBUG
ERROR
FATAL
INFO
OFF
TRACE
WARN
We have many options!
Best is we (roughly) understand the 2 Externalized Configuration and PropertySource:
Leaving our application.properties as it is, we can:
(As tgdavies commented), introduce src/test/resources/application...
Here we can:
call it application.properties, and it will override (existing settings/"sensible") of src/main/resources/application.properties, then we don't need #PropertySource or #Profiles on our test.
call it application_test.properties, then work rather with #Profile("test") + #ActiveProfiles("test") (on our test class(es), with even higher precedence as the above).
don't use #PropertySource (some_custom_name.properties file) for this use case, it has too low precedence!
...in these properties we will write (without placeholders):
logging.level.springframework.web=warn
logging.level.org.hibernate=warn
# or the log level(s) of our choice, overriding(!) the "main ones"
SET/EXPORT these properties in our (dev) environment! (with our cli/OS dialog/MAVEN_OPTS/...)
Using #TestPropertySource (2nd highest precedence, in spring-boot configuration hierarchy!, no profiles):
like (override property):
#TestPropertySource(properties = "logging.level.springframework.web=warn", ...)
or (using/trying relaxed binding):
#TestPropertySource(properties = "web.log.level=warn", ...)
or (using a file):
#TestPropertySource(locations = "classpath:/some/properties.properties", ...)
But a slight modification of our (src/main/...)application.properties can also be very helpful: Fallback! - looks like:
logging.level.springframework.web=${WEB_LOG_LEVEL:warn}
logging.level.org.hibernate=${HIBERNATE_LOG_LEVEL:warn}
It tries for the environment variables, and falls back to warn. With this, we can omit #PropertySource/#Profile and/or an additional test-application-properties.
And even better with relaxed binding:
logging.level.springframework.web=${web.log.level:warn}
logging.level.org.hibernate=${hibernate.log.level:warn}
This will accept the above environment variables, but also (previously defined)"properties" + fall back to "warn".
Conflict-free combinations of the proposed.
... -> Chapter 2, Relaxed Binding(, Profiles!) and Spring Boot How To: Properties and Configuration.

is it possible to refer environmental variable as values for properties in the kafkaProducer.properties and KafkaConsumer.properties files of Kafka

Im have a producer and consumer java code and Im trying to upgrade it to connect with the Kafka which is secured with SSL. I'm in a situation that the ssl related passwords should be given only via environmental variables.
So is it possible to directly refer to the values refered by Environmental variables in the KafkaProducer.properties and KafkaConsumer.properties files
For Example:
I declare an environmental variable in linux system SSL_KEY_PASSWORD=password
And inside the KafkaProducer/Consumer properties, I declare as,
''' ssl.key.password=${SSL_KEY_PASSWORD} '''
Sample KAFKA Consumer/Producer property file config may look like,
# For SSL
security.protocol=SSL
ssl.truststore.location=/var/private/ssl/client.truststore.jks
ssl.truststore.password=${TRUSTSTORE_PASS_ENV_VARIABLE}
# For SSL auth
ssl.keystore.location=/var/private/ssl/client.keystore.jks
ssl.keystore.password=${KEYSTORE_PASS_ENV_VARIABLE}
ssl.key.password=${KEY_PASS_ENV_VARIABLE}
No, they cannot.
Unclear how you are using the files or Kafka clients. If from the shell commands, you should create a bash wrapper around the command you're running that uses sed or other templating scripts that generates the files before running the final command.
If you are actually writing Java code, then build the Properties from the environment there, and not using files.
Don't think properties file values are interpolated but probably you can test it once. Alternatively you can also remove these lines from property file and do it from code something like below...
final Properties properties = new Properties();
final FileInputStream input = new FileInputStream(yourExistingFile);
properties.load(input);
properties.put("ssl.key.password",System.getenv("SSL_KEY_PASSWORD"));//this is additional property

Invalid path of external Kafka keystore and truststore

My app connects to Kafka topic and everything goes well in local environment when truststore and keystore are stored under classpath, but when I try to switch to Dockerized external environment and point to those files localized on a server, then the app crashes.
Snippet in a local environment where it works:
spring.kafka.ssl.trust-store-location=file:src/main/resources/keys/application.truststore.jks
spring.kafka.ssl.key-store-location=file:src/main/resources/keys/application.keystore.jks
Snippet of application.properties on a server side when the app is launched inside a docker container and does not work. Both keys are stored in /deployment/keys folder inside the container:
spring.kafka.ssl.trust-store-location=/deployment/keys/application.truststore.jks
spring.kafka.ssl.key-store-location=/deployment/keys/application.keystore.jks
The following java exception occurs:
NoSuchFileException: /tmp/tomcat-docbase.45456574985379.8080/deployment/keys/application.keystore.jks
So for an unknown reason Spring Boot inside Docker container adds the /tmp/tomcat-docbase.45456574985379.8080/ prefix to the keystore and truststore location.
I have also tried:
spring.kafka.ssl.trust-store-location=file:/deployment/keys/application.truststore.jks
spring.kafka.ssl.key-store-location=file:/deployment/keys/application.keystore.jks
and
spring.kafka.ssl.trust-store-location=file:///deployment/keys/application.truststore.jks
spring.kafka.ssl.key-store-location=file:///deployment/keys/application.keystore.jks
but none of them seem to work. I would not like to change the code but what comes to my mind is to create a Properties object and create strings with those paths. Then inject them to the KafkaTemplate as a bean. However, I have not yet checked if this could help. Would rather focus just on adjusting application.properties file than correct the code. Could you please help me find the solution?

Default value for application.properties (profile) environment placeholder cannot be comma separated

I have the following property in my application.properties.
spring.profiles.active=dev,local
This works fine. However, I decided to also expose this as an environment variable and keep dev,local as the default values. However the following does not work.
spring.profiles.active=${PROFILES_ACTIVE:dev,local}
It seems comma causes this issue.
Checking the logs
[2018-05-24 05:38:28.163] [main] [INFO] [Application] The following profiles are active: ${PROFILES_ACTIVE:dev,local}
However, the following works.
spring.profiles.active=${PROFILES_ACTIVE:dev}
Any suggestions on how go about this?
Try:
spring.profiles.active=${PROFILES_ACTIVE:#{'dev,local'}}
It uses the EL syntax with templating.

override values in application.properties files from command line

I have apllication.properties files in java web application which contains these properties.
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:19095/test
spring.datasource.username=test
spring.datasource.password=test123
But I want to override these properties (except driverClassName) while starting tomcat server.
I'm trying to set these variables from command line, but it's not working.
tomcat version : 7.0.63
Why don't you use a property placeholder with config directory specified by a system parameter:
<context:property-placeholder location="file:${configLocation}/database.properties:defaultDatabase.properties" />
Then start the tomcat with:
-DconfigLocation=/opt/config
see http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/PropertySource.html and also Loading property file from system properties with default path in Spring context

Categories