I just started using of log4j2.
But i found that log4j2 including library name in stacktrace.
How can i disable that?
Here is an example:
java.lang.NullPointerException
at com.sev.controllers.UserController.login(UserController.java:35) ~[UserController.class:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_31]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_31]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_31]
at java.lang.reflect.Method.invoke(Method.java:483) ~[?:1.8.0_31]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
Im talking about that name in [] braces.
Here is my log4j config
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.apache.log4j.xml" level="INFO"/>
<Logger name="org.hibernate" level="INFO"/>
<Logger name="org.springframework" level="INFO"/>
<Root level="debug">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
And here is my versions:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.3</version>
</dependency>
Forget to mention that my app is spring-boot based.
Your configuration's PatternLayout pattern does not contain an explicit exception converter. Log4j will provide a default which is %xEx. This includes the jar file etc.
You can change this by explicitly specifying setting the simple %ex converter. So your pattern ends in ...%m%ex%n.
You need to set the alwaysWriteExceptions to false in the pattern layout.
https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout
Then add to your pattern the throwable options you would like instead.
https://logging.apache.org/log4j/2.x/manual/layouts.html#Patterns
Outputs the Throwable trace bound to the LoggingEvent, by default this
will output the full trace as one would normally find with a call to
Throwable.printStackTrace().
You can follow the throwable conversion word with an option in the
form %throwable{option}.
%throwable{short} outputs the first line of the Throwable.
%throwable{short.className} outputs the name of the class where the
exception occurred.
%throwable{short.methodName} outputs the method name where the
exception occurred.
%throwable{short.fileName} outputs the name of the class where the
exception occurred.
%throwable{short.lineNumber} outputs the line number where the
exception occurred.
%throwable{short.message} outputs the message.
%throwable{short.localizedMessage} outputs the localized message.
%throwable{n} outputs the first n lines of the stack trace.
Specifying %throwable{none} or %throwable{0} suppresses output of the
exception.
If you still can not satisfy what you want with those options you would need to write a custom converter as described here.
https://logging.apache.org/log4j/2.x/manual/extending.html#PatternConverters
An example that is a little more clear then theirs.
#Plugin(name="HostNameConverter", category ="Converter")
#ConverterKeys({"h","host","hostName"})
public class HostNameConverter extends LogEventPatternConverter {
/**
* Constructs an instance of LoggingEventPatternConverter.
*
* #param name name of converter.
* #param style CSS style for output.
*/
protected HostNameConverter(String name, String style) {
super(name, style);
}
#Override
public void format(LogEvent event, StringBuilder toAppendTo) {
toAppendTo.append(HostNameUtil.getLocalHostName());
}
public static HostNameConverter newInstance(String[] options){
return new HostNameConverter(HostNameConverter.class.getSimpleName(),HostNameConverter.class.getSimpleName());
}
}
I think it's better: [...%m%n%ex]
Related
I have a Java maven application in which I have created a swing GUI.
I am using logback-classic for logging purposes. logback.xml is present under the src/main/resources directory.
When I run the application using eclipse "Run As Java Application", it is working as intended and application is logging to the console and log file.
But after exporting the application as a runnable JAR file and double clicking to run the application, it is not logging to file.
When I opened command prompt and execute application using "java -jar myjarfile.jar", I am able to see the console logs, but it is using the default logback configuration.
I tried giving additional parameter, -Dlogback.configurationFile="path-to-file/logback.xml" and I am getting the below error,
Failed to instantiate [ch.qos.logback.classic.LoggerContext] Reported
exception: java.lang.IllegalArgumentException: name
at sun.misc.URLClassPath$Loader.findResource(Unknown Source)
at sun.misc.URLClassPath$1.next(Unknown Source)
at sun.misc.URLClassPath$1.hasMoreElements(Unknown Source)
at java.net.URLClassLoader$3$1.run(Unknown Source)
at java.net.URLClassLoader$3$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader$3.next(Unknown Source)
at java.net.URLClassLoader$3.hasMoreElements(Unknown Source)
at sun.misc.CompoundEnumeration.next(Unknown Source)
at sun.misc.CompoundEnumeration.hasMoreElements(Unknown Source)
at ch.qos.logback.core.util.Loader.getResources(Loader.java:73)
at ch.qos.logback.classic.util.ContextInitializer.multiplicityWarning(ContextInitializer.java:183)
at ch.qos.logback.classic.util.ContextInitializer.statusOnResourceSearch(ContextInitializer.java:175)
at ch.qos.logback.classic.util.ContextInitializer.findConfigFileURLFromSystemProperties(ContextInitializer.java:111)
at ch.qos.logback.classic.util.ContextInitializer.findURLOfDefaultConfigurationFile(ContextInitializer.java:120)
at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:148)
at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:84)
at org.slf4j.impl.StaticLoggerBinder.(StaticLoggerBinder.java:55)
at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
at com.esignature.tools.templatemigration.ConverterGUI.(ConverterGUI.java:35)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:59)
I don't know what I am missing and I want to log from runnable JAR to the log file.
It is confusing because it is working from eclipse but not from the exported runnable JAR.
Below is the logback.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_HOME" value="C:/template converter logs" />
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level - %msg%n</pattern>
</encoder>
</appender>
<appender name="rollingFile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/applog-%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="rollingFile" />
</root>
</configuration>
The error you are facing is because there is two logback.xml configuration, one is in your classpath and you are trying to override/add another one using -Dlogback.configurationFile
In my case when packaging the runnable JAR I changed the pom configuration to this.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
Note the executable set to true, this makes sure that a MANIFEST.MF file is added to the JAR package.
So in order to make this work with this config I added this property to my application.yml/application.properties
logging:
config: file:D:\\LogConfig\\logback.xml
Then I proceed to generate the JAR file using clean, install mvn commands.
From there running the JAR file using java -jar myJar.jar works fine and there is no need to add arguments to search the application.yml or logback.xml. That is because the properties is being loaded from within the jar and the log config from the specified route on the application.yml .
Using maven shade plugin to generate a shaded JAR file that includes the dependencies and the custom logback.xml is one working solution that I utilized.
Now when I run this JAR file (either from command line or by double-clicking it), logs are generated in the specified location as expected.
I have created a sample application by following the tutorial mentioned at Creating a Basic REST Web Service using Grizzly, Jersey. I have extended the sample with logback.xml. I later found out that jersey uses java.util.logging and configured a slf4j bridge. Things are working fine but I get a unrecoverable exception when having logback level at trace and works fine when level is set at debug or higher (INFO, WARN etc).
Below is the stacktrace -
20:35:24.531 [grizzly-nio-kernel(7) SelectorRunner] WARN o.g.g.filterchain.DefaultFilterChain - GRIZZLY0013: Exception during FilterChain execution
java.lang.NullPointerException: null
at java.lang.String.<init>(String.java:166)
at java.lang.String.valueOf(String.java:3008)
at org.glassfish.grizzly.filterchain.FilterChainContext.toString(FilterChainContext.java:1076)
at java.text.MessageFormat.subformat(MessageFormat.java:1280)
at java.text.MessageFormat.format(MessageFormat.java:865)
at java.text.Format.format(Format.java:157)
at java.text.MessageFormat.format(MessageFormat.java:841)
at org.slf4j.bridge.SLF4JBridgeHandler.getMessageI18N(SLF4JBridgeHandler.java:265)
at org.slf4j.bridge.SLF4JBridgeHandler.callLocationAwareLogger(SLF4JBridgeHandler.java:220)
at org.slf4j.bridge.SLF4JBridgeHandler.publish(SLF4JBridgeHandler.java:303)
at java.util.logging.Logger.log(Logger.java:738)
at java.util.logging.Logger.doLog(Logger.java:765)
at java.util.logging.Logger.log(Logger.java:851)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:280)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539)
at org.glassfish.grizzly.nio.NIOConnection.preClose(NIOConnection.java:879)
at org.glassfish.grizzly.nio.transport.TCPNIOConnection.preClose(TCPNIOConnection.java:97)
at org.glassfish.grizzly.nio.NIOConnection.terminate0(NIOConnection.java:603)
at org.glassfish.grizzly.nio.transport.TCPNIOConnection.terminate0(TCPNIOConnection.java:291)
at org.glassfish.grizzly.nio.NIOConnection$4.completed(NIOConnection.java:567)
at org.glassfish.grizzly.nio.NIOConnection$4.completed(NIOConnection.java:563)
at org.glassfish.grizzly.asyncqueue.AsyncWriteQueueRecord.notifyCompleteAndRecycle(AsyncWriteQueueRecord.java:173)
at org.glassfish.grizzly.nio.AbstractNIOAsyncQueueWriter.write(AbstractNIOAsyncQueueWriter.java:279)
at org.glassfish.grizzly.nio.AbstractNIOAsyncQueueWriter.write(AbstractNIOAsyncQueueWriter.java:169)
at org.glassfish.grizzly.nio.AbstractNIOAsyncQueueWriter.write(AbstractNIOAsyncQueueWriter.java:71)
at org.glassfish.grizzly.AbstractWriter.write(AbstractWriter.java:76)
at org.glassfish.grizzly.nio.NIOConnection.closeGracefully0(NIOConnection.java:562)
at org.glassfish.grizzly.nio.NIOConnection.closeWithReason(NIOConnection.java:513)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:160)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539)
at org.glassfish.grizzly.nio.transport.TCPNIOServerConnection$RegisterAcceptedChannelCompletionHandler.completed(TCPNIOServerConnection.java:353)
at org.glassfish.grizzly.nio.transport.TCPNIOServerConnection$RegisterAcceptedChannelCompletionHandler.completed(TCPNIOServerConnection.java:320)
at org.glassfish.grizzly.nio.DefaultSelectorHandler.registerChannel0(DefaultSelectorHandler.java:336)
at org.glassfish.grizzly.nio.DefaultSelectorHandler.access$400(DefaultSelectorHandler.java:64)
at org.glassfish.grizzly.nio.DefaultSelectorHandler$RegisterChannelOperation.run(DefaultSelectorHandler.java:467)
at org.glassfish.grizzly.nio.DefaultSelectorHandler.processPendingTaskQueue(DefaultSelectorHandler.java:301)
at org.glassfish.grizzly.nio.DefaultSelectorHandler.processPendingTasks(DefaultSelectorHandler.java:293)
at org.glassfish.grizzly.nio.DefaultSelectorHandler.preSelect(DefaultSelectorHandler.java:101)
at org.glassfish.grizzly.nio.SelectorRunner.doSelect(SelectorRunner.java:335)
at org.glassfish.grizzly.nio.SelectorRunner.run(SelectorRunner.java:279)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573)
at java.lang.Thread.run(Thread.java:748)
My logging.properties file -
handlers = org.slf4j.bridge.SLF4JBridgeHandler
.level=ALL
java.util.logging.SLF4JBridgeHandler.level = ALL
My logback.xml file -
<configuration>
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="trace">
<appender-ref ref="STDOUT" />
</root>
</configuration>
NOTE: I have the following in my main method if it makes any difference
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
This is bug FilterChainContext.toString crashes with NullPointerException #1959 in Grizzly.
There are two overloads of String.valueOf, with Object and char[]. (Java 8)
Because of the dangerous unbound generic in getMessage both overloads would seem applicable, however the char[] overload is chosen, probably because it is more specific.
[snip]
However String.valueOf(char[]) will fail if the result of getMessage is null. I would assume a ClassCastException could happen in other cases. This can be fixed by explicitly casting the result to object or ensuring that the correct generics are infered.
You need to upgrade to a newer version of Grizzly (2.4.3).
A regression bug was filed in Nov 10, 2020 under: FilterChainContext.toString causes NullPointerException #2110 which reports fixed in 4.0.0-M2-RELEASE.
Commit is listed as: https://github.com/eclipse-ee4j/grizzly/commit/d7a96f15083a55c38f63746007f664f1ede9f474
My application logging crashes during maven build in the tests. This is the log4j2.xml what I have in the src/test/resources:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="stdout" target="SYSTEM_OUT">
<PatternLayout pattern="MyApp: %d{yyyy-MM-dd HH:mm:ss,SSS} %5p [%t] %c{1.} - %m%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="com.my.app" level="info" additivity="false">
<Appender-ref ref="stdout"/>
</Logger>
<Root level="error">
<Appender-ref ref="stdout"/>
</Root>
</Loggers>
</Configuration>
And I get this exception during test during build:
2017-11-23 15:12:28,371 main ERROR An exception occurred processing Appender stdout java.lang.NullPointerException
at org.apache.logging.log4j.core.impl.ThrowableProxy.toExtendedStackTrace(ThrowableProxy.java:671)
at org.apache.logging.log4j.core.impl.ThrowableProxy.<init>(ThrowableProxy.java:138)
at org.apache.logging.log4j.core.impl.ThrowableProxy.<init>(ThrowableProxy.java:122)
at org.apache.logging.log4j.core.impl.Log4jLogEvent.getThrownProxy(Log4jLogEvent.java:566)
at org.apache.logging.log4j.core.pattern.ExtendedThrowablePatternConverter.format(ExtendedThrowablePatternConverter.java:64)
at org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:38)
at org.apache.logging.log4j.core.layout.PatternLayout$PatternSerializer.toSerializable(PatternLayout.java:333)
at org.apache.logging.log4j.core.layout.PatternLayout.toText(PatternLayout.java:232)
at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:217)
at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:57)
at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:177)
at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:170)
at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:161)
at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:156)
at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:129)
at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:120)
at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:84)
at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:448)
at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:433)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:417)
at org.apache.logging.log4j.core.config.LoggerConfig.logParent(LoggerConfig.java:439)
at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:434)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:417)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:403)
at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:63)
at org.apache.logging.log4j.core.Logger.logMessage(Logger.java:146)
at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2116)
at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2100)
at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:1994)
at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1966)
at org.apache.logging.slf4j.Log4jLogger.error(Log4jLogger.java:319)
at com.my.app.MyTest.testingMyApp(MyTest.java:89)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:19)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
This is my pom:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jul</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.dblock.log4jna</groupId>
<artifactId>log4jna-api</artifactId>
</dependency>
The version of log4j is 2.9.1
And the funny thing, that it logs to the console, for example when the spring application starting, then there I can see the logs which are coming from the MyApplication.java which has the #SpringBootApplication annotation.
And MyTest.java:89 is:
logger.error("error occured",e);
And the logger is coming from:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
So it looks like it crashes during error log, but there is no problem if I log a normal info.
So what is this nullpointer?
Ok, I figured it out: it is because in the test class I have a mock exception. If I change it to creating a new object from the exception, it works fine.
It is a good candidate for reporting a bug I guess.
The Exception or Throwable you passed as parameter of logger.error("error occured", e); does not have any stacktrace (its stacktrace is null), however the Log4j2 implementation you are using tries to access said stacktrace and throws this error.
Looking at the source, the line throwing your error is:
stackLength = stackTrace.length;
Meaning that the stackTrace variable is null. It is obtained with throwable.getStackTrace() from the Throwable (Exception) you passed as parameter to
logger.error("error occured", e);
As to why your stacktrace is null, that will depends on the JVM your are using and how you get said Exception. It can happen but that's definitely not a standard behavior. You can take a look at this post and this post.
If you need to create a mock exception with Mockito, you can setup the getStackTrace method to return an empty array of StackTraceElements:
private Throwable logSafeExceptionMock(Class<? extends Throwable> exceptionType) {
Throwable t = mock(exceptionType);
when(t.getStackTrace()).thenReturn(new StackTraceElement[0]);
return t;
}
I'm using Tomcat to deploy a java webapp.
I get a very long stacktrace, in short:
GRAVE: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/new-webapp]]
[...]
Caused by: java.lang.NoClassDefFoundError: Lorg/apache/logging/log4j/Logger;
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2509)
at java.lang.Class.getDeclaredFields(Class.java:1819)
at org.apache.catalina.util.Introspection.getDeclaredFields(Introspection.java:106)
at org.apache.catalina.startup.WebAnnotationSet.loadFieldsAnnotation(WebAnnotationSet.java:256)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationFilterAnnotations(WebAnnotationSet.java:105)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:64)
at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:335)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:782)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:306)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5150)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
... 6 more
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.Logger
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1305)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1139)
... 20 more
[...]
Now, the error is pretty clear. For some reason, the log4j bundle is not in the classpath.
The application is a maven webapp, and the pom.xml is like this:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wb</groupId>
<artifactId>new-webapp</artifactId>
<packaging>war</packaging>
<version>0.0.1</version>
<properties>
<log4j.version>2.5</log4j.version>
</properties>
<dependencies>
[...]
<!-- Logging -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
[...]
</project>
If I go to the project properties, under Libraries->Maven Dependencies I see this:
Libraries were found, downloaded and they are in the classpath.
I also tried to open a java class inside my project and declare
org.apache.logging.log4j.Logger Logger;
No errors, the Logger interface is found.
What's going on here? Why does Tomcat fail to start even if libraries are in the classpath?
Edit - this is the log4j configuration file:
<?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>
By the description you've made, I assume you are working with Eclipse.
Well, you'd better go to Project properties -> Deployment assembly and ensure that the maven dependencies entry is included.
I've experimented often that this configuration gets missed whenever you execute Maven -> Update Project.
I'm working with Eclipse and I had same problem every time I made changes in my pom.xml. I don't know why but Eclipse delete the Maven Dependencies.
Solution: rigth click on project, select Properties, choose Deployment Assembly and verify in column "Source" a row called "Maven Dependencies". If it isn't there, click on Add..., Java Build Path Entries and click on Maven Dependencies. Finally Apply and close.
Ensure that the log4j libraries are not included already in the Tomcat runtime (nor the endorsed directories), because it could produce conflict about classloading policy.
I am running some unit tests and I was to use SLF4J and logback.
Here is the relevant pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.6-RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.21</version>
</dependency>
And here is the log and stacktrace:
20:29:16,293 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml] at [file:/code/web/target/test-classes/logback-test.xml]
20:29:16,387 |-ERROR in ch.qos.logback.core.joran.event.SaxEventRecorder#7a1ebcd8 - Unexpected exception while parsing XML document. java.lang.NullPointerException
at java.lang.NullPointerException
at at org.xml.sax.helpers.LocatorImpl.<init>(LocatorImpl.java:103)
at at ch.qos.logback.core.joran.event.SaxEvent.<init>(SaxEvent.java:31)
at at ch.qos.logback.core.joran.event.StartEvent.<init>(StartEvent.java:27)
at at ch.qos.logback.core.joran.event.SaxEventRecorder.startElement(SaxEventRecorder.java:106)
at at org.allcolor.xml.parser.CShaniSaxParser.parseStartTag(CShaniSaxParser.java:1393)
at at org.allcolor.xml.parser.CXmlParser.parseSTARTTag(CXmlParser.java:1405)
at at org.allcolor.xml.parser.CXmlParser.parse(CXmlParser.java:682)
at at org.allcolor.xml.parser.CShaniSaxParser.parse(CShaniSaxParser.java:767)
at at javax.xml.parsers.SAXParser.parse(SAXParser.java:392)
at at ch.qos.logback.core.joran.event.SaxEventRecorder.recordEvents(SaxEventRecorder.java:59)
at at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:141)
at at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:103)
at at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:53)
at at ch.qos.logback.classic.util.ContextInitializer.configureByResource(ContextInitializer.java:75)
at at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:150)
at at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:84)
at at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:55)
at at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
at at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
at at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
at at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
at at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
at at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:132)
at at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:685)
at at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<clinit>(SpringJUnit4ClassRunner.java:91)
at at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
And the logback-test.xml:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>.%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %n
</Pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>TRACE</level>
</filter>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</root>
<logger name="com.me.ControllerTester" level="debug" additivity="false">
<appender-ref ref="consoleAppender" />
</logger>
</configuration>
Now I have checked the dependency tree, and I have nothing conflicting. I have tried messing with the SAX parser versions.
The XML looks fine to me. I must be conflicted somehow...
Any Ideas?
logback uses SAXParserFactory.newInstance(), which has a lookup procedure that determines which implementation to use. It seems that org.allcolor.xml.parser.CShaniSaxParser is being selected in your environment based on this lookup:
public static SAXParserFactory newInstance()
Obtain a new instance of a SAXParserFactory. This static method creates a new factory instance This method uses the following ordered lookup procedure to determine the SAXParserFactory implementation class to load:
Use the javax.xml.parsers.SAXParserFactory system property.
Use the properties file "lib/jaxp.properties" in the JRE directory. This configuration file is in standard java.util.Properties format and contains the fully qualified name of the implementation class with the key being the system property defined above. The jaxp.properties file is read only once by the JAXP implementation and it's values are then cached for future use. If the file does not exist when the first attempt is made to read from it, no further attempts are made to check for its existence. It is not possible to change the value of any property in jaxp.properties after it has been read for the first time.
Use the Services API (as detailed in the JAR specification), if available, to determine the classname. The Services API will look for a classname in the file META-INF/services/javax.xml.parsers.SAXParserFactory in jars available to the runtime.
Platform default SAXParserFactory instance.
Once an application has obtained a reference to a SAXParserFactory it can use the factory to configure and obtain parser instances.
Tip for Trouble-shooting
Setting the jaxp.debug system property will cause this method to print a lot of debug messages to System.err about what it is doing and where it is looking at.
If you have problems loading DocumentBuilders, try:
java -Djaxp.debug=1 YourProgram ....
Try switching to a standard SAX parser (such as Apache Xerces) by setting javax.xml.parsers.SAXParserFactory system property for your unit tests:
-Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl