Trying to get this logging issue resolved
wgpuckett Apr 12, 2011 12:54 PMI have been using jBoss for 6 years now and still have not figured out how to generate consistent separate logs from my servlets. So far the best I have been able to do is get maybe 75% of my log output to go to a unique log file but also getting 100% of the output to the jboss server log file. I would like to get this resolved completely. Unfortunately I usually research and scratch and claw at a solution until my back is up against the wall before I try to ask for help on the forums. I have Googled this and tried a number of suggestions. I just can't get anything to work as advertised. I started out with the attempt of putting the log4j jar file in my EAR file. This doesn't work because of the way the class loader works in jBoss. It gets all screwed up when attempting to generate logging from both the EJB and the WEB containers. I tried ALL of the suggested solutions for that one without any success.
I have come across what seems like the best solution in the jBoss wiki. After implementing the code as described I don't get any errors, I get a log file created, but nothing ever goes to the log file. At the moment I am first trying to get the log output from the JPA persistence EntityManagerHelper to go to a specific log file. Once I get that working I need to implement other logging functionality.
Based on my research it appears the best solution (at least for me) is using a custom repository selector. So I used the provided class that implements RepositorySelector:
{code}
package mm.logging.repository;
/**
* This RepositorySelector is for use with web applications. It assumes that
* your log4j.xml file is in the WEB-INF directory.
*
*
*/
public class AppRepositorySelector implements RepositorySelector {
private static boolean initialized = false;
private static Object guard = LogManager.getRootLogger();
private static Map repositories = new HashMap();
private static LoggerRepository defaultRepository;
public static synchronized void init(ServletConfig servletConfig)
throws ServletException {
init(servletConfig.getServletContext());
}
public static synchronized void init(ServletContext servletContext)
throws ServletException {
if (!initialized) // set the global RepositorySelector
{
defaultRepository = LogManager.getLoggerRepository();
RepositorySelector theSelector = new AppRepositorySelector();
LogManager.setRepositorySelector(theSelector, guard);
initialized = true;
}
Hierarchy hierarchy = new Hierarchy(new RootLogger(Level.DEBUG));
loadLog4JConfig(servletContext, hierarchy);
ClassLoader loader = Thread.currentThread().getContextClassLoader();
repositories.put(loader, hierarchy);
}
public static synchronized void removeFromRepository() {
repositories.remove(Thread.currentThread().getContextClassLoader());
}
// load log4j.xml from WEB-INF
private static void loadLog4JConfig(ServletContext servletContext,
Hierarchy hierarchy) throws ServletException {
try {
String log4jFile = "/WEB-INF/log4j.xml";
InputStream log4JConfig = servletContext.getResourceAsStream(log4jFile);
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(log4JConfig);
DOMConfigurator conf = new DOMConfigurator();
conf.doConfigure(doc.getDocumentElement(), hierarchy);
} catch (Exception e) {
throw new ServletException(e);
}
}
private AppRepositorySelector() {
}
public LoggerRepository getLoggerRepository() {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
LoggerRepository repository = (LoggerRepository) repositories.get(loader);
if (repository == null) {
return defaultRepository;
} else {
return repository;
}
}
}
{code}
Then I put in the context listener
{code}
package mm.logging.repository;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class AppContextListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent contextEvent) { }
public void contextInitialized(ServletContextEvent contextEvent) {
try {
AppRepositorySelector.init(contextEvent.getServletContext());
} catch (Exception ex) {
System.err.println(ex);
}
}
}
{code}
and then added the listener to the web.xml file
{code:xml}
<listener>
<listener-class>mm.logging.repository.AppContextListener</listener-class>
</listener>
{code:xml}
And then put the following log4j.xml file in the WEB-INF folder:
{code:xml}
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<appender name="JPA" class="org.jboss.logging.appender.RollingFileAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="File" value="D:/WWW/CWDC/logs/jpa.log"/>
<param name="Append" value="false"/>
<param name="MaxFileSize" value="500KB"/>
<param name="MaxBackupIndex" value="1"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
</layout>
</appender>
<category name="CWDCPU">
<priority value="DEBUG" />
<appender-ref ref="JPA"/>
</category>
</log4j:configuration>
{code:xml}
The EntityManagerHelper has the followoing code:
{code}
logger = Logger.getLogger("CWDCPU");
logger.setLevel(Level.ALL);
{code}
And in the JPA code the logging looks something like:
{code}
EntityManagerHelper.log("saving AccountStructureTbl instance", Level.INFO, null);
{code}
When jBoss starts don't see any sort of diagnostic indicating this did not start properly. I can't say I see anything that says it does either.
I end up getting all of the JPA logging on the console and nothing in the log file itself.
I will admit that I am much more familiar with the log4j properties file rather than the xml but I tried to keep it as simple as possible.
Where did I go wrong?