Reputation: 37
I am just starting to master modular applications and I have a problem with the logback.
Before modularity was introduced into the project, Logback successfully worked with the same settings.
As soon as I start working with the LoggerContext and add the line requires ch.qos.logback.classic
to the module-info.java
, the application crashes.
Crash occurs in the line receiving the logger:
private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
That being said, the code using the LoggerContext works fine. And as soon as I remove all mention of the LoggerContext, the application starts working normally.
Failed to instantiate [ch.qos.logback.classic.LoggerContext]
Reported exception:
java.lang.NullPointerException: Cannot invoke "ch.qos.logback.core.model.processor.ModelHandlerBase.isSupportedModelType(ch.qos.logback.core.model.Model)" because "handler" is null
at ch.qos.logback.core/ch.qos.logback.core.model.processor.DefaultProcessor.traverse(DefaultProcessor.java:114)
at ch.qos.logback.core/ch.qos.logback.core.model.processor.DefaultProcessor.traversalLoop(DefaultProcessor.java:39)
at ch.qos.logback.core/ch.qos.logback.core.model.processor.DefaultProcessor.process(DefaultProcessor.java:54)
at ch.qos.logback.core/ch.qos.logback.core.joran.GenericConfigurator.processModel(GenericConfigurator.java:178)
at ch.qos.logback.core/ch.qos.logback.core.joran.GenericConfigurator.playEventsAndProcessModel(GenericConfigurator.java:165)
at ch.qos.logback.core/ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:151)
at ch.qos.logback.core/ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:115)
at ch.qos.logback.core/ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:58)
at ch.qos.logback.classic/ch.qos.logback.classic.util.ContextInitializer.configureByResource(ContextInitializer.java:82)
at ch.qos.logback.classic/ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:157)
at ch.qos.logback.classic/ch.qos.logback.classic.spi.LogbackServiceProvider.initializeLoggerContext(LogbackServiceProvider.java:49)
at ch.qos.logback.classic/ch.qos.logback.classic.spi.LogbackServiceProvider.initialize(LogbackServiceProvider.java:40)
at org.slf4j/org.slf4j.LoggerFactory.bind(LoggerFactory.java:152)
at org.slf4j/org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:139)
at org.slf4j/org.slf4j.LoggerFactory.getProvider(LoggerFactory.java:418)
at org.slf4j/org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:404)
at org.slf4j/org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:353)
at takil/com.company.Main.<init>(Main.java:23)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:802)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
If you remove the line, then the application works fine.
My module-info file
module elements {
requires com.jfoenix;
requires javafx.graphics;
requires javafx.base;
requires javafx.controls;
requires ModbusLibrary;
requires de.gsi.chartfx.dataset;
requires de.gsi.chartfx.chart;
requires ch.qos.logback.classic;
requires org.slf4j;
requires org.apache.commons.io;
requires eu.hansolo.medusa;
requires org.kordamp.iconli.core;
requires org.kordamp.ikonli.javafx;
requires org.kordamp.ikonli.fontawesome;
exports com.company.elements;
exports com.company.elements.messageTable;
exports com.company.elements.gauge;
exports com.company.elements.chart;
exports com.company.elements.log;
exports com.company.elements.materialDesign;
}
My pom dependency:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.3.0-alpha5</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.0-alpha1</version>
</dependency>
Method using LoggerContext:
public static String getPathLog() {
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
String folder = context.getProperty("LOG_PATH");
String file = context.getProperty("FILE_NAME");
return folder + "/" + file;
}
My logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property scope="context" name="LOG_PATH" value="${user.home}/log"/>
<property scope="context" name="FILE_NAME" value="last.log"/>
<property scope="context" name="APS_MESSAGE_FILE_NAME" value="msg.log"/>
<property scope="context" name="SEPARATOR" value=";"/>
<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{dd.MM.yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{20} ebobo- %msg%n</pattern>-->
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/${FILE_NAME}</file>
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${LOG_PATH}/archived/%d{yyyy-MM-dd}.%i.zip</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<!-- Храним файлы логов 10 дней -->
<maxHistory>360</maxHistory>
<!-- Максимальный размер файлов лога 30 гигабайт -->
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{dd.MM.yyyy HH:mm:ss.SSS};%msg%n</pattern>
</encoder>
</appender>
<appender name="MSG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/${APS_MESSAGE_FILE_NAME}</file>
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${LOG_PATH}/archivedMsg/%d{yyyy-MM-dd}.%i.zip</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<!-- Храним файлы логов 10 дней -->
<maxHistory>360</maxHistory>
<!-- Максимальный размер файлов лога 30 гигабайт -->
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{dd.MM.yyyy HH:mm:ss.SSS};%msg%n</pattern>
</encoder>
</appender>
<logger name="com.company.elements.baseElement.Registerable" level="WARN">
<appender-ref ref="console"/>
</logger>
<logger name="com.company.elements.log.LogWriter" level="INFO" additivity="false">
<appender-ref ref="FILE"/>
</logger>
<logger name="com.company.elements.messageTable.MessageTable" level="INFO" additivity="false">
<appender-ref ref="MSG"/>
</logger>
<root level="WARN">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
Sorry for my google english :)
Upvotes: 2
Views: 2505
Reputation: 8114
It is a bug in logback 1.3.0-alpha5
Add
--add-exports ch.qos.logback.classic/ch.qos.logback.classic.model.processor=ch.qos.logback.core
to the java VM argument as a workaround first, or try other version.
The actual problem occur inside DefaultProcessor#instantiateHandler
ModelHandlerBase instantiateHandler(Class<? extends ModelHandlerBase> handlerClass) {
try {
Constructor<? extends ModelHandlerBase> commonConstructor = getWithContextConstructor(handlerClass);
if (commonConstructor != null) {
return commonConstructor.newInstance(context);
}
Constructor<? extends ModelHandlerBase> constructorWithBDC = getWithContextAndBDCConstructor(handlerClass);
if (constructorWithBDC != null) {
return constructorWithBDC.newInstance(context, interpretationContext.getBeanDescriptionCache());
}
addError("Failed to find suitable constructor for class [" + handlerClass + "]");
return null;
} catch (InstantiationException | IllegalAccessException | SecurityException | IllegalArgumentException
| InvocationTargetException e1) {
addError("Failed to instantiate " + handlerClass);
return null;
}
}
Which return null when InstantiationException
is thrown due to
java.lang.IllegalAccessException: class ch.qos.logback.core.model.processor.DefaultProcessor (in module ch.qos.logback.core) cannot access class ch.qos.logback.classic.model.processor.ConfigurationModelHandler (in module ch.qos.logback.classic) because module ch.qos.logback.classic does not export ch.qos.logback.classic.model.processor to module ch.qos.logback.core
Upvotes: 3