tokenize application.conf in play java app - java

I want to tokenize a few keys in my application.conf file to use variables from another properties file. How can I do so? Here is an example.
my-play-project/conf/application.conf
db.default.url=${env.db.url}
db.default.driver=${env.db.driver}
db.default.user=${env.db.user}
db.default.pass=${env.db.password}
my-play-project/conf/env/devlab/project.properties
db.url=myoracleserver.lab.org:1521
db.driver=oracle.thin
db.user=myname
db.password=mypassword
my-play-project/conf/env/devlab2/project.properties
db.url=myoracleserver2.lab.org:1521
db.driver=oracle.thin
db.user=myname
db.password=mypassword
Q. Is there a way to set devlab/project.properties to be part of system resolvable properties?

Play's configuration uses Typesafe Config. There are several ways of combining configuration together on the classpath and at runtime.
Creating multiple application.conf and application.properties files and putting them all on the classpath (i.e. in different JARs). The configuration will be combined. See Standard Behavior.
Using includes to pull in files with different names.
Using substitutions to pull in values from other config files.
Using substitutions to pull in environment variables or system properties.

Related

Java Microprofile change properties on already deployed app (Wildfly)

I have an ear artifact deployed on a wildfly server. On some beans I used the following configuration injection
#Inject
private Config config;
I want to change the properties specified on the "microprofile-config.properties" file on runtime. It is not necessary to change the file itself, I just want to change the properties. I think there might be a way using the console, but I cannot find if there is any.
If you take a look at the spec or even at articles like this, you will see that, by default, Microprofile config reads configuration values from the following 3 places in this order - i.e. from wherever it finds it first:
System.getProperties()
System.getenv()
The configuration file
So, you can override values in the configuration file in 2 ways:
Defining -D command line arguments to the VM (e.g. java -DXXX=yyy ...)
Defining system environment variables (e.g. export XXX=yyy in bash or set XXX=yyy in Windows)
Note that there are some rules for defining environment variables and matching them to actual configurations, e.g. for a configuration aaa.bbb.ccc you may need to set an environment variable as AAA_BBB_CCC. Read ch. 5.3.1 in the specs, and experiment a little.
You can always extend the configuration sources with your own custom ones (to read configuration from JNDI, DB, Zookeeper, whatever).

Disable spring-context-indexer by profile

I want to enable Spring Context Indexer on a project but I am having issues with Swagger3 (check here and here).
I understand the limitations and would like to enable it, at least, at the DEV profile where we do not need Swagger running.
My goal is to disable indexing on PROD environment. From docs:
you can fallback to a regular classpath arrangement (as though no index was present at all) by setting spring.index.ignore to true, either as a system property or in a spring.properties file at the root of the classpath.
My first approach (without success) was setting an env var (Windows 10) with the following:
SPRING_APPLICATION_JSON={"spring":{"index":{"ignore":true}}}
If I create a spring.properties file and set the value accordingly it works. But I can't figure how to use different properties for each profile, I imagined it was something like the application.properties file but I was wrong.
How can I achieve that?
EDIT:
Just to be clear, this config (spring.index.ignore) will just work if inside a spring.properties file, not an application.properties one. (Just double-checked before this edit)
Actually I have one application-prod.properties and one application-dev.properties.
I don't know the difference between spring.properties and application.properties but the first one doesn't seem to work with multiple profiles as the later.
Edit 2:
Just went through org.springframework.context.index.CandidateComponentsIndexLoader and it uses SpringProperties.getFlag(IGNORE_INDEX) to read the value.
SpringProperties class is clear about the file it uses:
Reads a spring.properties file from the root of the Spring library classpath, and also allows for programmatically setting properties through setProperty. When checking a property, local entries are being checked first, then falling back to JVM-level system properties through a System.getProperty check.
I think I will need to pass a property to Java runner during initialization. Will research a little bit more about it.
you can use different application.properties file as follow:
add the following files to the resource folder:
application.properties
spring.profiles.active=dev #place profile name you want to use
application-dev.properties
#dev properties
...
You can create many application-env.properties you may wish
application-env.properties
#env properties
...
Spring Boot supports profile-specific properties files. You have to name these files with the following format: application-{profile}.properties. You can activate a profile via JVM system parameter: -Dspring.profiles.active=dev. You can read more about this subject here: https://www.baeldung.com/spring-profiles

Multiple profiled properties configuration in Spring-boot 2

I have a spring-boot 2.1.3.RELEASE application with multiple properties files.
In my /src/main/resources I have my-app.properties and profiled my-app-local.properties.
Also, outside the project I have another profiled properties file /config/my-app-local.properties.
The point of this configuration is to have the following properties hierarchy:
/resources/my-app.properties
/resources/my-app-local.properties
/config/my-app-local.properties
So when I try to run the application with the following parameters:
--spring.profiles.active=local --spring.config.name=my-app --spring.config.location=config/my-app.properties
the application fails to start because it can't find any properties files.
However, this configuration and parameters worked perfectly on spring-boot 1.5.19.RELEASE. How can the same be achieved in spring-boot 2?
use spring.config.additional-location doc
When custom config locations are configured by using spring.config.location, they replace the default locations. For example, if spring.config.location is configured with the value classpath:/custom-config/,file:./custom-config/, the search order becomes the following:
file:./custom-config/
classpath:custom-config/
Alternatively, when custom config locations are configured by using spring.config.additional-location, they are used in addition to the default locations. Additional locations are searched before the default locations. For example, if additional locations of classpath:/custom-config/,file:./custom-config/ are configured, the search order becomes the following:
file:./custom-config/
classpath:custom-config/
file:./config/
file:./
classpath:/config/
classpath:/

How to use multiple configuration files for Log4j2?

I am writing Java code that tests a Java library. The library includes its own Log4j2 configuration as part of the distribution.
I would like to use Log4j2 in my test code without modifying the library's configuration.
Is there a way to have a separate Log4j2 configuration for my test code?
This is all running as command-line Java, no servers or web involvement at all.
EDIT
What I want is to be able to configure loggers, appenders, etc for the test code to use, and at the same time have the library code use its own separate configuration file for its logging.
The idea is to use Log4j2 in my test code, but without having to change the library's configuration file. Since the library configuration file is part of the library's distribution, I don't want to change it for testing.
This may be helpful:
Log4j2 will first look for log4j2-test.xml in the classpath
if that file is not found, it will look for log4j2.xml in the classpath
So one option is to copy the library's configuration (log4j2.xml) to log4j2-test.xml and add your own configuration to log4j2-test.xml.
Furthermore, Log4j2 supports XInclude in XML configuration, so you could use that feature to avoid duplicating the library's configuration in your log4j2-test.xml.
Log4j2 supports "Composite Configuration" which exactly matches your requirement. All you need to do is provide path to multiple files in log4j.configurationFile property. This can be passed from command line or added to log4j2.component.properties file in your application.
References
https://logging.apache.org/log4j/2.x/manual/configuration.html#CompositeConfiguration
https://logging.apache.org/log4j/2.x/manual/configuration.html#SystemProperties
There are two step you can try to solve for your issue
Create your own configuration file with your custom name(eg: xyz.properties/.xml)
You must add the following line to your java runtime command
cmd> java -Dlog4j.configuration=location/xyz.properties
If you use diffent name for configuration rather log4j.properties/.xml file you need to configure that file at runtime by above command for more info have a look here..
Correct format for using an alternate XML file to log4j2.xml:
java -Dlog4j.configurationFile=./location/log4j2-custom.xml
Assuming ./location/log4j2-custom.xml exists and is the new XML to replace log4j2.xml in this run
See:
https://github.com/kamalcph/Log4j2Examples/blob/master/src/main/java/in/co/nmsworks/log4j2/examples/CompositeConfigurationExample.java
Referencing https://logging.apache.org/log4j/2.x/manual/configuration.html states that you can add multiple comma separated files under log4j2.configurationFile property.
To use multiple configuration files, depending on the environment you must set the.
for example:
if (env.equals("DEV")) {
setConfigFile("log4j2-dev.xml");
}
public static void setConfigFile(String logConfigFile) {
File file = new File(logConfigFile);
LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
context.setConfigLocation(file.toURI());
}
first configure application.yaml file
spring:
profiles:
active: dev
---
spring:
message: running in the dev profile //just to output the message in the log
profiles: dev
logging.config: classpath:log4j2-dev.xml
---
spring:
profiles: prod
logging.config: classpath:log4j2-prod.xml
and create these similar files in your classpath
* log4j2-dev.xml
* log4j2-prod.xml

Play Framework - How to keep the configurations of my module inside it?

I am using Play Framework 2.2.x/Java.
I want to create a module to sperate some of the logics from my main application and also I want to use the application.conf inside the module for its configurations instead of using the main application's config file!
But using the following snippet in the module, only reads values from the main application config file:
Play.application().configuration().getString("myVar");
Is there any other way to get the values from the application.conf file inside my module?
Play uses the typesafe-config library for reading configuration. This is actually a Java library, even though Typesafe is a Scala company.
The documentation for typesafe-config says "The idea is that libraries and frameworks should ship with a reference.conf in their jar."
So your module's config should be stored in a file called reference.conf - the format is exactly the same, it's just the name that is different.
The problem occurs because there is a conflict between the two config files because they are named the same, so it probably goes by classpath order or something. Don't use two application.conf files - this problem has bitten me in the past!
Save your config into ie. /conf/my-module.conf of the main app and then include it at the end of application.conf like:
include "my-module.conf"

Categories