How to have env specific log4j2 config for spring boot2 application - spring

Currently spring boot seems to support only classpath based logging configuration.
It also ignores any configuration passed as vm argument as follows.
-Dlog4j.configurationFile=/opt/xyz/log4j2-prod.xml
How can we have different log4j2 configuration based on different environment, considering classpath for all environment remains same.

What about set the properties: logging.config=classpath:log4j2-dev-spring.xml in each application-{profile}.properties that you have. Can use like this too: logging.config=${ENV_VAR}

You should use the following param
-Dlogging.config='/path/to/log4j2.xml'

Related

Quarkus: How to define and read properties file (or application.properties) outside application or at runtime?

In Quarkus, We have properties file inside project itself called application.properties.
Is there any Quarkus way to define external properties file in my use case like i am developing a mail sender and i want to add recipients in future.
Is it possible to give application.properties outside at local and inject it at runtime?
You can add a configuration file in your application working directory under config/application.properties : https://quarkus.io/guides/config#overriding-properties-at-runtime
There is ongoing discussion to have more runtime configuration capabilities here: https://github.com/quarkusio/quarkus/issues/1218
You can achieve this by keeping .properties (or .yaml) in Spring Cloud Config Server.
It's really easy to set it up. It's is well documented in following link (official documentation):
Quarkus - Reading properties from Spring Cloud Config Server
As loïc says, you can follow the convention and create a config/application.properties. You can also use the property quarkus.config.locations to specify additional config locations. It can be defined at runtime like below
java -Dquarkus.config.locations=app-config/config.properties -jar my-app.jar

logging.path to ${LOG_PATH}

I am setup to use logback with my SpringBoot application and everything is running fine and dandy.
I noticed a property called logging.path in the application.properties file which sets the value for ${LOG_PATH} in logback.xml. How does it do it?
I went through the SpringBoot logging documentation.
Any documentation I could find on property placeholder configurer
Yet I don't understand how logging.path could pass the value for ${LOG_PATH}. Though not a killer issue, I would like to know how this mapping is made.
The magic is spring will transfter logging.path into System propeties LOG_PATH.
Description from spring doc:
To help with the customization some other properties are transferred from the Spring Environment to System properties:
And it also says:
All the logging systems supported can consult System properties when parsing their configuration files. See the default configurations in spring-boot.jar for examples.
Details:
https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/htmlsingle/#boot-features-custom-log-configuration
For more recent versions of Spring Boot, such as 2.5.x, the logging.file.path maps to LOG_PATH.

Spring Cloud Config dual bootstrap files behavior

I have a setup where I am using the following:
Spring Boot 1.5.13 with Spring Cloud Version Edgware.S3
I have Spring Cloud Config Server and my Spring Boot apps are its clients
Each app carries a bootstrap.yml with the config server uri and some other properties.
Running containers on a Docker Swarm
I am currently passing Swarm secrets to the clients via a custom script which reads the files put into /run/secrets/ and creating a /config/bootstrap.properties file. It ends up looking like this:
spring.cloud.config.username=user
spring.cloud.config.password=password
My Docker image's default command is then this:
java -Djava.security.egd=file:/dev/./urandom -jar /${appName}.jar --spring.cloud.bootstrap.location=file:/config/bootstrap.properties"
Great. This is working without a problem. The app, seemingly, reads:
The external bootstrap.properties to read in the config server's credentials
The classpath bootstrap.yml to read in the rest of the config client props
Fetches and reads in the config server's application-appName.yml
Then reads the bundled application.yml from the classpath
Now. I'm moving the apps to Spring Boot 2.0.3 with Finchley.RELEASE and well, this breaks.
What is happening now is:
The external bootstrap.properties is read in to get the config server's credentials
The classpath bootstrap.yml is SKIPPED entirely (UNEXPECTED!)
Fetches and reads in the config server's application-appName.yml
Then reads the bundled application.yml from the classpath
The problem is that the properties that were set in the internal bootstrap.yml are now missing for the app so it blows up on start. I've been able to reproduce it outside the container environment by doing the same thing; point the app to an external bootstrap.properties. If I copy over the bootstrap.yml properties into the bootstrap.properties, then it works just fine. Also, if I don't provide an external properties file, then the internal bootstrap.yml kicks in without a problem. So it's either one or the other!
I'v also tried modifying the bootstrap location to include the default locations but no luck:
-- spring.cloud.bootstrap.location=file:/config/bootstrap.properties,classpath:,classpath:/config,file:,file:config/
Any ideas where to look next? Maybe there is a new spring.cloud.config property I'm missing? Or can anyone confirm which behavior is the correct behavior? Assuming they fixed a potential loophole in Finchley then I can just put this to rest and look for another solution. If it's 'broken' in Finchley, I guess an issue report is in order?
Well, some more digging showed that it looks like this is the new behavior:
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide
The behavior of the spring.config.location configuration has been fixed; it previously added a location to the list of default ones, now it replaces the default locations. If you were relying on the way it was handled previously, you should now use spring.config.additional-location instead.
It didn't look to be Spring Cloud specific but I had nothing to lose.
Changing my java command to use this new property did the trick:
--spring.config.additional-location=file:/config/bootstrap.properties
Thanks.

How to configure Spring Session Redis redisNamespace at runtime

I'm using Spring Boot 1.3.6 and Spring Session and Redis as the Session store. I need to be able to set the redisNamespace for the application a runtime, and not hard-code it in the code. That means I cannot use #EnableRedisHttpSession since that is not something I can set via the applaction.yml file.
I've updated Spring Session to 1.2.1.RELEASE to get the support I need, but I cannot seem to get the system to configure the namespace via configuration. I tried using a SPEL in the #EnableRedisHttpSession(redisNamespace) call, but that doesn't work. I tried to have the RedisHttpSessionConfiguration injected via Autowired to set it as well, and that seemed to have been ignored. There was also another reference in another SO post about using spring.session.redis.namespace as a property in application.yml but that doesn't work.
Any suggestions/tips would be greatly appreciated!
Declaring spring.redis.namespace per the documentation is not enough.
After setting #EnableRedisHttpSession() to #EnableRedisHttpSession(redisNamespace = "${spring.redis.namespace}") it worked.
Per the normal functionality to externalise configuration you can use system environment variables as well, instead of spring.redis.namespace.
Note: In this case spring.redis.namespace corresponds to the application.yaml file that looks like:
spring:
redis:
namespace: ${REDIS_NAMESPACE:foobar}
I simply put a -Dspring.session.redis.namespace=myKeyName to VM arguments.
and it is working fine.
and I'm using spring boot v1.3.5.RELEASE and spring session 1.2.0.RELEASE.

No plain text passwords in Spring Boot’s application.properties

Having something like
security.user.password = plainTextPassword
inside Spring Boot’s application.properties is obviously an anti-pattern as it prevents the code from being pushed to a public SCM. In my non-Spring Boot projects I use
security.user.password = ${myPasswordFromMavenSettingsXML}
and put a corresponding <properties/> reference inside my pom.xml.
Using Maven’s resource filter plugin the passwords are replaced at build time so the application have access to actual plain text passwords after it has been build and deployed.
For some reason Maven’s resource filter plugin does not work in this case. Is there a way to not commit plain text passwords to an SCM and let Spring Boot to insert them at build time?
Spring boot has multiple mechanisms to provided externalized configuration. Some examples are command line arguments, environment variables and also application properties outside of your packaged JAR.
What I usually do:
Locally we configured several environment variables. Most (if not all) IDE's allow you to configure environment variables from within the run configuration.
For example if you don't want to expose the spring.datasource.password property you could set an environment variable called SPRING_DATASOURCE_PASSWORD.
When we deploy on another environment, we usually choose to add another application.properties or application.yml file within the same folder as the application JAR/WAR, since Spring boot picks that up as well.
Another solution is to use Spring cloud since it has a config service which can be used as a microservice to provide configuration. The configuration can be versioned using SCM as well, but you can put it on a separate system that is not connected to your source code.

Resources