Setting log4j.properties file for logging in servlets - java

The server is a simple jetty Server
How to set the log4j.properties file i have a proper log4j properties file,
but while setting the log4j.properties
using the following manner, i have the log4j.properties in my src folder
PropertyConfigurator.configure("log4j.properties");
it works fine when i am working locally, but when i create a jar file and run its throwing an exception like java.io.FileNotFoundException:
i have tried extracting it and created it in another folder called resources and tried accessing that by the following method
PropertyConfigurator.configure("resources/log4j.properties");
even after that its showing the same error
how to export the entire project as a jar file and make this log4j problem to work?
Found another link
Log4j Properties in a Custom Place
and in that it is required to set the class path
java -Dlog4j.configuration=conf/log4j.properties -classpath ...
Do not know how to set the -classpath and dont know whether this method will work!!
And even if its exported as a jar file it should work!

If the log4j.properties resource directory is on the classpath, you could use:
PropertyConfigurator.configure("classpath:resources/log4j.properties");
To see the working directory for Jetty, you could add:
System.out.println(System.getProperty("user.dir"));
before the PropertyConfigurator.configure statement. This would allow you to see where the property file is located in relation to the server's working directory.

In order to make it work immediatley, you can configure them from code:
Properties props = new Properties();
props.setProperty("<KEY>","VALUE");
PropertyConfigurator.configure(props);
Hardcode the props object with all the properties from log4j.properties file.
This is not the solution you ask, but it might very helpful if you are short on time.

Related

Can't get .properties file for configure database Tomcat [duplicate]

In my web application I have to send email to set of predefined users like finance#xyz.example, so I wish to add that to a .properties file and access it when required. Is this a correct procedure, if so then where should I place this file? I am using Netbeans IDE which is having two separate folders for source and JSP files.
It's your choice. There are basically three ways in a Java web application archive (WAR):
1. Put it in classpath
So that you can load it by ClassLoader#getResourceAsStream() with a classpath-relative path:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);
Here foo.properties is supposed to be placed in one of the roots which are covered by the default classpath of a webapp, e.g. webapp's /WEB-INF/lib and /WEB-INF/classes, server's /lib, or JDK/JRE's /lib. If the propertiesfile is webapp-specific, best is to place it in /WEB-INF/classes. If you're developing a standard WAR project in an IDE, drop it in src folder (the project's source folder). If you're using a Maven project, drop it in /main/resources folder.
You can alternatively also put it somewhere outside the default classpath and add its path to the classpath of the appserver. In for example Tomcat you can configure it as shared.loader property of Tomcat/conf/catalina.properties.
If you have placed the foo.properties it in a Java package structure like com.example, then you need to load it as below
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("com/example/foo.properties");
// ...
Note that this path of a context class loader should not start with a /. Only when you're using a "relative" class loader such as SomeClass.class.getClassLoader(), then you indeed need to start it with a /.
ClassLoader classLoader = getClass().getClassLoader();
InputStream input = classLoader.getResourceAsStream("/com/example/foo.properties");
// ...
However, the visibility of the properties file depends then on the class loader in question. It's only visible to the same class loader as the one which loaded the class. So, if the class is loaded by e.g. server common classloader instead of webapp classloader, and the properties file is inside webapp itself, then it's invisible. The context class loader is your safest bet so you can place the properties file "everywhere" in the classpath and/or you intend to be able to override a server-provided one from the webapp on.
2. Put it in webcontent
So that you can load it by ServletContext#getResourceAsStream() with a webcontent-relative path:
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties");
// ...
Note that I have demonstrated to place the file in /WEB-INF folder, otherwise it would have been public accessible by any webbrowser. Also note that the ServletContext is in any HttpServlet class just accessible by the inherited GenericServlet#getServletContext() and in Filter by FilterConfig#getServletContext(). In case you're not in a servlet class, it's usually just injectable via #Inject.
3. Put it in local disk file system
So that you can load it the usual java.io way with an absolute local disk file system path:
InputStream input = new FileInputStream("/absolute/path/to/foo.properties");
// ...
Note the importance of using an absolute path. Relative local disk file system paths are an absolute no-go in a Java EE web application. See also the first "See also" link below.
Which to choose?
Just weigh the advantages/disadvantages in your own opinion of maintainability.
If the properties files are "static" and never needs to change during runtime, then you could keep them in the WAR.
If you prefer being able to edit properties files from outside the web application without the need to rebuild and redeploy the WAR every time, then put it in the classpath outside the project (if necessary add the directory to the classpath).
If you prefer being able to edit properties files programmatically from inside the web application using Properties#store() method, put it outside the web application. As the Properties#store() requires a Writer, you can't go around using a disk file system path. That path can in turn be passed to the web application as a VM argument or system property. As a precaution, never use getRealPath(). All changes in deploy folder will get lost on a redeploy for the simple reason that the changes are not reflected back in original WAR file.
See also:
getResourceAsStream() vs FileInputStream
Adding a directory to tomcat classpath
Accessing properties file in a JSF application programmatically
Word of warning: if you put config files in your WEB-INF/classes folder, and your IDE, say Eclipse, does a clean/rebuild, it will nuke your conf files unless they were in the Java source directory. BalusC's great answer alludes to that in option 1 but I wanted to add emphasis.
I learned the hard way that if you "copy" a web project in Eclipse, it does a clean/rebuild from any source folders. In my case I had added a "linked source dir" from our POJO java library, it would compile to the WEB-INF/classes folder. Doing a clean/rebuild in that project (not the web app project) caused the same problem.
I thought about putting my confs in the POJO src folder, but these confs are all for 3rd party libs (like Quartz or URLRewrite) that are in the WEB-INF/lib folder, so that didn't make sense. I plan to test putting it in the web projects "src" folder when i get around to it, but that folder is currently empty and having conf files in it seems inelegant.
So I vote for putting conf files in WEB-INF/commonConfFolder/filename.properties, next to the classes folder, which is Balus option 2.
Ex: In web.xml file the tag
<context-param>
<param-name>chatpropertyfile</param-name>
<!-- Name of the chat properties file. It contains the name and description of rooms.-->
<param-value>chat.properties</param-value>
</context-param>
And chat.properties you can declare your properties like this
For Ex :
Jsp = Discussion about JSP can be made here.
Java = Talk about java and related technologies like J2EE.
ASP = Discuss about Active Server Pages related technologies like VBScript and JScript etc.
Web_Designing = Any discussion related to HTML, JavaScript, DHTML etc.
StartUp = Startup chat room. Chatter is added to this after he logs in.
It just needs to be in the classpath (aka make sure it ends up under /WEB-INF/classes in the .war as part of the build).
You can you with your source folder so whenever you build, those files are automatically copied to the classes directory.
Instead of using properties file, use XML file.
If the data is too small, you can even use web.xml for accessing the properties.
Please note that any of these approach will require app server restart for changes to be reflected.
Assume your code is looking for the file say app.properties. Copy this file to any dir and add this dir to classpath, by creating a setenv.sh in the bin dir of tomcat.
In your setenv.sh of tomcat( if this file is not existing, create one , tomcat will load this setenv.sh file.
#!/bin/sh
CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"
You should not have your properties files in ./webapps//WEB-INF/classes/app.properties
Tomcat class loader will override the with the one from WEB-INF/classes/
A good read:
https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html

Why is Spring Boot's resource precedence ignoring my external properties files?

As part of a Spring Boot project I need to load certain properties file which, by default, is located under de src/main/resources directory. Also, I need to be able to, instead, load an external properties file (located at the root directory of the project). If this external file exists, the file path should be passed as command line property.
The file structure would be like this:
/app_project
Net.properties (external file)
/src
/main
/resources
Net.properties (default file)
The thing is that the dependency that makes use of those properties wouldn't work unless you copy/overwrite the contents of the external file into the file under the /resources directory.
UPDATED
So far I've tried:
loading the file as an external resource and loading it into a Properties object (https://docs.oracle.com/javase/7/docs/api/java/util/Properties.html)
saving the properties as System Properties
modifying the resource handler to look into other directories by overriding th addResourceHandlers() to include the location
Explicitly including the location of the file in the CLASSPATH with the -cp argument (as #veysiertekin suggested)
Loading it as a #PropertySource (as suggesed by #Nikolay Shevchenko)
Overriding the Spring Boot's config location with the spring.config.location (as suggested by #gWombat)
With all these methods I've tried, the file is indeed read and loaded but, at some point, and every time, the app resorts to the file under src/main/resources .
I suspect it may have to do with the precedence of the file (as described here https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html), but I just couldn't figure out what's happening.
Thanks in advance for your help.
Try smth like
#PropertySources({
#PropertySource(name = "default", value = "classpath:default.properties"),
#PropertySource(name = "external", value = "classpath:external.properties", ignoreResourceNotFound = true)
})
public class YourSpringBootApplication {
...
}
Based on the official doc, you can try to use the propertyspring.config.additional-location to add additional config file , or spring.config.location to override default file location.
You should pass those properties as program arguments so that Spring can use them on application startup.
When spring-boot project is running, it checks files under the builded jar file. You need to add your external file to classpath before running the application:
java -cp 'path-to/spring-boot-application.jar:Net.properties' test.SpringBootApplicationMain

Runnable JAR properties file, refer to local driver [duplicate]

In my web application I have to send email to set of predefined users like finance#xyz.example, so I wish to add that to a .properties file and access it when required. Is this a correct procedure, if so then where should I place this file? I am using Netbeans IDE which is having two separate folders for source and JSP files.
It's your choice. There are basically three ways in a Java web application archive (WAR):
1. Put it in classpath
So that you can load it by ClassLoader#getResourceAsStream() with a classpath-relative path:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);
Here foo.properties is supposed to be placed in one of the roots which are covered by the default classpath of a webapp, e.g. webapp's /WEB-INF/lib and /WEB-INF/classes, server's /lib, or JDK/JRE's /lib. If the propertiesfile is webapp-specific, best is to place it in /WEB-INF/classes. If you're developing a standard WAR project in an IDE, drop it in src folder (the project's source folder). If you're using a Maven project, drop it in /main/resources folder.
You can alternatively also put it somewhere outside the default classpath and add its path to the classpath of the appserver. In for example Tomcat you can configure it as shared.loader property of Tomcat/conf/catalina.properties.
If you have placed the foo.properties it in a Java package structure like com.example, then you need to load it as below
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("com/example/foo.properties");
// ...
Note that this path of a context class loader should not start with a /. Only when you're using a "relative" class loader such as SomeClass.class.getClassLoader(), then you indeed need to start it with a /.
ClassLoader classLoader = getClass().getClassLoader();
InputStream input = classLoader.getResourceAsStream("/com/example/foo.properties");
// ...
However, the visibility of the properties file depends then on the class loader in question. It's only visible to the same class loader as the one which loaded the class. So, if the class is loaded by e.g. server common classloader instead of webapp classloader, and the properties file is inside webapp itself, then it's invisible. The context class loader is your safest bet so you can place the properties file "everywhere" in the classpath and/or you intend to be able to override a server-provided one from the webapp on.
2. Put it in webcontent
So that you can load it by ServletContext#getResourceAsStream() with a webcontent-relative path:
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties");
// ...
Note that I have demonstrated to place the file in /WEB-INF folder, otherwise it would have been public accessible by any webbrowser. Also note that the ServletContext is in any HttpServlet class just accessible by the inherited GenericServlet#getServletContext() and in Filter by FilterConfig#getServletContext(). In case you're not in a servlet class, it's usually just injectable via #Inject.
3. Put it in local disk file system
So that you can load it the usual java.io way with an absolute local disk file system path:
InputStream input = new FileInputStream("/absolute/path/to/foo.properties");
// ...
Note the importance of using an absolute path. Relative local disk file system paths are an absolute no-go in a Java EE web application. See also the first "See also" link below.
Which to choose?
Just weigh the advantages/disadvantages in your own opinion of maintainability.
If the properties files are "static" and never needs to change during runtime, then you could keep them in the WAR.
If you prefer being able to edit properties files from outside the web application without the need to rebuild and redeploy the WAR every time, then put it in the classpath outside the project (if necessary add the directory to the classpath).
If you prefer being able to edit properties files programmatically from inside the web application using Properties#store() method, put it outside the web application. As the Properties#store() requires a Writer, you can't go around using a disk file system path. That path can in turn be passed to the web application as a VM argument or system property. As a precaution, never use getRealPath(). All changes in deploy folder will get lost on a redeploy for the simple reason that the changes are not reflected back in original WAR file.
See also:
getResourceAsStream() vs FileInputStream
Adding a directory to tomcat classpath
Accessing properties file in a JSF application programmatically
Word of warning: if you put config files in your WEB-INF/classes folder, and your IDE, say Eclipse, does a clean/rebuild, it will nuke your conf files unless they were in the Java source directory. BalusC's great answer alludes to that in option 1 but I wanted to add emphasis.
I learned the hard way that if you "copy" a web project in Eclipse, it does a clean/rebuild from any source folders. In my case I had added a "linked source dir" from our POJO java library, it would compile to the WEB-INF/classes folder. Doing a clean/rebuild in that project (not the web app project) caused the same problem.
I thought about putting my confs in the POJO src folder, but these confs are all for 3rd party libs (like Quartz or URLRewrite) that are in the WEB-INF/lib folder, so that didn't make sense. I plan to test putting it in the web projects "src" folder when i get around to it, but that folder is currently empty and having conf files in it seems inelegant.
So I vote for putting conf files in WEB-INF/commonConfFolder/filename.properties, next to the classes folder, which is Balus option 2.
Ex: In web.xml file the tag
<context-param>
<param-name>chatpropertyfile</param-name>
<!-- Name of the chat properties file. It contains the name and description of rooms.-->
<param-value>chat.properties</param-value>
</context-param>
And chat.properties you can declare your properties like this
For Ex :
Jsp = Discussion about JSP can be made here.
Java = Talk about java and related technologies like J2EE.
ASP = Discuss about Active Server Pages related technologies like VBScript and JScript etc.
Web_Designing = Any discussion related to HTML, JavaScript, DHTML etc.
StartUp = Startup chat room. Chatter is added to this after he logs in.
It just needs to be in the classpath (aka make sure it ends up under /WEB-INF/classes in the .war as part of the build).
You can you with your source folder so whenever you build, those files are automatically copied to the classes directory.
Instead of using properties file, use XML file.
If the data is too small, you can even use web.xml for accessing the properties.
Please note that any of these approach will require app server restart for changes to be reflected.
Assume your code is looking for the file say app.properties. Copy this file to any dir and add this dir to classpath, by creating a setenv.sh in the bin dir of tomcat.
In your setenv.sh of tomcat( if this file is not existing, create one , tomcat will load this setenv.sh file.
#!/bin/sh
CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"
You should not have your properties files in ./webapps//WEB-INF/classes/app.properties
Tomcat class loader will override the with the one from WEB-INF/classes/
A good read:
https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html

Adding spring XML files to classpath (Windows cmd-line)

I am trying to run a jar file via cmd line that uses Spring and a spring xml configuration file.
The cmd line call is similar to:
java -cp lib/MyJar.jar my.package.MyClass
The error I get is:
Caused by: java.io.FileNotFoundException: class path resource
[myPath/mySpringCfg.xml] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:157)
My manifest classpath is similar to:
Class-Path: 3rdPartyJar1.jar 3rdPartyJar2.jar ./myPath/
The call that loads the file equates to:
context = new ClassPathXmlApplicationContext("myPath/mySpringCfg.xml");
Is there a way to correctly pull in XML files in the classpath so that Spring will work as expected? It seems like the classpath docs only talk about archive files and folders.
Thanks!
UPDATE
It seems to run fine when I switch over to FileSystemXmlApplicationContext. I guess the ClassPathXmlApplicationContext cannot be used from command-line
Your reference to the XML is myPath/mySpringCfg.xml - this means that myPath has to be in the classpath.
Change your manifest to be:
Class-Path: 3rdPartyJar1.jar 3rdPartyJar2.jar ./
This way myPath will be a part of the classpath and not just its contents.
Note:
The application configuration XML is a part of your application's code, don't mistake it for a configuration.
If you want configuration - put it outside in a properties file and use place-holders in your XML configuration file.
Update:
I think the root cause of your problem is in the code (I didn't test it though) - try this instead:
context = new ClassPathXmlApplicationContext("/myPath/mySpringCfg.xml");
The difference is in the '/' before 'myPath'
I am not aware of the architecture of your project, but why not place your xml configuration file into your project jar?

Where should I put the log4j.properties file?

I wrote a web service project using netbeans 6.7.1 with glassfish v2.1, put log4j.properties to the root dir of project and use:
static Logger logger = Logger.getLogger(MyClass.class);
in Constructor:
PropertyConfigurator.configure("log4j.properties");
and in functions:
logger.info("...");
logger.error("...");
// ...
but, it is error info(actually, I have tried to put it almost every dir that I could realize):
log4j:ERROR Could not read configuration file [log4j.properties].
java.io.FileNotFoundException: log4j.properties (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:106)
at java.io.FileInputStream.<init>(FileInputStream.java:66)
at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:297)
at org.apache.log4j.PropertyConfigurator.configure(PropertyConfigurator.java:315)
at com.corp.ors.demo.OrsDemo.main(OrisDemo.java:228)
log4j:ERROR Ignoring configuration file [log4j.properties].
log4j:WARN No appenders could be found for logger (com.corp.ors.demo.OrsDemo).
log4j:WARN Please initialize the log4j system properly.
the example project could be get from http://www.91files.com/?N3F0QGQPWMDGPBRN0QA8
I know it's a bit late to answer this question, and maybe you already found the solution, but I'm posting the solution I found (after I googled a lot) so it may help a little:
Put log4j.properties under WEB-INF\classes of the project as mentioned previously in this thread.
Put log4j-xx.jar under WEB-INF\lib
Test if log4j was loaded: add -Dlog4j.debug # the end of your java options of tomcat
Hope this will help.
rgds
As already stated, log4j.properties should be in a directory included in the classpath, I want to add that in a mavenized project a good place can be src/main/resources/log4j.properties
You can specify config file location with VM argument -Dlog4j.configuration="file:/C:/workspace3/local/log4j.properties"
You have to put it in the root directory, that corresponds to your execution context.
Example:
MyProject
src
MyClass.java
log4j.properties
If you start executing from a different project, you need to have that file in the project used for starting the execution. For example, if a different project holds some JUnit tests, it needs to have also its log4j.properties file.
I suggest using log4j.xml instead of the log4j.properties. You have more options, get assistance from your IDE and so on...
For a Maven Based Project keep your log4j.properties in src/main/resources. Nothing else to do!
If you put log4j.properties inside src, you don't need to use the statement -
PropertyConfigurator.configure("log4j.properties");
It will be taken automatically as the properties file is in the classpath.
Try:
PropertyConfigurator.configure(getClass().getResource("/controlador/log4j.properties"));
The file should be located in the WEB-INF/classes directory.
This directory structure should be packaged within the war file.
My IDE is NetBeans. I put log4j.property file as shown in the pictures
Root
Web
WEB-INF
To use this property file you should to write this code:
package example;
import java.io.File;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.Logger;
import javax.servlet.*;
public class test {
public static ServletContext context;
static Logger log = Logger.getLogger("example/test");
public test() {
String homeDir = context.getRealPath("/");
File propertiesFile = new File(homeDir, "WEB-INF/log4j.properties");
PropertyConfigurator.configure(propertiesFile.toString());
log.info("This is a test");
}
}
You can define static ServletContext context from another JSP file.
Example:
test.context = getServletContext();
test sample = new test();
Now you can use log4j.property file in your projects.
A few technically correct specific answers already provided but in general, it can be anywhere on the runtime classpath, i.e. wherever classes are sought by the JVM.
This could be the /src dir in Eclipse or the WEB-INF/classes directory in your deployed app, but it's best to be aware of the classpath concept and why the file is placed in it, don't just treat WEB-INF/classes as a "magic" directory.
I've spent a great deal of time to figure out why the log4j.properties file is not seen.
Then I noticed it was visible for the project only when it was in both MyProject/target/classes/ and MyProject/src/main/resources folders.
Hope it'll be useful to somebody.
PS: The project was maven-based.
I found that Glassfish by default is looking at [Glassfish install location]\glassfish\domains[your domain]\ as the default working directory... you can drop the log4j.properties file in this location and initialize it in your code using PropertyConfigurator as previously mentioned...
Properties props = System.getProperties();
System.out.println("Current working directory is " + props.getProperty("user.dir"));
PropertyConfigurator.configure("log4j.properties");
Your standard project setup will have a project structure something like:
src/main/java
src/main/resources
You place log4j.properties inside the resources folder, you can create the resources folder if one does not exist
I don't know this is correct way.But it solved my problem.
put log4j.properties file in "project folder"/config and use PropertyConfigurator.configure("config//log4j.properties");
it will works with IDE but not when run the jar file yourself.
when you run the jar file by yourself just copy the log4j.properties file in to the folder that jar file is in.when the jar and property file in same directory it runs well.
Put log4j.properties in classpath.
Here is the 2 cases that will help you to identify the proper location-
1. For web application the classpath is /WEB-INF/classes.
\WEB-INF
classes\
log4j.properties
To test from main / unit test the classpath is source directory
\Project\
src\
log4j.properties
There are many ways to do it:
Way1: If you are trying in maven project without Using PropertyConfigurator
First:
check for resources directory at scr/main
if available,
then: create a .properties file and add all configuration details.
else
then: create a directory named resources and a file with .properties
write your configuration code/details.
follows the screenshot:
Way2: If you are trying with Properties file for java/maven project Use PropertyConfigurator
Place properties file anywhere in project and give the correct path.
say: src/javaLog4jProperties/log4j.properties
static{
PropertyConfigurator.configure("src/javaLog4jProperties/log4j.properties");
}
Way3: If you are trying with xml on java/maven project Use DOMConfigurator
Place properties file anywhere in project and give correct path.
say: src/javaLog4jProperties/log4j.xml
static{
DOMConfigurator.configure("src/javaLog4jProperties/log4j.xml");
}
For me, it worked when I put the file inside the resources folder.
Also, it was a war file for my project. My recommendation is to ensure that the name of the file is log4j.properties, as my project didn't recognize "log4j2.properties"
Actually, I've just experienced this problem in a stardard Java project structure as follows:
\myproject
\src
\libs
\res\log4j.properties
In Eclipse I need to add the res folder to build path, however, in Intellij, I need to mark the res folder as resouces as the linked screenshot shows: right click on the res folder and mark as resources.
You don't need to specify PropertyConfigurator.configure("log4j.properties"); in your Log4J class, If you have already defined the log4j.properties in your project structure.
In case of Web Dynamic Project: -
You need to save your log4j.properties under WebContent -> WEB-INF -> log4j.properties
I hope this may help you.
Open spark-shell
Then type System.getenv("SPARK_CONF_DIR")
That will print where your log4j.properties should go.

Categories

Resources