Background
I am developing a Java web application, packaged as a WAR in an EAR, which utilizes Log4j2 for logging, and am encountering an issue when deploying the application to a development server. The logging relies on a custom filter (based on this answer), located in a separate JAR, which is used to set the log level per client.
On my local machine, specifically when the EAR is running via the IDE, the filter is loaded (Took 0.x seconds to load 1 plugins from package a.b.c
) and works as expected . On the development server, and on my local machine when exported and loaded manually via the Admin Console, the filter is not loaded (Took 0.x seconds to load 0 plugins from package a.b.c
), and thus logging does not function as desired .
The EAR layout looks approximately like this:
.
├── lib
| ├── Common.jar
| | ├── CustomFilter.class
| | └── OtherCustomUtils.class
| ├── log4j-api.jar
| ├── log4j-core.jar
| └── [more third party JARs]
├── WebApp.war
| ├── WebApp.class
| └── WEB-INF
| ├── lib
| | ├── log4j-web.jar
| | └── [more third party JARs]
| ├── log4j2.xml
| └── web.xml
├── SomeEJB.jar
| └── ClassThatAlsoUsesCommonJar.class
└── META-INF
└── application.xml
Analysis and Attempts
My hypothesis is that the classes in Common.jar are simply not being loaded by the classloader before Log4j2 is initialized and configured. Here's what I've tried thus far:
- Initially I feared that it might be a conflict between the EAR's and web module's classloaders; I think I eliminated this possibility by configuring the deployed EAR to only use one classloader for the whole application, but I could be wrong.
- I've left the EAR in this condition since. Hopefully this isn't screwing everything up.
- I'm currently using log4j-web, as recommended by the "Using Log4j 2 In Web Applications" page. With minimal configuration I observe that it runs and loads the log4j2.xml almost immediately after starting the web app. While running in the IDE I presume the Common.jar is already loaded, so this is OK, while on the development server (or installed manually on local) Common.jar doesn't seem to be loaded yet, and the search for the plugin fails.
- Removing log4j2-web and just letting log4j2 initialize itself on first-call doesn't seem to fix this problem (first call to log4j2 happens before first call to any class in Common.jar)
- Logs are going to a couple files and databases, so I don't think I want to have this application running without log4j-web.
- Acknowledging that log4j-web is a web fragment, I thought to try and make Common.jar a web fragment, and specify that it load before log4j-web via the web.xml in the web app. I have next to no idea what I'm doing here, so I probably messed this up. Furthermore, this requires that Common.jar be in WEB-INF/lib, which may or may not be a big deal?
- The EJB project depends on Common.jar, so it needs it to be loaded, but since I'm using one classloader for the whole app I assume if the web app loads it first, and then the EJB needs it later, it'll already be there?
I'll admit that my hypothesis hinges entirely on the idea that my application server doesn't eagerly load all of the classes in all of the JARs in the EAR's lib directory.
Desired Solution
A simple configuration-based fix would be ideal. I'm still a novice at best when it comes to crafting JEE applications, so I wouldn't be surprised to find an option buried somewhere to explicitly specify that everything in Common.jar be preloaded (assuming it isn't already?)
An actual code change is not out of the question of course. I'd just prefer not to.
Environment
- Java Version: 1.7.1
- JEE Version: 6
- Log4j2 Version: 2.6.2
- Application Server: WebSphere 8.5.5.6
- IDE: Rational Software Architect 8.5 (Eclipse 3.6?)
Similar Questions
- Log4j2 (2.1) custom plugin not detected by packages attribute and Log4j2 custom filter
- using packages attribute, works on local
- Log4j2 custom plugins not working in EAR
- application set to use one classloader
- Custom plugin not getting detected in EAR with log4j2 API
- not using Maven, packages attribute works now, questioner doesn't appear to be using log4j-web