My java application references a 3rd-party jar file which uses log4j logging. The problem is that this jar contains its own log4j.properties file which causes access denied exceptions on my machine, but I don't have control over the jar file to change its contents.
I have tried adding my own log4j.properties file in my application's classpath, but it doesn't seem to have an effect. If I try to use PropertyConfigurator to import my own settings programmatically, log4j seems to load the jar file's properties file first (causing an exception).
How can I short-circuit log4j to ignore a 3rd-party jar file's log4j.properties file and use my own?
There are several way to override log4j.properties, one of them is:
Use log4j.xml please see the extension
Another approach is:
Setting the log4j.defaultInitOverride system property to any other value
then "false" will cause log4j to skip the default initialization procedure (this procedure).
Set the resource string variable to the value of the log4j.configuration system property. The preferred way to specify the default initialization file is through the log4j.configuration system property. In case the system property log4j.configuration is not defined, then set the string variable resource to its default value "log4j.properties".
Attempt to convert the resource variable to a URL.
If the resource variable cannot be converted to a URL, for example due to a MalformedURLException, then search for the resource from the classpath by calling org.apache.log4j.helpers.Loader.getResource(resource, Logger.class) which returns a URL. Note that the string "log4j.properties" constitutes a malformed URL. See Loader.getResource(java.lang.String) for the list of searched locations.
If no URL could not be found, abort default initialization. Otherwise, configure log4j from the URL. The PropertyConfigurator will be used to parse the URL to configure log4j unless the URL ends with the ".xml" extension, in which case the DOMConfigurator will be used. You can optionaly specify a custom configurator. The value of the log4j.configuratorClass system property is taken as the fully qualified class name of your custom configurator. The custom configurator you specify must implement the Configurator interface.
Ref: http://logging.apache.org/log4j/1.2/manual.html
If none of these works
Add this following statement in your app configuration
BasicConfigurator.configure();
it worked for me
Try adding an environment variable called LOG4J_CONFIGURATION_FILE while you start the application.
Related
Where can i store SLF4J configuration file so that all production and test environment may have access to it? I want to store the config file outside of the web app at an arbitrary location and retrieve that location upon startup. I also want to allow for changing location of the config file so no classpath. Im thinking about using getters and setters to retrieve the file path.
Any ideas??
slf4j is (for all practical purposes) just the API. You need a backend which does the actual work.
If you use logback you can ship a logback.xml file with your application which just includes another file. If I recall correctly the filename string can hold a ${variable} which you can then define outside your application.
See https://logback.qos.ch/manual/configuration.html#configFileProperty
You may specify the location of the default configuration file with a system property named "logback.configurationFile". The value of this property can be a URL, a resource on the class path or a path to a file external to the application.
java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1
I have a library (non- executable) jar file and I need to place the log4j.properties outside the jar.
In executable jar files, I can pass the path through -Dlog4j.configuration. But how can I do it in this case?
From https://logging.apache.org/log4j/1.2/manual.html:
The exact default initialization algorithm is defined as follows:
Setting the log4j.defaultInitOverride system property to any other value then "false" will cause log4j to skip the default initialization procedure (this procedure).
Set the resource string variable to the value of the log4j.configuration system property. The preferred way to specify the default initialization file is through the log4j.configuration system property. In case the system property log4j.configuration is not defined, then set the string variable resource to its default value "log4j.properties".
Attempt to convert the resource variable to a URL.
If the resource variable cannot be converted to a URL, for example due to a MalformedURLException, then search for the resource from the classpath by calling org.apache.log4j.helpers.Loader.getResource(resource, Logger.class) which returns a URL. Note that the string "log4j.properties" constitutes a malformed URL.
See Loader.getResource(java.lang.String) for the list of searched locations.
If no URL could not be found, abort default initialization. Otherwise, configure log4j from the URL.
The PropertyConfigurator will be used to parse the URL to configure log4j unless the URL ends with the ".xml" extension, in which case the DOMConfigurator will be used. You can optionaly specify a custom configurator. The value of the log4j.configuratorClass system property is taken as the fully qualified class name of your custom configurator. The custom configurator you specify must implement the Configurator interface.
You can use PropertyConfigurator.configure to initialize log4j and specify the path to your log4j.properties via a system property, another config file, an environment variable, etc.
However, you may not want to have a separate logging mechanism/configuration for your JAR instead of letting it use the one(s) from the application(s) calling it.
I've looked all over the documentation, but was unable to find one. How can I achieve this?
According to the Audit4j documentation and javadoc there are multiple ways to specify the configuration:
It can be injected into the Context directly by calling static methods of the Context class (e.g. at application startup before doing any audit!):
Context#initWithConfiguration(Configuration configuration) with the appropriate Configuration
or Context#initWithConfiguration(String configFilePath) to specify the configuration as file.
Other ways to specify the path to the configuration file without manually initializing the Context are:
Setting path in environment variable "AUDIT4J_CONF_FILE_PATH"
Setting path in Java system property variable "audit4j.conf.file.path"
Also the configuration file can be put into the application classpath or the user directory. In this case the name of the configuration file has to be "audit4j.conf.yml" or "audit4j.conf.yaml" for YAML style or "audit4j.conf.xml" for XML style.
I'm having difficulty trying to override a property declared in a profile-specific application properties file on the classpath with another value declared in an overrides file on the file system.
I have an auto-configured Spring-boot application (that is, using #EnableAutoconfiguration) that has multiple profiles, which I launch using PropertiesLauncher rather than JarLauncher (the reason having to do with deployment constraints - I need to deploy an exploded directory rather than an archive into a read-only filesystem.)
Within the root of my application, I have some profile-specific application properties, for example:
application-dev.properties
application-qa.properties
application-prd.properties
And let's say, for the sake of argument that application-dev.properties contains:
foo.bar=baz
foo.baz=other
For any environment, it may be necessary to override an existing property, as well as supply an absent one (like a production password, for example), and the issue I'm seeing is with overriding properties already declared in an application-${profile}.properties file on the classpath. (Supplying properties not present in the classpath file works fine, this is not the issue.)
Say I have an overrides properties file in a file system location such as:
/local/appname/dev/overrides/application.properties
and I want to override the property, foo.bar, as well as declare a new property, foo.password.
Therefore the contents of the overrides file are:
foo.bar=overridden-value
foo.password=something
When I launch the application, I use a command line something like this:
java -Dspring.config.location=file:/local/appname/dev/overrides/
-Dspring.profiles.active=dev
org.springframework.boot.loader.PropertiesLauncher
--debug &
The issue I am seeing is that although foo.password, the property not declared in the application-dev.properties file is picked up, the override of foo.bar is ignored - I still see the value, baz from application-dev.properties rather than the value, overridden-value from /local/appname/dev/overrides/application.properties.
With the --debug option enabled, I can see the ConfigFileApplicationListener logging that it has loaded both the overrides file (from the filesystem) and the profile-specific file (from the classpath), in that order.
I'm tempted into the perhaps naïve conclusion that because the overrides file is listed first, it is being loaded first then overridden by the 'default' profile-specific file from the classpath, which is listed later. I do appreciate however, that order of listing in the log doesn't necessarily correlate with behaviour. And I have tried varying the order of paths declared on the spring.config.location property, so that classpath: is listed before file:... but this hasn't helped and I't not convinced it would anyway, given that the Spring-boot documentation clearly states that the default properties locations are always searched even if you supply a value for spring.config.location.
The Spring-boot documentation is very specific about the order that properties are resolved for a Spring-boot executable JAR, in descending order of precedence:
Command line arguments.
Java System properties (System.getProperties()).
OS environment variables.
JNDI attributes from java:comp/env
A RandomValuePropertySource that only has properties in random.*.
Application properties outside of your packaged jar (application.properties including YAML and profile variants).
Application properties packaged inside your jar (application.properties including YAML and profile variants).
#PropertySource annotations on your #Configuration classes.
Default properties (specified using SpringApplication.setDefaultProperties).
Take note of lines 6 and 7 - properties outside over properties inside your jar.
What's not stated, as far as I can see, and which may be the source of my confusion/issue, is what happens when you're not using a JAR but an exploded directory (and therefore PropertiesLauncher.)
If the behaviour of an exploded directory were consistent with what's stated for a JAR, I'd expect that the values of properties declared in /local/appname/dev/overrides/application.properties would override any of the same name declared in classpath:application-dev.properties, but this doesn't seem to be the case.
Also noted from the Spring-boot documentation (appendix C.4 on PropertiesLauncher) is mention of the loader.home property, which is described as '... [the] Location of additional properties file, e.g. /opt/app (defaults to ${user.dir})'.
So I tried using loader.home instead of spring.config.location, but to no avail.
(Update: I also tried using loader.config.location and I have two notes: it seems to want a file rather than a directory (so its behaviour is not analogous with spring.config.location), and when I did supply a file path rather than the parent directory, it still didn't help.)
Can anyone spot what I'm doing wrong, or what incorrect assumption(s) I'm making?
Thanks, Dave, your suggestion was 100% correct.
If I rename the properties file in /local/appname/dev/overrides to application-dev.properties then the property values from that file do override the ones in classpath:application-dev.properties.
I was sure I had tried this combination yesterday, but I think what must have stopped it working was when I was playing around with specifying the spring.config.location and got that wrong so it wasn't looking for the override file in the right place.
I am using log4j to log information in my web application. I have chosen log4j.xml type of configuration instead of log4j.properties. I remember that, for log4j.properties configuration, I did not write Java code lines to find the log4j.property file location. However, for log4j.xml file configuration I am specifying explicitly to find it like this
DOMConfigurator.configure("log4j.xml");//it reads file from classpath, working!
Also, tested my application removing the above statement from source. It doesn't see to work. None of the debug statements were printed except
System.out.println();
I have read that log4j by default looks for log4jproperties file or log4j.xml file in the classpath. I checked in the deployed web application, log4j.xml file is in web-inf/classes.
Even though it can't find log4j.xml.
Is it that, the above code line is mandatory for log4j xml configuration in Java?
In fact, can't Java source code doesn't pickup log4j.xml from the classpath without explicit specification as above?
From log4j manual:
The exact default initialization algorithm is defined as follows:
Setting the log4j.defaultInitOverride system property to any other value
then "false" will cause log4j to skip the default initialization
procedure (this procedure).
Set the resource string variable to the value of the log4j.configuration system
property. The preferred way to specify the default initialization file
is through the log4j.configuration system property. In case the system
property log4j.configuration is not defined, then set the string variable
resource to its default value "log4j.properties".
Attempt to convert the resource variable to a URL.
If the resource variable cannot be converted to a URL, for example
due to a MalformedURLException, then search for the resource from the
classpath by calling org.apache.log4j.helpers.Loader.getResource(resource, Logger.class)
which returns a URL. Note that the string "log4j.properties"
constitutes a malformed URL. See Loader.getResource(java.lang.String) for the list of searched locations.
If no URL could not be found, abort default initialization. Otherwise, configure log4j from the URL. The PropertyConfigurator will be used to parse the URL to configure log4j unless the URL ends with the ".xml" extension, in
which case the DOMConfigurator will be used. You can optionaly specify
a custom configurator. The value of the log4j.configuratorClass system
property is taken as the fully qualified class name of your custom
configurator. The custom configurator you specify must implement the
Configurator interface.
So, without code, you can (and should!) define the system property to tell where your config file is. If not, it by default will search for log4j.properties in the classpath. That is the only file it is searching for by default.
System property is usually defined as a startup parameter for your app (app server), something like -Dlog4j.configuration=path/to/your/config.xml.