1

I'm working on a Java EE project which had configuration files in resources folder. The web project is assembled into a war file using Maven and deployed to Tomcat.

Then I started doing some maintainance and tried to externalize the configurations which had been successful to some extent.

In case you wonder how it was on production before I edited the code, here it goes:

// x stands for `application.conf` or  `en.properties` depending on where in the code the file is being 
getClass().getClassLoader().getResourceAsStream(x)

I've moved every single file under resources to /CATALINA_BASE/conf/myProject and I'm reading from these paths in the code. (doesn't look like a good practice to me)

And here is my version:

// x stands for `application.conf` or  `en.properties` depending on where in the code the file is being read
new File(System.getProperty("catalina.base") + "/conf/myProject/x")

This works fine obviously but the project also has a log4j2.properties file which was automatically read from the classpath before and since I've externalized the configuration I'm not able to read from it.

What I tried was setting a parameter inside web.xml like below(not sure if it is right thing to do)

<web-app>
...
    <context-param>
<!--        also tried with log4jConfigLocation-->
        <param-name>log4Configuration</param-name>
        <param-value>file:${catalina.base}/conf/myProject/log42.properties</param-value>
    </context-param>
...
</web-app>

The error output during application startup:

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console. Set system property 'org.apache.logging.log4j.simplelog.StatusLogger.level' to TRACE to show Log4j2 internal initialization logging.

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".

SLF4J: Defaulting to no-operation (NOP) logger implementation

Any suggestions would be appreciated.

UPDATE: The tomcat running on the server is serving several other applications so setting VM arguments is not an option for me since other projects might have their log4j configurations in their classpath and VM arguments may break those configurations.

ardatosun
  • 457
  • 4
  • 22

2 Answers2

2

In case anyone faces this issue, I've found a solution.

After digging down into the source files of org.apache.logging.log4j:log4j-core:2.8.2 I saw that the ConfigurationFactory class calls PropertiesUtil.getProperties() which has a line as follows:

private static final PropertiesUtil LOG4J_PROPERTIES = new PropertiesUtil("log4j2.component.properties");

Therefore I created a log4j2.component.properties file under src/main/resources/ which has only one line of property:

log4j.configurationFile=myCustomPath/log4j2.properties

Since we cannot use logging.config property to set configuration path in Java EE applications unlike a Spring project, adding this specific file solved my problem with externalizing Log4j configuration.

Hope this answer helps others too.

informatik01
  • 16,038
  • 10
  • 74
  • 104
ardatosun
  • 457
  • 4
  • 22
1

You should go to Catalina.properties and add the conf/myProject directory to the classpath. Then your could can just look for files at the root of the classpath. You can create a logging configuration for each web app in that directory by changing your configuration in web.xml to just the name of the file - i.e. log4j2-appname.xml.

Another alternative that could work is to change your file url from file: to file://.

BTW - my employer has apps running like this - multiple apps in a single tomcat. It has caused all kinds of problems over time and really is a bad idea.

rgoers
  • 8,696
  • 1
  • 22
  • 24
  • I've put a `log4j2.component.properties` file under project classpath and inside I give the actual configuration file path. It works but it would be more elegant if I could just use `${catalina.base}` instead of writing full absolute path inside my property file. Do you have any idea how I can resolve system arguments inside .properties file? – ardatosun Jul 14 '20 at 12:27