Using log4j on Google App Engine - java

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>

Related

Spring boot + maven not printing logs on console

Running spring boot/java test project using maven through terminal is not printing logs.However when I run the project through Intellij(run configuration), it does print logs.
I have tried enable logging for spring boot by enabling logs in application.yml file but it didn't work. I have also observed that since intellij uses java to run the test project logging works however I am using maven from terminal so it doesn't work.
logging:
level:
root: INFO
org.package INFO
Enable logs in spring boot java project that prints stuff on terminal.
Besides from the indentation, you are missing the:
logging:
level:
root: INFO
org.package: INFO
Also, you can configure the Logback for Spring-Boot, here is how to: logback
Basically, creating a logback.xml file in the resources path, with the content of:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="org.springframework.web" level="DEBUG"/>
</configuration>
Here it is also another great tutorial: here

spring boot .war tomcat application logs not there

I am trying to write to my webapp logs to a .log file in the /logs directory in tomcat but the file is not generated nor is any logging output going to the console other than the spring logs and tomcat logs. When I run spring boot as a jar file with the embedded tomcat it writes to the log file just fine, but as soon as I deploy to tomcat via the webapps folder the application logs are no where to be found.
SpringBoot 2.1.2
Java 1.8
Tomcat 8.5
I have tried:
configuring LOGGING_CONFIG in setenv.sh
Multiple loggers.. logback, java utils etc..
application.properties:
logging.file=../logs/my-app.log
logging.level.org.springframework=INFO
logging.level.com.bose=DEBUG
log4j.properties for log4j:
log4j.rootLogger=${marge.log.level}, stdout, file
# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=marge.log
#when stdout is also specified it will not write to the file
log4j.appender.file.MaxFileSize=1MB
# Keep one backup file
log4j.appender.file.MaxBackupIndex=1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{dd MMM yyyy HH:mm:ss,SSS} [%c] [%-5p] %n%m%n
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
# stdout uses PatternLayout
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%c] [%-5p] %n%m%n
# Print only messages of level DEBUG or above in the package com.bose
log4j.logger.com.app=${log.level}
Expected: when I deploy my webapp in /webapps the application logs (generated by log4j) should be in my-app.log in the /logs directory
Actual: No file is generated and no logs are even in stdout/console
By default spring boot uses logback as a logging binder, so the key concept here to exclude logback first then include log4j
Example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
After that add log4j 2 dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
Add your log4j2.properties file to src/main/resources to be on classpath
Finally pay attention to what logging interface you are using this is important, with the above configuration you should use apache logging like:
package com.example;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
private static final Logger LOGGER = LogManager.getLogger(Application.class);
public static void main(String[] args){
ApplicationContext ctx = SpringApplication.run(Application.class, args);
LOGGER.info("Info level log message");
LOGGER.debug("Debug level log message");
LOGGER.error("Error level log message");
}
}

Trace for multiple Camel Context

I have two projects let's say - Project_1 and Project_2, and corresponding camel contexts, Configured as follows
<camel:camelContext id="project_1.context" trace="true">
<camel:contextScan />
</camel:camelContext>
<camel:camelContext id="project_2.context" trace="true">
<camel:contextScan />
</camel:camelContext>
with corresponding deployment units as project_1.jar, and project_2.jar, have been deployed in jboss.
But still I am not able to see traces for any of the CamelContext while starting my jboss.
log configuration for both projects are:
log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%c] %m%n
log4j.logger.org.apache.camel=ALL
both projects have added the dependency for slf4j
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
both projects have added the module dependency for slf4j in jboss-deployment-structure:
<module name ="org.slf4j"/>
Kindly help me to let me know the thing that I am missing.
Looks like your root logger is set as "Error".
In your project, if you have the messages logged in DEBUG or INFO mode, please try to change the root log level to "DEBUG" or "INFO" and verify

Where put log4j properies file?

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.

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>

Categories