I am trying to set up log4j for a project of mine. I have found this tutorial, I followed each of its steps.
Of course, I have added the jar file to the Referenced Libraries. The following picture shows that the path to the log.out file is in the PATH variable. This is how my PATH variable looks like (just a snippet):
The following picture shows that the path to the log4j jar file and the log4j.properties file is in the CLASSPATH variable. This is my CLASSPATH:
log4j.properties file (the only thing I changed is the log4j.appender.FILE.File in comparison to the .properties example from the tutorial previously mentioned):
This is how my project hierarchy looks like:
I am testing it with the following class:
package test;
import org.apache.log4j.Logger;
import java.io.*;
import java.sql.SQLException;
public class Log4jExample{
/* Get actual class name to be printed on */
static Logger log = Logger.getLogger(Log4jExample.class.getName());
public static void main(String[] args) throws IOException,SQLException{
log.debug("Hello this is an debug message");
log.info("Hello this is an info message");
}
}
I keep receiving the following exceptions and nothing is being logged to the file specified:
When trying to follow the link specified in the WARN message, I have found the following answer:
This occurs when the default configuration files log4j.properties and log4j.xml can not be found and the application performs no explicit configuration.
How come the log4j.properties cannot be found? How can this be solved?
NOTE: I have seen that there are many posts regarding these particular WARN messages, however, I have neither a maven project, nor a dynamic web project. This is a plain Java project and I am simply trying to test log4j. I have Windows 7 and use Eclipse Luna.
UPDATE: It seems that if I move my log4j.properties file to the src folder, everything goes fine. How could I modify things to work from the current structure of files?
UPDATE #2: The answer I marked as accepted below answers my question from UPDATE. However, I have also found this post that proposes an useful solution to this problem with the location.
By default, Log4j searches for a configuration file (log4j.xml or log4j.properties) at the root of your classpath. Putting it in the src folder automatically does that.
If you do not wish to have it there, you can tell Log4j where to look for it through the system property log4j.configuration. Launching your app then becomes : java -Dlog4j.configuration=file:"D:\..." -jar myapp.jar. In Eclipse, the system property is configured in "Run Configurations > Arguments > VM arguments".
By default, Log4j searches for a configuration file (log4j.xml or log4j.properties) at the root of your classpath. Putting it in the src folder automatically does that.
Related
My question is expressed in terms of these
two Images.
In the first one, configuration.configure() method of hibernate loads the
file from src folder as indicated by red arrows
While in this second image,
it is shown that PropertyConfigurator.configure() method of Log4j loads the file from
root folder of Project as indicated by the red arrows again
In both projects, this and only this setup works and no alternate setup works.
Thanks for help.
Eclipse isn't doing anything, it's all the JVM. the results would be the same if you used the command line or another IDE.
The different programs load configuration diferently in your 2 examples.
Hibernate loads config files as a resource which looks for a file with that path on your class path which is why it can be in src.
sourcode of Hibernate's Configuration#configure(String)
Log4j uses the String as a path to open a FileInputStream. Since you give a relative path, it looks for a file relative the root of your project
sourcecode of log4j PropetyConfigruator#configure(String)
load hibernate.cfg.xml
configuration.configure(hibernate.cfg.xml) means your hibernate configuration file “hibernate.cfg.xml” is at the root of your project classpath.Even if you don't pass the configuration file name in the configure() method, it will work, but in that case name should be hibernate.cfg.xml.
If you want to place this configuration file into a different directory then you need do like below
new Configuration().configure("/com/config/hibernate.cfg.xml")
load log4j.properties
Loading log4j.properties also works in the similar way.
If you want to put your log4j.properties in to com-->config source folder you can do like below
PropertyConfigurator.configure("classpath:com/config/log4j.properties");
I have one application running in WAS8.
we have a jar - commons-logging-1.1.1.jar in WEB-INF/lib
we have one properties file - commons-logging.properties
the content of the file is
priority=1
org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
we have org.apache.commons.logging.LogFactory file in WebContent/META-INF/services
the content of the file is
org.apache.commons.logging.impl.Log4jFactory
The log files are created but nothing is written in it. It is not showing any error in the log files in log of appserver.
Please let me know if I am missing something.
Please note: if I keep commons-logging.properties in /opt/IBM/WebSphere/80/AppServer/profiles/AppSrv01/properties, then it works perfectly fine. It is writing in the log files. But as I heard it is not standard practice so I can't keep the file in that place. I have to find some alternative way.
Please help me.
If it is not a requirement to have separate log files for your web application, you can simply remove the commons-log jar and properties from your module (war) and your log statements will write to SystemOut.log according to the log level settings in the WebSphere console (which can be changed at runtime, by the way).
If you must separate application logging, you can refer to this infocenter article that lays out the combination of commons-log jar location, commons-log properties values, and application classloader settings (Parent-First, Parent-Last, commons-log.jar bundled or not, etc) to achieve the desired results.
I'm using ESAPI for my project, and added the ESAPI configuration directory to src/main/resources so it is copied to my WAR file (I downloaded the WAR from cloudbees, I can see it was put in WEB-INF/classes/esapi/ directory)
Locally, I just point to where the directory is and all works fine, but on cloudbees it just doesn't work for me.
In order to access its properties, ESAPI project tries all kinds of stuff, including checking the org.owasp.esapi.resources system property, so I've added the following code to cloudbees-web.xml:
<sysprop name="org.owasp.esapi.resources" value="WEB-INF/classes/esapi/" />
and I can see that the system property value is found because of the following error in the logs:
Not found in 'org.owasp.esapi.resources' directory or file not readable: /var/genapp/apps/akld3873/WEB-INF/classes/esapi/ESAPI.properties
so it finds the system property (because the path is like I've specified), but when it looks for the actual directory and files in it, I guess the directory is either not there or not readable.
Do I need to move it somewhere else? Inside the WEB-INF directory maybe? Is the setting not right? I've read that others solved similar issues by building a JAR just for this directory, but this doesn't seem like a good solution, there must be a simple setup that will work for cloudbees.
Design for ESAPI lib to require a directory access to configuration is not very flexible.
A general purpose option is to use ServletContext.getRealPath to resolve the absolute filesystem path to this directory and pass it to ESAPI.
Another option is for you to have some init code to copy WEB-INF/classes/esapi content in a temporary directory (using java.io.temp system property to point to the currently configured temp dir for your app) and point ESAPI lib to this path.
Ok so after searching and testing, I finally figured it out.
Cloudbees deploys your web app to the following directory:
staxcat/install/webapp.war/
notice that this is a relative path, with prefix of this path attached it looks something like this:
/var/genapp/apps/xxxxxxxx/staxcat/install/webapp.war/WEB-INF/esapi/ESAPI.properties
so, in order to get ESAPI to work, I had to set the following in cloudbees-web.xml:
<sysprop name="org.owasp.esapi.resources" value="staxcat/install/webapp.war/WEB-INF/esapi" />
this will enable ESAPI to find the directory if in your project it is located under:
src/main/webapp/WEB-INF/esapi
and you should get the following log line:
Found in 'org.owasp.esapi.resources' directory: /var/genapp/apps/xxxxxxxxx/staxcat/install/webapp.war/WEB-INF/esapi/ESAPI.properties
To elaborate on that, I have a Tomcat server version 7.0.27 running Java 1.6.0_27.
I have two wars, each with their own log4j jar, also using slf4j with slf4j-log4j. Each war has it's own configuration file (log4j.xml).
war 1 should use file log-1.log and war 2 should use file log-2.log but both are logging into log-1.log.
I've checked there are no other log4j jars in the tomcat installation so I'm not sure where the problem is. I've also turned off shared class loading but that made no difference. My next step is to turn on verbose class loader logging and/or start debugging log4j but maybe someone here knows why this is and can save me some time. Thanks for any input on this.
Update:
Ok think I got this one. The log4j xml files are fine. After doing a verbose:class I can see that log4j.jar is only getting loaded once and from neither web application.
I'm working with Documentum. They have a runtime jar required to use their libraries that is an empty jar with a manifest file. The manifest points to a bunch of jars. In other words, they don't use maven... Anyway ... one of those jars happens to be logj4 found in the Documentum installation. So it seems both webapps are using that one. I think this is the problem. To be confirmed...
If you are placing Documentum's runtime jar on your top-level classpath, and that runtime jar is referencing log4j.jar, then it will only load once. You don't have to use that runtime jar, though, or you can use it in just your Documentum .war, if one is non-Documentum.
You didn't post your properties file but i can think of some reasons:
You don't have an appender that writes to the different files, i.e you need appender1 to write to log1.log and appender2 writing to log2.txt
You have the appenders set up right but both the applications are using the same logger, so they both write to the same file.
You have 2 loggers, each with its own appender, but in your code you are not initializing the correct logger:
//there is no logger called com.sample, so it defaults to root logger that has appender that writes to log1.txt
Logger logger = Logger.getLogger(com.sample.MyClass.class);
If you post your properties file and your logger init code it'll be easier to help you.
I have a web application, in which one of the JSPs contain:
PropertyConfigurator.configure(System.getenv("MY_HOME") + "/cfg/log4j.properties");
I double-checked that MY_HOME is setup
The Tomcat web server says:
log4j:WARN No appenders could be found for logger (com.mycompany.data.JobData).
log4j:WARN Please initialize the log4j system properly.
The same setup works fine in one of the other servers.
Any hints?
The problem is that no logs are created
Not related to your answer, but this helps too.
If it's a web application, the easiest way is to make sure that your log4j.properties is situated in WEB-INF/classes folder in your WAR file. When your application will be deployed, log4J will be configured.
The PropertyConfigurator must be called before anything in your system attempts to log to avoid this warning. You may find setting the log4j configuration on the command line more reliable.
Or you could ignore the warning. ;)
BTW: You don't want to call this method too often, ideally only once.
You can try this, its helps to me.
http://www.log4j.ru/articles/HelloWorld.html
I was able to find the solution to this problem running a Eclipse Dynamic Web Project in Apache Tomcat 6. Bascially, you need to load the log4j properties file out of your context.
Two basic steps
(1) Get the log4j.properties file into the "class directory" of the war file.
(2) Read the log4j properties file out of the current context. I found the best way to do this is to access the current thread's context and work from there.
For the first step above, alter the Eclipse build process to add an additional directory that will eventually load into the WEB-INF/classes directory in the war file. Specifically....
(1) In Eclipse, right click your project in the project explorer, select 'New'->'Folder'. You can name the folder anything, but the standard in this case is 'resources'. The new folder should appear at the root level of your project.
(2) Move the log4j.properties file into this new folder.
(3) Right click the project again, and select 'Build-Path'->'Configure Build Path'. Select the 'Sources' tab. Click the 'Add Folder' button. Browse to find your new folder you created in step (1) above. Select 'OK'.
(4) Once back to the eclipse Project Explorer view, note that the folder has now moved to the 'Java Resources' area (ie it's no longer at the root due to eclipse presentation abstraction).
(5) Clean build your project.
(6) To validate that the .properties file now exists in WEB-INF/classes in your war file, export a war file to an easy location (right click Project -> Export -> War file) and checkout the contents. Note that the log4j.properties file now appears in the WEB-INF/classes.
Now for the second step above, accessing the context to read the file. Add the following code where attempting to read the file. Note that this reads this out of the war file context, so this 'should' work as the war file moves from server to server.
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
PropertyConfigurator.configure(classLoader.getResourceAsStream("log4j.properties") );