Where put log4j properies file? - java

I added in .pom file
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Generally it works. But where should I put log4j.properites file? I tried put it everywhere. In WEB-INF, resources folder. I put this file in each folder in my app. And manually to class dir in .war file.
Didn't work.
Also I tried modify Jboss logging properies file. But it's not logging my log, only Jboss logs.
How can I change logging pattern and output file?
In pom file I also have
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
src/main/resources/log4j.properties
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.ConversionPattern=%m\n
log4j.category.com.devdaily.log4jdemo.Log4JDemo=INFO, STDOUT
In java code
private static Logger log = Logger.getLogger(Test.class);
log.error("aaaaaaaa");
Console output
11:28:50,247 ERROR [Test] (http--127.0.0.1-8080-1) aaaaaaaa
Where I make mistake in my .properties file I get error on console. My .properies file. Maybe it's mistake inside?
log4j.appender.NotConsole=org.apache.log4j.RollingFileAppender
log4j.appender.NotConsole.fileName=/home/mateusz/log4j/ussd.log
log4j.appender.NotConsole.maxFileSize=20MB
log4j.appender.STDOUT.layout.ConversionPattern=<%d{HH:mm:ss,SSS}><%-5p><%C><%t><%x><%m>%n

I added dependency to my pom.xml with log4j, but configuration file is in in jboss7dir/standalone/configuration/standalone.xml It's logging my app (I,m using log4j normally) and some jboss log.

you can put log4.properties in the project's root folder.

Related

Log4j2 api cannot find Log4j2 core in OSGi environment

I'm trying to use log4j2 OSGi bundles, but it seems log4j2 api cannot find log4j2 core in an OSGi environment. I'm continuously getting the following exception :
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console
I found the same exception discussed in few places but still I could not figure out this issue. Isuspect I'm getting this issue because log4j2 api cannot find the log4j-provider.properties inside the META-INF directory of log4j2 core.
Is there any clue why I'm getting this exception and how can I correct the issue ?
(If anybody has correct pom file for adding log4j dependencies and bundling please share it with me)
These are the dependencies I have used
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.2</version>
</dependency>
I use apache felix as the bundle plugin. This error occures because resources inside the META-INF of log4j2-core specially the log4j-providoer.properties file is not visible to log4j api.
Thanks!
The log4j-core bundle registers a bundle listener when the Activator is started and starts searching for log plugins and if something is found it performs a sequence of operations similar to the usual Logger initialization (not really idiomatic OSGi stuff and i'm not sure it works, but it seems to set at least Log4jContextSelector and LoggerContextFactory), just to be sure of it, did you install and start the log4j-core bundle and verified that nothing changed?
Update:
I did some testing and found what is an acceptable solution/workaround for log4j2 OSGi issues. But as someone else recommended, alternatively i would use slf4j, pax-logging or simply the OSGi Log Service (the simpler of the bunch).
#Grant, you have 2 separate things that need to be fixed:
1. As you described, the "Log4j2 could not find a logging implementation" error is caused by the fact that the log4j2-api bundle is unable to find the log4j-provider.properties file and, after that is fixed, log4j2-api cannot find the log4j2-core classes (it's a different bundle and log4j2-api doesn't have a specific Import-Package: for those classes).
The workaround for this is to create a small fragment bundle for log4j2-api (i called mine log4j-api-config.jar) with that .properties file in META-INF and a manifest that forces a dynamic import:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Log4j API configurator
Bundle-SymbolicName: org.apache.logging.log4j.apiconf
Bundle-Version: 1.0.0
Bundle-Vendor: None
Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.2
Fragment-Host: org.apache.logging.log4j.api
DynamicImport-Package: *
I'm importing * here, you can improve it adding the required subset of log4j2-core packages that log4j2-api needs.
With this, that error will disappear, but log4j will notice that you didn't provide a log4j2 configuration file, next thing to fix (only if you care in this case).
2. At this point Felix will display this:
log4j2.xml not found by org.apache.logging.log4j.core
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
and i suppose you could want to add your own log4j2.xml without messing with the original log4j2-core.jar. You can do this creating another fragment bundle, this time hosted by log4j2-core, with just a log4j2.xml configuration file in the root and a simple manifest:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Log4j Core configurator
Bundle-SymbolicName: org.apache.logging.log4j.coreconf
Bundle-Version: 1.0.0
Bundle-Vendor: None
Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.2
Fragment-Host: org.apache.logging.log4j.core
I used this simple log4j2.xml configuration during my tests:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
With this you will not need that sort of "bridge" bundle you described below anymore, and you'll just need a simple Import-Package: org.apache.logging.log4j to use log4j from your bundle.
Update 2:
Important to note that the two fragments are NOT dependencies of the original bundles (no need to modify log4j jars or or even your bundles to add import/export), so the original bundles and your own custom ones will remain untouched.
Also, they don't depend on the original bundle either, they are just basic jar archive with a manifest and an additional text file, no code, no need for Import-Package or Export-Package.
You just need to install each fragment after their host bundle is installed.
I've created both fragments manually starting from an empty jar and copying inside the archive the properties file and modifying the MANIFEST.MF with a text editor, you can create them both with this pom.xml, remember to copy log4j-provider.properties where pom.xml is located.
For the log4j2-api fragment:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.group</groupId>
<artifactId>log4j2-api-config</artifactId>
<version>1.0</version>
<name>log4j2-api-config</name>
<packaging>bundle</packaging>
<properties>
<java-version>1.7</java-version>
</properties>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.0.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>org.apache.logging.log4j.apiconf</Bundle-SymbolicName>
<Bundle-Name>Log4j API Configurator</Bundle-Name>
<Bundle-Version>1.0.0</Bundle-Version>
<Fragment-Host>org.apache.logging.log4j.api</Fragment-Host>
<DynamicImport-Package>
*;resolution:=optional
</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>.</directory>
<includes>
<include>log4j-provider.properties</include>
</includes>
<targetPath>META-INF</targetPath>
</resource>
</resources>
</build>
</project>
Modify this pom where appropriate(included file, bundle names) to generate the other one with the log4j2-core configuration.
Log4j is not suitable for an OSGi environment. Luckily there is a nice drop in replacement pax-logging. In your bundle you use the log4j api or any other of the supported apis (I prefer slf4j-api). Then you deploy pax logging to your OSGi framework and your bundle.
You can configure pax logging using a standard log4j config. So it is very easy to use. If you want a really easy start you can simply install apache karaf and deploy your bundle to it. Karaf already includes a fully set up pax logging.
Try changing the name of the jar file something does not contain core word (eg:log4j-zore) and try again
You need specify OSGI related dependencies on Your bundle in META-INF/MANIFEST.MF by add the following dependencies:
Require-Bundle: org.apache.logging.log4j.core;org.apache.logging.log4j.api
For me this error is resolved by:
ensuring that the log4j-api bundle is actually activated - and not just resolved - before calling the logger. I did this by setting it to Auto-Start with a low start level.
let log4j-api import classes of log4j-core (as mentioned by #uraime) to make sure it finds log4j-core. The cleanest way to do this is using a fragment. Instead of dynamic import you could also add this to the manifest:
Require-Bundle: org.apache.logging.log4j.core
I also use a fragment for log4j-core to let it find my log4j2.xml configuration file, but when not using this fragment, log4j will show a different error message.
Additionally I found that it's not required for the log4j-core bundle to be activated (only resolved) but note that this does mean that the Activator cannot find custom log4j2 plugins.

Internationalization Maven application

Actually, I've created two files (MessageBundle_fr_BE and MessageBundle_us_US) where I put the different text to translate to internationalize my application
My problem is when I launch the application, I've following error :
Problem accessing /MyServlet. Reason:
Can't find bundle for base name MessageBundle, locale fr_FR
Caused by:
java.util.MissingResourceException: Can't find bundle for base name MessageBundle, locale fr_FR
at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:1499)
at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1322)
at java.util.ResourceBundle.getBundle(ResourceBundle.java:796)
at com.application.myGoogleAppEngine.Internationale.<init>(Internationale.java:13)
at com.application.myGoogleAppEngine.Internationale.getInstance(Internationale.java:18)
at com.application.myGoogleAppEngine.MyServlet.doPost(MyServlet.java:52)
at com.application.myGoogleAppEngine.MyServlet.doGet(MyServlet.java:30)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
The project structure is below :
- src
- main
- webapp
- images
- js
- stylesheets
- resources
MessageBundle_fr_FR.properties
MessageBundle_us_US.properties
- WEB-INF
- appengine-web.xml
- logging.properties
- web.xml
- index.jsp
- java
- com.application.myGoogleApp
- test
- target
- pom.xml
- nbActions.xml
- README.md
And a part of my pom.xml to include 'src/main/webapp/resources' directory:
<configuration>
<archiveClasses>true</archiveClasses>
<webResources>
<!-- in order to interpolate version from pom into appengine-web.xml -->
<resource>
<directory>${basedir}/src/main/webapp/WEB-INF</directory>
<filtering>true</filtering>
<targetPath>WEB-INF</targetPath>
</resource>
<resource>
<directory>${basedir}/src/main/webapp/resources</directory>
</resource>
</webResources>
</configuration>
Can you help me ?
Thank you
ResourceBundle.getBundle will only look in the classpath. It has no knowledge of .war files or servlets. You must place the .properties files in WEB-INF/classes.
I can see that you are using maven archetypes. So, I suggest to have template below:
src/main/java
src/main/resources
-MessageBundle_fr_FR.properties
-MessageBundle_us_US.properties
src/main/webapp
You must create src/main/resources and move your properties to this folder.

FileNotFoundException for bean definition file happens only online, not on localhost

When I published a war file for an application that works locally with Eclipse WTP, I had a FileNotFoundException for the bean.xml file with my beans definitions.
SEVERE: Exception sending context initialized event to listener instance of
class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanDefinitionStoreException:
IOException parsing XML document from class path resource
[META-INF/spring/beans.xml]; nested exception is java.
io.FileNotFoundException: class path resource [META-INF/spring/beans.xml]
cannot be opened because it does not exist
at Caused by: java.io.FileNotFoundException: class path resource
[META-INF/spring/beans.xml] cannot be opened because it does not exist
...
I created the war file with mvn war:war and copied in the webapps folder of Tomcat 7.
beans.xml is located in src/main/resources/META-INF/spring/beans.xml and I've the following in my pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<webResources>
<resource>
<directory>src/main/resources</directory>
</resource>
</webResources>
</configuration>
</plugin>
In the war file beans.xml gets packaged in META-INF/spring/beans.xml
In my web.xml I've:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:META-INF/spring/beans.xml</param-value>
</context-param>
However the file is not found. How to solve the problem?
UPDATE: as Matthew Farwell suggested, is bean.xml is not packaged in the right location, so it's not in the class path, I think it's specified with maven-war-plugin parameters, now I try to look at its documentation. If someone knows it would be helpful.
UPDATE 2: As explained in maven-war-plugin documentation, there is an optional parameter called targetPath. I tried and after changing maven-war-plugin configuration adding targetPath it gets packaged correctly.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<webResources>
<resource>
<directory>src/main/resources</directory>
<targetPath>WEB-INF/classes</targetPath>
</resource>
</webResources>
</configuration>
</plugin>
UPDATE 3: About Ryan Stewart's suggestion, I started my initial pom setup using roo, but after that I've done many changes and I'm not using roo any more. The directory src/main/resources is not mentioned in any other places in pom.xml (I've used grep), however the only setting that looks suspicious to me is:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration><encoding>UTF-8</encoding></configuration>
</plugin>
I've commented out that plugin, but nothing changed, then I commented out the configuration part of maven-war-plugin, but src/main/resources was not added to the war anymore, so for now I've added it back and I'm uploading it to test it online (it's still a staging server actually, not the final one anyway).
UPDATE 4 Ryan Stewart suggested that the problem was that I was running "mvn war:war" instead of "mvn package", and that was indeed the problem. With my targetPath, the resources appeared in WEB-INF/classes, but there weren't any classes there.
I was fighting an uphill battle, while instead the simpler solution was to remove the configuration part as in update 3, and use "mvn package" to build the war file. Thank you to both of you Ryan and Matthew, not only I solved my problem, but I've also learnt something more about Maven.
I have to assume you have another part of the POM that's excluding the file in question from being processed as a classpath resource, else it should be working. Either
Stop doing that, and it'll work fine--the content of src/main/resources becomes classpath resources by default--or
remove the classpath: from your path. Without that prefix, the path given in contextConfigLocation will be resolved against the root of the WAR file, and it will correctly find your file in META-INF/spring.
If you take path 1, then you should remove the webResources section, or you'll end up with the file in two places--not problematic, but potentially confusing.
In a war, / is not part of the classpath for a webapp. The classpath includes /WEB-INF/classes and all of the jars in /lib. See Apache Tomcat 6.0 - Class Loader HOW-TO
WebappX — A class loader is created for each web application that is
deployed in a single Tomcat instance. All unpacked classes and
resources in the /WEB-INF/classes directory of your web application,
plus classes and resources in JAR files under the /WEB-INF/lib
directory of your web application, are made visible to this web
application, but not to other ones.
The other web servers will have similar rules. If you wish to reference something as part of the classpath, put it in WEB-INF/classes.

Send/redirect/route java.util.logging.Logger (JUL) to Logback using SLF4J?

Is it possible to have a typical call to java.util.logging.Logger and have it route to Logback using SLF4J? This would be nice since I wouldn't have to refactor the old jul code line by line.
EG, say we have this line:
private static Logger logger = Logger.getLogger(MahClass.class.getName());
//...
logger.info("blah blah blah");
It would be nice to configure this to call through SLF4J.
It's very easy and not a performance issue anymore.
There are two ways documented in the SLF4J manual. There are also precise examples in the Javadocs
Add jul-to-slf4j.jar to your classpath. Or through maven dependency:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.0</version>
</dependency>
If you don't have logging.properties (for java.util.logging), add this to your bootstrap code:
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
If you have logging.properties (and want to keep it), add this to it:
handlers = org.slf4j.bridge.SLF4JBridgeHandler
In order to avoid performance penalty, add this contextListener to logback.xml (as of logback version 0.9.25):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<!-- reset all previous level configurations of all j.u.l. loggers -->
<resetJUL>true</resetJUL>
</contextListener>
...
</configuration>

Using log4j on Google App Engine

I need to use log4j in my application, but I don't know how I can get properties loaded. Deafult properties files says that I should put log4j.properties to /WEB-INF/classes/ folder, but in eclipse I cannot see that folder and I cannot create it, because it already exists. And I cannot add any files to that folder either.
Here is error that I get:
log4j:WARN No appenders could be found for logger (DataNucleus.ClassLoading).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
So how can I get web application to load log4j properties?
Put the log4j.properties file into a source directory of your project, e.g. /src. Eclipse will copy it into your target build directory.
I recomend using SLF4J with Log4J, and the SpringSource Tool Suite (STS) for your project.
Here is how to get log4j working using Eclipse with the Google plugin.
Modify appengine-web.xml as follows:
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/classes/log4j.properties"/>
</system-properties>
You can add the following code to your servlet:
import org.apache.log4j.Logger;
...
Logger logger = Logger.getLogger("com.foo");
logger.debug("Yay2!");
Put the log4j.properties file in the src/ directory with the following content:
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{1}:%M:%L - %m%n
You can do a Project > Clean then allow it to automatically build, The build copies the log4j.properties file to /war/WEB-INF/classes/. You'll see the log displayed when you Run As > Web Application and request a URL.
I know that you're not using Maven but I will add instructions below in case anyone else needs them. These instructions will work with com.google.appengine.archetypes:guestbook-archetype.
Add the following to pom.xml:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
Add the following code to guestbook.jsp:
<%# page import="org.apache.log4j.Logger" %>
...
<%
Logger logger = Logger.getLogger("com.foo");
logger.debug("Yay2!");
%>
Create src/main/webapp/WEB-INF/classes/log4j.properties with the same content as above.
Then run:
mvn clean
mvn verify
mvn appengine:devserver
You will see log output in our console after calling http://localhost:8080/.
I have to put the log4j.properties and then configured in web.xml:
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
That way it runs before the classpath loading and it works.
Although it doesn't send the JUL stuff to log4j, so you will need a separated configuration to do that.
Ignore everything you see in the internet for the keywords spring + log4j + appengine.
The solution that worked for me and didn't created ambiguity was to leave JUL be and configure log4j with spring separately in this way:
public class CustomXmlWebApplicationContext extends XmlWebApplicationContext {
#Override
protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
super.initBeanDefinitionReader(beanDefinitionReader);
try {
Resource res = beanDefinitionReader.getResourceLoader().getResource("classpath:log4j.properties");
Properties props = new Properties();
props.load(res.getInputStream());
PropertyConfigurator.configure(props);
}
catch(Throwable e) {
e.printStackTrace();
}
}
}
Then just put your log4j.properties in the root of your source folder.
There is a good article on Logging in the Google AppEngine for Java (GAE/J) with Slf4j, Log4j and JUL.
In \src\main\webapp\WEB-INF\appengine-web.xml you need to have
appengine-web.xml
<!-- Configure java.util.logging -->
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/java-util-logging.properties"/>
</system-properties>
to tell GAE where java.util.logging (JUL) is configured.
In \src\main\webapp\WEB-INF\java-util-logging.properties you need
java-util-logging.properties
.level = ALL
or another of the JUL level names, as you like (i.e. 'TRACE' does not work).
In \src\main\resources\log4j.properties file you will have
log4j.properties
log4j.rootLogger=ALL, stdout
# or a lower log level such as DEBUG, INFO or WARN.
# Define the destination and format of our logging
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p: %m at %C.(%F:%L) on %d{ISO8601}%n
You need to add log4j to your CLASSPATH. I use Gradle for dependency management, so here is my build script:
build.gradle
configurations {
all*.exclude group: "commons-logging", module: "commons-logging"
}
dependencies {
// Logging
compile 'org.slf4j:slf4j-api:1.7.+'
runtime 'org.slf4j:slf4j-jdk14:1.7.+'
runtime ('log4j:log4j:1.2.17') {
exclude group: "com.sun.jdmk", module: "jmxtools"
exclude group: "com.sun.jmx", module: "jmxri"
exclude group: "javax.mail", module: "mail"
exclude group: "javax.jms", module: "jms"
}
}
If you are using Spring WebMVC, in order to provide a Log4J configuration file when starting up your application add the following listener to your Deployment descriptor.
web.xml
<!-- The definition of the Log4j Configuration -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>

Categories