Are there other ways to provide `-D` java configs? - java

I have a usecase to provide a logging.properties file to change the log levels. In logging frameworks like, slf4j-simple, we can directly provide the properties file in resources and it will pick it up. But when using slf4j-jdk14 we need to provide the properties file path as a run config.
java -Djava.util.logging.config.file=logging.properties -jar test.jar
I need a way to provide this -Djava.util.logging.config.file=logging.properties config to the jar in another way.
There is also an option as follows,
static {
System.setProperty("java.util.logging.config.file",
"logging.properties");
}
But I want to know, if there is a way to provide this config to jar in any other ways. Maybe specifying this config in another config file which would be automatically picked up.

Related

externalize spring configuration and logs

I need your help on two issues :
1// I have a spring batch app that has this application.properties file :
spring.datasource.username=xxx
spring.datasource.password=xxx
spring.datasource.url=jdbc:oracle:xxxxxxxx
ClassApp=xxxx
Country=xxxxx
spring.batch.initialize-schema=always
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
CRON_EXPRESSION=xxxxx
I want to externalize this configuration to an external file in a specific location and pass it then in the jvm when i run the final jar generated by my application.
Because the jar will be run on a centos machine later and all the variables in the properties file should get their values from that external file !!
How can i do this ?
2// Also, i have some log feature in my app like this one :
log.debug("CreateQuartzJob is running......");
But i want to externalize application logs to an external file also with all execution details too.
How can i make these two features pleaaase ?
Thank you for help :)
As for external configuration, you can use the "additional-location" argument when running your application. Just create a properties or yaml file, e.g., application.yml, and run your jar like this:
java -jar myJar.jar
--spring.config.additional-location=file:/some/directory/application.yml

Using a default log4j2 configuration file from inside the jar

I placed a default log4j2 config file (log4j2.xml) in my application jar.
If the user doesn't define a own config file, I want to load my default config.
I could get a stream of the default config this way:
InputStream defaultConfigStream = MyApp.class.getClassLoader().getResourceAsStream("log4j2.xml");
But that won't help me, because following code takes a full path to the config file to check its existance and to load it.
System.setProperty("log4j.configurationFile", file.toUri().toURL().toString());
How can I accomplish that? I don't want to hardcode my default config settings, like here.
Use a DomConfigurator, see: https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/DOMConfigurator.html, you can parse the XML and feed it to the configurator and when initializing logger it will automatically consider the configuration
As I found out, it's pretty simple. Like described in the documentation (point 7), Log4j2 will automatically look for a log4j2.xml on the classpath.
So if the user doesn't define a own config file, I don't call any method to load my default config.

Condition logging level in Log4j.properties

Is it possible to have conditions in log4j.properties. I have a situation where I want to have logging level set to Info on production environment and DEBUG on local. Is it possible to read environment variables in log4j.properties.
No, you have to have 2 different log4j.properties file
Configuring logging is something that should happen as part of the deployment, not as part of the build, i.e. you should NOT create multiple builds for different log configurations, the risk of introducing also other differences in artifacts is to big.
Create ONE build containing a default configuration, possibly the one you want to use in production.
Implement a way to find and use an alternative configuration without changing your artifact. Most of the time this is achieved by adding an additional directory to the classpath of your application and store a log4j configuration there. You can use the default initialization of log4j by using a configuration format that has higher precedence then the one contained in the artifact. This also allows you to reconfigure logging without new deployment, which can be very helpful when troubleshooting.
Alternatively you can provide the location of the configuration file to use via a environment variable at startup: -Dlog4j.configuration=log4j-prod.xml (borrowed from Keerthi Ramanathan's answer)
You can prepare different builds and decide which log4j.propeties you want to include on build time, for example using maven params, profiles or any other way.
There is no way to declare condition in log4j.properties
No.
But just to outline some other options
a) I would encourage you to have a look at logback which provides a simple facade over log4j and you can then change your config at runtime. The relevant documentation can be found here.
b) If you have a build process in place (ant/maven) you can do the replacement as part of the build process. If you use maven you can set up a profile to build and the in the build-cycle apply filtering
c) Load the log4j files from a conf directory for each environment. The idea for that is that the files once set for an environment are changed minimally over time. You maintain both in your repository and as part of your deployment process ensure that additional/deleted files/props get added/removed.
What i would suggest as said in comment, have a separate version of log4j properties file for every environment and follow the naming convention for easy maintainance. say, for dev environment, it would be log4j-dev.xml and for production, log4j-prod.xml. Now, you can configure the appropriate file to pick up during runtime using
-Dlog4j.configuration=log4j-prod.xml
during server startup. so, that appropriate conffiguration file will be taken by log4j.
You can use programmatic configuration when using log4j, which gives you more control over what options to use in what environment. You can have your own configuration files and use your own logic to convert them into a log4j configuration. The downside is that you need to do init() somewhere in your application. This answer provides good reference.
I used a this approach when I had similar question. A default log level if nothing is explicitly specified, and option to override.
So, I added a log4j.properties file in application resources.
log4j.rootLogger=ALL, stdout
...
log4j.appender.stdout.Threshold=INFO
...
And then added more log config properties (log4j-n.properties, for n in {d, i, w, e}) defining log levels at debug, info, warning and error. Now, during startup I would supply the config file explicitly if I wanted to override the default.
java ... -Dlog4j.configuration=file:///<path>/log4j-n.properties ...
This would override any config I had in the default log4j.properties.
Later I went with this approach. I removed all the extra config files. In the log4j.properties file in resources, I used a JVM arg placeholder:
log4j.appender.stdout.Threshold=${app.log.level}
And supplied that as JVM argument.
java ... -Dapp.log.level=<LOG-LEVEL> ...
Voila!

Setting log4j.properties file for logging in servlets

The server is a simple jetty Server
How to set the log4j.properties file i have a proper log4j properties file,
but while setting the log4j.properties
using the following manner, i have the log4j.properties in my src folder
PropertyConfigurator.configure("log4j.properties");
it works fine when i am working locally, but when i create a jar file and run its throwing an exception like java.io.FileNotFoundException:
i have tried extracting it and created it in another folder called resources and tried accessing that by the following method
PropertyConfigurator.configure("resources/log4j.properties");
even after that its showing the same error
how to export the entire project as a jar file and make this log4j problem to work?
Found another link
Log4j Properties in a Custom Place
and in that it is required to set the class path
java -Dlog4j.configuration=conf/log4j.properties -classpath ...
Do not know how to set the -classpath and dont know whether this method will work!!
And even if its exported as a jar file it should work!
If the log4j.properties resource directory is on the classpath, you could use:
PropertyConfigurator.configure("classpath:resources/log4j.properties");
To see the working directory for Jetty, you could add:
System.out.println(System.getProperty("user.dir"));
before the PropertyConfigurator.configure statement. This would allow you to see where the property file is located in relation to the server's working directory.
In order to make it work immediatley, you can configure them from code:
Properties props = new Properties();
props.setProperty("<KEY>","VALUE");
PropertyConfigurator.configure(props);
Hardcode the props object with all the properties from log4j.properties file.
This is not the solution you ask, but it might very helpful if you are short on time.

Multiple log4j xml files for multiple applications

I have 5 applications which have different log4j xml configuration file. And I want each of them to be configured according to the given file and logs correctly when called from one main method.
Log4j will automatically look for and use config files it finds on the classpath. It looks for files called log4j.properties and log4j.xml and possibly others.
Alternatively you can programatically load config using;
String filename = "/path/to/config/file.xml";
DOMConfigurator.configure(filename);

Categories

Resources