Log4j2 configuration file in Java EE project - java

I have simple Maven Java-EE based on Jersey web service in my Eclipse that runs in Windows 10. Project is created from jersey-quickstart-webapp artifact. I'm trying to use Log4j logger, but can't find where to place log4j2.xml file. I was trying to place it together with source code java files, but logger complains regarding configuration file not found. What is the right place to keep configuration file?

Put it into resources directory. Usually, all configuration files are kept there.

According to docs , Log4j2 will look for the configuration file in the following orders :
Log4j will inspect the "log4j.configurationFile" system property and, if set, will attempt to load the configuration using the
ConfigurationFactory that matches the file extension.
If no system property is set the properties ConfigurationFactory will look for log4j2-test.properties in the classpath.
If no such file is found the YAML ConfigurationFactory will look for log4j2-test.yaml or log4j2-test.yml in the classpath.
If no such file is found the JSON ConfigurationFactory will look for log4j2-test.json or log4j2-test.jsn in the classpath.
If no such file is found the XML ConfigurationFactory will look for log4j2-test.xml in the classpath.
If a test file cannot be located the properties ConfigurationFactory will look for log4j2.properties on the classpath.
If a properties file cannot be located the YAML ConfigurationFactory will look for log4j2.yaml or log4j2.yml on the
classpath.
If a YAML file cannot be located the JSON ConfigurationFactory will look for log4j2.json or log4j2.jsn on the classpath.
If a JSON file cannot be located the XML ConfigurationFactory will try to locate log4j2.xml on the classpath.
If no configuration file could be located the DefaultConfiguration will be used. This will cause logging output to go to the console.
So you can see that apart from (1) , all are looking the configuration file from classpath . In the standard Maven project , /src/main/resources is the root of the classpath .So you can put log4j2.xml in /src/main/resources.
Otherwise, you have to explicitly specify the configuration file by log4j.configurationFile system property :
-Dlog4j.configurationFile=path/to/log4j2.xml

Related

Log4j Doesn't Log Messages

So I am programming a game and I decided I should switch from System.out.println to an actual logging api and decided to use Log4j. I followed a tutorial to use the basic configuration but when I call logger.info("string stuff"); it doesn't actually log anything.
I have:
public static final Logger logger = Logger.getLogger("Main.class");
And
public static void main(String[] args) {
BasicConfigurator.configure();
logger.info("Starting Game...");
}
You should configure Log4j with either command line options or a configuration file to enable the info level logging to an appender e.g. system console. Assuming you are using Log4j2 check out the Configuration docs.
The order of processing configuration in Log4j2 is:
Log4j will inspect the "log4j2.configurationFile" system property and, if set, will attempt to load the configuration using the
ConfigurationFactory that matches the file extension. Note that this
is not restricted to a location on the local file system and may
contain a URL.
If no system property is set the properties ConfigurationFactory will look for log4j2-test.properties in the classpath.
If no such file is found the YAML ConfigurationFactory will look for log4j2-test.yaml or log4j2-test.yml in the classpath.
If no such file is found the JSON ConfigurationFactory will look for log4j2-test.json or log4j2-test.jsn in the classpath.
If no such file is found the XML ConfigurationFactory will look for log4j2-test.xml in the classpath.
If a test file cannot be located the properties ConfigurationFactory will look for log4j2.properties on the classpath.
If a properties file cannot be located the YAML ConfigurationFactory will look for log4j2.yaml or log4j2.yml on the
classpath.
If a YAML file cannot be located the JSON ConfigurationFactory will look for log4j2.json or log4j2.jsn on the classpath.
If a JSON file cannot be located the XML ConfigurationFactory will try to locate log4j2.xml on the classpath.
If no configuration file could be located the DefaultConfiguration will be used. This will cause logging output to go to the console.
If you haven't configured anything you are most likely on point 10 and using the default configuration. This will only log error level and higher to console while you are using info level, which is lower. As per docs:
Log4j will provide a default configuration if it cannot locate a configuration file. The default configuration, provided in the DefaultConfiguration class, will set up:
A ConsoleAppender attached to the root logger.
A PatternLayout set to the pattern "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" attached to the ConsoleAppender
Note that by default Log4j assigns the root logger to Level.ERROR.

Externalized Configuration in Spring boot

I have a external configuration file(out side jar). I try to run and expected
that value in external file will override value in internal file(application.properties in \resource\ - in jar file).
I read Documentation and try this:
java -jar ccgame-1.0.jar --spring.config.location=classpath:/application.properties,file:/production.properties
This not working.
My jar file at \target\ directory and my production.properties too(at \target\)
How can I resolve my problem?
Where should I put external config file ?
And what I have to do ?
Starting from Spring Boot 2.0 it's possible to use property spring.config.additional-location. With this property, you can set external config file, but properties from that config will only override the corresponding ones from internal config, leaving other properties unchanged.
More about it in docs.
If you need to completely override the whole config, then continue to use spring.config.location property instead.
By convention, Spring Boot looks for an externalized configuration file – application.properties or application.yml – in 4 predetermined locations in the following order of precedence:
/config subdirectory of the current directory
The current directory
Classpath /config package
The classpath root
You can place your application.properties in any of the 4 locations without needing to give the location of application.properties while executing the jar. If you want to given any other custom location , then you will have to provide the path of the config location while executing the jar:
java -jar -Dspring.config.location=<path-to-file> myProject.jar
Source: https://www.baeldung.com/spring-properties-file-outside-jar

springboot external configuration - profile specific configuration

According to the SpringBoot documentation, the order of configuration is as:
Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)
Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)
Application properties outside of your packaged jar (application.properties and YAML variants).
Application properties packaged inside your jar (application.properties and YAML variants).
On my project I have a profile called "prod" and the following files:
application.yml (inside the jar)
application-prod.yml (inside the jar)
And I also want to override some of the properties using an external file. Since according to the docs, an external application.yml will be overridden by the internal application-prod.yml, I need to make sure that the external file is considered as a profile specific config file.
I have tried to use:
-Dspring.config.location=<my path>/application-prod.yml
and I have also tried:
-Dspring.config.location=file:<my path>/application-prod.yml
In all cases I get the value from the internal application-prod.yml
If I totally remove the internal config file then I get the value from the external (so I know that the config picks up the file).
I understand that this external file is considered as the equivalent to the generic application.yml and not a profile specific.
How can I configure it to be considered as a profile specific external config?
Found the answer:
You need to use a Directory externally to set the profile specific configuration files, not using the file directly and it needs to end in /. So it has to be:
-Dspring.profiles.active=prod
-Dspring.config.location=/<some-path>/config/ (any path that ends in /)
and in there have a :
application-prod.yml

Why is Spring Boot's resource precedence ignoring my external properties files?

As part of a Spring Boot project I need to load certain properties file which, by default, is located under de src/main/resources directory. Also, I need to be able to, instead, load an external properties file (located at the root directory of the project). If this external file exists, the file path should be passed as command line property.
The file structure would be like this:
/app_project
Net.properties (external file)
/src
/main
/resources
Net.properties (default file)
The thing is that the dependency that makes use of those properties wouldn't work unless you copy/overwrite the contents of the external file into the file under the /resources directory.
UPDATED
So far I've tried:
loading the file as an external resource and loading it into a Properties object (https://docs.oracle.com/javase/7/docs/api/java/util/Properties.html)
saving the properties as System Properties
modifying the resource handler to look into other directories by overriding th addResourceHandlers() to include the location
Explicitly including the location of the file in the CLASSPATH with the -cp argument (as #veysiertekin suggested)
Loading it as a #PropertySource (as suggesed by #Nikolay Shevchenko)
Overriding the Spring Boot's config location with the spring.config.location (as suggested by #gWombat)
With all these methods I've tried, the file is indeed read and loaded but, at some point, and every time, the app resorts to the file under src/main/resources .
I suspect it may have to do with the precedence of the file (as described here https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html), but I just couldn't figure out what's happening.
Thanks in advance for your help.
Try smth like
#PropertySources({
#PropertySource(name = "default", value = "classpath:default.properties"),
#PropertySource(name = "external", value = "classpath:external.properties", ignoreResourceNotFound = true)
})
public class YourSpringBootApplication {
...
}
Based on the official doc, you can try to use the propertyspring.config.additional-location to add additional config file , or spring.config.location to override default file location.
You should pass those properties as program arguments so that Spring can use them on application startup.
When spring-boot project is running, it checks files under the builded jar file. You need to add your external file to classpath before running the application:
java -cp 'path-to/spring-boot-application.jar:Net.properties' test.SpringBootApplicationMain

using property-placeholder for in jar properties file

I use this line :
context:property-placeholder location="classpath*:resources/BLLresources/MQ.properties"
in a spring.xml file to look for MQ.properties which is inside the jar where the xml file is (in config folder at the root level).
I got error :
Caused by: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: {{uriMesarimReadQueue}} due to: Properties file classpath*:resources/BLLresources/MQ.properties not found in classpath
If I put the properties file outside the jar it works fine.
the jar is in the classpath.
any advice ?
I think your have your references setup incorrectly. In a normal java project the resources folder would be located in src/main/resources, this folder gets mapped to the root of the generated jar file. Therefore, if you had a file src/main/resources/BLLresources/MQ.properties, the mapping would be classpath*:BLLresources/MQ.properties

Categories

Resources