У меня есть этот код, который инициализирует контекст Log4J в моем приложении. Приложение разрабатывается с использованием Quarkus 2.16.7.Final. Контекст Log4j заключен в мой общий класс «loggingContext», который предоставляет метод «initialize», который можно использовать для инициализации контекста журналирования внутри более общего контекста приложения:
public synchronized void initialize(ApplicationContext currentApplicationContext) throws LoggingContextException {
if (!isInitialized()) {
File configurationFile = null;
configurationFile = new File(getConfigurationContext().getLog4jFilePath());
if (!configurationFile.exists()) {
throw new LoggingContextException("Could not find LOG4J configuration file: \"" + getConfigurationContext().getLog4jFilePath() + "\".");
}
this.loggingId = currentApplicationContext.getApplicationName();
try (FileInputStream fis = new FileInputStream(configurationFile);) {
this.loggerContext = LoggerContext.getContext(getConfigurationContext().getClassLoader(), false, null);
loggerContextOwnership = initLoggerContext(this.loggerContext, configurationFile);
if (loggerContextOwnership) {
System.out.println(loggingId + " - Logging Context INITIALIZED (LOG4J File Path: \"" + this.loggerContext.getConfiguration().getConfigurationSource().getFile() + "\"). <<<");
} else {
File configFile = loggerContext.getConfiguration().getConfigurationSource().getFile();
if (!configFile.getAbsolutePath().equals(configurationFile.getAbsolutePath())) {
throw new LoggingContextException("Could not acquire LOG4J context ownership.");
}
}
} catch (IOException e) {
throw new LoggingContextException("Could not read LOG4J configuration file", e);
}
this.initialized = true;
super.initialize(currentApplicationContext);
}
}
private boolean initLoggerContext(LoggerContext loggerContext, File log4jConfigurationFile) {
boolean hasOwnership = false;
Configuration xmlConfig = ConfigurationFactory.getInstance().getConfiguration(null, "Application Framework LOG4J configuration", log4jConfigurationFile.toURI());
File configFile = loggerContext.getConfiguration().getConfigurationSource().getFile();
String key = getConfigurationContext().getLog4jFilePath();
if (configFile == null) {
loggerContext.setConfiguration(xmlConfig);
hasOwnership = true;
synchronized (log4jContextMap) {
List<LOG4JContext> list = log4jContextMap.get(getConfigurationContext().getClassLoader()).computeIfAbsent(key, k -> {
return new LinkedList<>();
});
list.add(this);
}
} else {
if (!configFile.getAbsolutePath().equals(log4jConfigurationFile.getAbsolutePath())) {
System.out.println(loggingId + " - WARNING: LOG4J Context already initialized (file: \"" + configFile.getAbsolutePath() + "\").");
LoggingOwnershipMode loggingOwnershipMode = getConfigurationContext().getLoggingOwnershipMode();
switch (loggingOwnershipMode) {
case DEFAULT:
break;
case FORCE:
loggerContext.setConfiguration(xmlConfig);
hasOwnership = true;
System.out.println(loggingId + " - WARNING: LOG4j Context has been reconfigured.");
break;
default:
break;
}
} else {
hasOwnership = true;
synchronized (log4jContextMap) {
List<LOG4JContext> list = log4jContextMap.get(getConfigurationContext().getClassLoader()).computeIfAbsent(key, k -> {
return new LinkedList<>();
});
list.add(this);
}
}
}
return hasOwnership;
}
У меня есть эти зависимости (иерархия зависимостей, представление Eclipse IDE):
Мой контекст Log4J работает (в Windows) только с конфигурацией FAST-JAR. Вместо этого я хотел бы использовать Uber-Jar. Используя Uber Jar, у меня есть следующий SystemOut:
Я не хочу использовать ведение журнала Jboss, поскольку это приложение представляет собой порт из приложения J2EE, которое активно использует log4j. Использование fast jar не считается окончательным решением. Я почти уверен, что проблема связана с механизмами загрузки классов, но мне хотелось бы ее преодолеть. Есть предложения?
Я не уверен, что это связано с предложенным дублирующим вопросом. Мы создаем Uber-Jar в семантике Quarkus. maven-shade-plugin не используется, и вопрос связан с добавлением моста log4j1-2 в Quarkus, который работает в режиме fast-jar, но не в режиме uber-jar/legacy-jar.
Если вы хотите объединить несколько JAR-файлов в один, вам необходимо правильно разрешить каждый конфликт имен файлов. В частности, файлы Log4j2Plugins.dat
должны быть объединены соответствующим образом. См. обсуждение 2874 по той же проблеме.
Привет Петр, спасибо за ваш комментарий. Кстати, я не использую какой-либо плагин maven-shade. Uber-jar здесь используется как особый режим для jar-файлов Quarkus. Решение, представленное в прикрепленном вами вопросе, не применимо для моего конкретного случая, поскольку я создаю приложение, используя: quarkus-maven-plugin
Детали могут измениться, но причина одна и та же. Если два файла из разных файлов JAR имеют одинаковое имя, quarkus-maven-plugin
удаляет один из них.
СПАСИБО! Мне помогло удаление Log4j2Plugins.dat. Я знаю, что его следует объединить, но мне просто нужны плагины log4j2-CORE, которые должны быть аннотированы @Plugin, и мне их достаточно.
Проблема была решена удалением из финального runner.jar файла "Log4j2Plugins.dat". этот файл следует объединить, а не удалить, но мне просто нужны плагины log4j2-CORE, которые должны быть помечены @Plugin, и мне их достаточно.
Предупреждения Quarkus достаточно, чтобы понять, что проблема в файле (упаковке uber-jar):
[ПРЕДУПРЕЖДЕНИЕ] [io.quarkus.deployment.pkg.steps.JarResultBuildStep] Обнаружены зависимости с повторяющимися файлами. Зависимости [org.apache.logging.log4j:log4j-1.2-api::jar:2.19.0[пути: H:\Maven\org\apache\logging\log4j\log4j-1.2-api\2.19.0\log4j -1.2-api-2.19.0.jar;], org.apache.logging.log4j:log4j-core::jar:2.19.0[пути: H:\Maven\org\apache\logging\log4j\log4j-core \2.19.0\log4j-core-2.19.0.jar;], org.apache.logging.log4j:log4j-web::jar:2.19.0[пути: H:\Maven\org\apache\logging\log4j \log4j-web\2.19.0\log4j-web-2.19.0.jar;]] содержат повторяющиеся файлы, например. META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat
Этот вопрос похож на: Динамическое добавление Log4J2 не работает с плагином maven-shade. Если вы считаете, что это другое, отредактируйте вопрос, поясните, чем он отличается и/или как ответы на этот вопрос не помогают решить вашу проблему.