• Post Reply Bookmark Topic Watch Topic
  • New Topic

Sign up Log4j logging not working, log4j.xml file getting emptied when tomcat is bounced  RSS feed

 
eswari Malluru
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All,

I have a strange issue with log4j. When calling the  org.apache.log4j.xml.DOMConfigurator.configure(configurationPath); log4j.xml in class path is getting empty and no log file is generated when tomcat is bounced and any action is performed to generate log.

Actually I am trying to update the log level and logging file path in log4j.xml file dynamically using javax.xml.parsers.DocumentBuilderFactory from my web application while tomcat is up and running. After updating the log4j.xml calling org.apache.log4j.xml.DOMConfigurator.configure(Path/log4j.xml); to incorporate log4j.xml file changes to logger with out restarting the tomcat. This is working fine in my local windows 7 system and our developmet linux instances where the configuration is Struts 1.3, [color=red]Tomcat-8.0.36, Java - 8 update 74
and linux-2.6.18-238.el5xen.

Now I am getting issue with logging in new instance having same configurations mentioned above except linux version here it is : Linux-2.6.32-642.el6.x86_64

Catalina.out is showing the below errors

13 Jul 2017 05:33:10  INFO ChangeLogMode - XML modification Done and new file has placed in the path
13 Jul 2017 05:33:10  INFO ChangeLogMode - Now Logger mode will switch to = INFO
13 Jul 2017 05:33:10  INFO ChangeLogMode -  log4j.xml file exists rebooting the log4j.xml to tomcat server == /user/apache-tomcat-8.0.36/webappsTestApplication/WEB-INF/classes/log4j.xml
log4j: System property is :null
log4j: Standard DocumentBuilderFactory search succeded.
log4j: DocumentBuilderFactory is: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
log4j:WARN Fatal parsing error -1 and column -1
log4j:WARN Premature end of file.
log4j:ERROR Could not parse file [/user/apache-tomcat-8.0.36/webapps/TestApplication/WEB-INF/classes/log4j.xml].
org.xml.sax.SAXParseException; Premature end of file.
    at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:205)
    at org.apache.log4j.xml.DOMConfigurator$1.parse(DOMConfigurator.java:749)
    at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:866)
    at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:755)
    at org.apache.log4j.xml.DOMConfigurator.configure(DOMConfigurator.java:891)
    at com.aasc.model.ChangeLogMode.<init>(ChangeLogMode.java:178)
    at com.aasc.util.Log4JInitServlet.init(Log4JInitServlet.java:49)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1238)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1151)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1038)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5027)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5337)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:940)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1816)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)



my log4j.xml file is


<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration debug="true" xmlns:log4j="http://jakarta.apache.org/log4j/" threshold="null" reset="false">

<appender name="logFIle" class="org.apache.log4j.RollingFileAppender">
<param name="file" value="/user/apache-tomcat-8.0.36/logs/"/>
<param name="Append" value="true"/>
<param name="ImmediateFlush" value="true"/>
<param name="MaxFileSize" value="10GB"/>
<!-- <param name="threshold" value="debug"/> -->
<param name="maxBackupIndex" value="1"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd MMM yyyy HH:mm:ss} %5p %c{1} - %m%n"/>
</layout>
</appender>

<appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd MMM yyyy HH:mm:ss} %5p %c{1} - %m%n"/>
</layout>
</appender>
   
<root>
<level value="INFO"/>
<appender-ref ref="logFIle"/>
<!-- <appender-ref ref="infoFile" />
<appender-ref ref="warnFile" />
<appender-ref ref="errFile" />
<appender-ref ref="traceFile" /> -->
<appender-ref ref="consoleAppender"/>
</root>

</log4j:configuration>



And ChangeLogMode.java to edit.xml file is as below


javax.xml.parsers.DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
              javax.xml.parsers.DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
              Document doc = docBuilder.parse(new File(configurationPath));
              // Get the root element
              Node appender = doc.getFirstChild();
Node debugFile = doc.getElementsByTagName("param").item(0);
             NamedNodeMap attr = debugFile.getAttributes();
             Node nodeAttr = attr.getNamedItem("value");
             nodeAttr.setNodeValue(logPath+"ShipConsole.log");
             logger.info("debugFile  nodeAttr.setNodeValue done from ChangeLogMode == " + nodeAttr);
Node level = doc.getElementsByTagName("level").item(0);
             NamedNodeMap levelAttribt = level.getAttributes();
             Node nodeLevelAttr1 = levelAttribt.getNamedItem("value");
             nodeLevelAttr1.setNodeValue(loggerMode);
             logger.info("level  nodeLevelAttr1.setNodeValue done from ChangeLogMode == " + nodeLevelAttr1);
              // write the content into xml file
             javax.xml.transform.TransformerFactory transformerFactory = TransformerFactory.newInstance();
             javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
             javax.xml.transform.dom.DOMSource source = new DOMSource(doc);
              FileOutputStream outputStream = new FileOutputStream(new File(configurationPath));
              javax.xml.transform.stream.StreamResult result = new StreamResult(outputStream);
              transformer.transform(source, result);
              logger.info("XML modification Done and new file has placed in the path");
              File log4jFile = new File(configurationPath);
                             if (log4jFile.exists()) {
                                 logger.info("log4j.xml file exists rebooting the log4j.xml to tomcat server == "+configurationPath);      // Till this line it is perfect
                                 org.apache.log4j.xml.DOMConfigurator.configure(configurationPath);                                             // server is throwing the above errors mention in catalina.out when this line is executed
                                 logger.info("Initialized Log files with new modifications == "+configurationPath);
                             }


I am getting this issue only in client instance, it is working fine with same configurations and same deployment in other instances. Could you please suggest me whether the Linux instance has any dependency on using DOMConfigurator.configure

Could someone please help me to resolve this issue and generate the log file using logj4.xml.

Thanks in Advance.
Eshwari

[/color]
 
Tim Holloway
Bartender
Posts: 18663
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Linux should be no different.

Check your /user/apache-tomcat-8.0.36/webapps/TestApplication/WEB-INF/classes/ directory to see if the log4j.xml file is present and not empty. If so, check the file access rights. The userid that you are running Tomcat  under must have permission to read this file. Use the "ls -lZh" directory option just to make sure that you don't have some sort of weird selinux rule blocking you. The error message you are getting is what I'd expect to see if the file had no text in it, or the first column/line of the file was not in the form "<?xml ....". Or if access was denied so that an attempt to read that line failed.

Remember also that if you are deploying as a WAR file, that Tomcat's default behavior is to unpack ("explode") that file into a directory with the same name as the WAR file's basename. And that having done so, updating/replacing the WAR file will do nothing. To properly update a WAR installation, delete the exploded directory so that Tomcat will know to use the new WAR.
 
eswari Malluru
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Hi Tim,

Thank you very much for you reply.

log4j.xml file is there in /user/apache-tomcat-8.0.36/webapps/TestApplication/WEB-INF/classes/ directory. Initially this file size is 4222 bytes and also have 777 permissions. When tomcat is bounced this file is remaining as it is but when any action is performed in the web application to generate log, before creating the log file this log4j.xml file is becoming empty with size 0 bytes.

The code highlighted with red color in the below code snippet is making the log4j.xml file empty

[color=darkblue][size=11]

              String configurationPath= contextPath+"\\WEB-INF\\classes\\log4j.xml";
              DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
              DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
              Document doc = docBuilder.parse(new File(configurationPath));

              logger.info("doc : "+doc);  // Here is printing as[#document: null]
              // Get the root element
              Node appender = doc.getFirstChild();
              logger.info("appender : "+appender); // this is getting the first child in the log4j.xml
             
             Node debugFile = doc.getElementsByTagName("param").item(0);
             NamedNodeMap attr = debugFile.getAttributes();
             Node nodeAttr = attr.getNamedItem("value");
             logger.info("node Attr before changing to new file name : "+nodeAttr);
            
             nodeAttr.setNodeValue(logPath+"ShipConsole.log");
             logger.info("debugFile  nodeAttr.setNodeValue done from ChangeLogMode == " + nodeAttr);
          
             Node level = doc.getElementsByTagName("level").item(0);
             NamedNodeMap levelAttribt = level.getAttributes();
             Node nodeLevelAttr1 = levelAttribt.getNamedItem("value");
             nodeLevelAttr1.setNodeValue(loggerMode);
             logger.info("level  nodeLevelAttr1.setNodeValue done from ChangeLogMode == " + nodeLevelAttr1);

                           // write the content into xml file
              TransformerFactory transformerFactory = TransformerFactory.newInstance();
              Transformer transformer = transformerFactory.newTransformer();
             
              transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
              transformer.setOutputProperty(OutputKeys.METHOD, "xml");
              transformer.setOutputProperty(OutputKeys.INDENT, "yes");
              transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");


[color=red]
              DOMSource source = new DOMSource(doc);
              FileOutputStream outputStream = new FileOutputStream(new File(configurationPath));
              StreamResult result = new StreamResult(outputStream);
              logger.info("source : "+source); // This is printing some object
              logger.info("result : "+result);   // This is printing some object
              transformer.transform(source, result);
             
              File log4jFile = new File(configurationPath);
              logger.info("log4jFile : "+log4jFile);     // this is printing  /user/apache-tomcat-8.0.36/webapps/TestApplication/WEB-INF/classes/log4j.xml
              logger.info("log4jFile path : "+log4jFile.getPath());  // this is also printing  /user/apache-tomcat-8.0.36/webapps/TestApplication/WEB-INF/classes/log4j.xml
              logger.info("log4jFile canWrite : "+log4jFile.canWrite());  // this is printing true

              logger.info("log4jFile length : "+log4jFile.length());   // this is printing 0
              logger.info("log4jFile.exists() : "+log4jFile.exists());  // this is printing
                             if (log4jFile.exists()) {
                              logger.info("Inside if before configure");
                                  DOMConfigurator.configure(configurationPath);   // At this line trowing exceptions as below
                                 logger.info("Initialized Log files with new modifications == "+configurationPath);
                             } else {
                                   BasicConfigurator.configure();
                             }

             
             Logger rootLogger = Logger.getRootLogger();    
             if(loggerMode != null && !loggerMode.equals("")){
              rootLogger.setLevel(Level.toLevel(loggerMode));
               }


           Exceptions :

log4j: System property is :null
log4j: Standard DocumentBuilderFactory search succeded.
log4j: DocumentBuilderFactory is: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl
log4j:WARN Fatal parsing error -1 and column -1
log4j:WARN Premature end of file.
log4j:ERROR Could not parse file [/user/aasc/apache-tomcat-8.0.36/webapps/TestApplication/WEB-INF/classes/log4j.xml].
         org.xml.sax.SAXParseException; Premature end of file.
        at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
        at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
        at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:205)
        at org.apache.log4j.xml.DOMConfigurator$1.parse(DOMConfigurator.java:749)
        at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:866)
        at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:755)
        at org.apache.log4j.xml.DOMConfigurator.configure(DOMConfigurator.java:891)
        at com.aasc.model.ChangeLogMode.<init>(ChangeLogMode.java:209)
        at com.aasc.view.AascProfileOptionsAction.execute(AascProfileOptionsAction.java:2561)
        at org.apache.struts.chain.commands.servlet.ExecuteAction.execute(ExecuteAction.java:58)
        at org.apache.struts.chain.commands.AbstractExecuteAction.execute(AbstractExecuteAction.java:67)
        at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)

           
[/color]




Not able to find out why this log4j.xml file is getting empty.

Did anyone face this type of issue. If so please let me know why this issue is coming and how to resolve this issue

Thanks,
Eshwari

[/size][/color]
 
Tim Holloway
Bartender
Posts: 18663
71
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, one thing that sets off skyrockets is this path:

contextPath+"\\WEB-INF\\classes\\log4j.xml"

This is alarming in a number of ways.

First of all, Linux doesn't use backslashes as file path separators. While the File classes MIGHT accept them, this is a much better way:

File configFile = new File(contextPath, "WEB-INF/classes/log4j.xml");

Note that I did 2 things there. First, I used the directory+relative path File constructor, which automatically knows which OS file path conventions to use. And secondly, I used forward-slash separators on the relative path. The forward-slash separators are guaranteed to work on all OS's - even Windows. The File constructor adapts. And as a bonus, you don't get zapped if you forget to double-up like you have to do with backslashes, since the forward-slash doesn't have an alternate meaning.

But beyond that, there's more. The context path is part of the URL. It is NOT a filesystem path, even though it looks like one and even though the default directory name under TOMCAT_HOME/webapps is the same as its context name (note the word "default"). In fact, you really shouldn't reference resources within a WAR by filesystem pathnames at all. For one thing, unless the server has exploded the WAR, the filesystem path won't exist, since the WEB-INF/classes/log4j.xml would be simply an entry within the WAR file. More properly, you should use the J2EE resource access methods (getResource or getResourceAsStream), which use a WAR-rooted path ("/WEB-INF/classes/log4j.xml).

But wait - there's more! The default place for log4j to look for log4j.properties or log4j.xml is at the root of the WAR's classpath. So you could simply not provide an explicit location and as long as you placed the log4j.file in /WEB-INF/classes, log4j would find it automatically.

I don't guarantee that attending to all this will definitely solve your problem, but just seeing that path was a speed bump for me. There is one other thing that Windows does different than Linux, although I don't think that it's the problem here. Windows locks files based on their filenames. Linux locks files based on their physical locations. That's why Windows often requires a reboot (or program exit, depending on where the file was locked) after replacing a file and Linux starts using the replacement immediately.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!