How to make log4j&logback compatible after upgrading poi to v5? - apache-poi

I'm facing problems after upgrading the latest poi 5.2.2.
Now my project is using the springboot default logback to print the logs.
but after upgrading the poi
implementation "org.apache.poi:poi:5.2.2"
it must let me implement the log4j implementation. so I added
implementation 'org.apache.logging.log4j:log4j-core:2.17.2'
then this works in my local environment.
However got below errors in docker environment
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]
Exception in thread "main" java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath.
Either remove Logback or the competing implementation (class org.apache.logging.slf4j.Log4jLoggerFactory
loaded from file:/opt//BOOT-INF/lib/log4j-slf4j-impl-2.17.2.jar). If you are using WebLogic you will need to add 'org.slf4j' to
prefer-application-packages in WEB-INF/weblogic.xml: org.apache.logging.slf4j.Log4jLoggerFactory
at org.springframework.util.Assert.instanceCheckFailed(Assert.java:702)
at org.springframework.util.Assert.isInstanceOf(Assert.java:621)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.get
below is my build.gradle file
configurations.all {
exclude group: 'org.hibernate', module: 'hibernate-entitymanager'
exclude group: 'org.apache.tomcat', module: 'tomcat-jdbc'
exclude group: 'log4j'
exclude group: 'org.slf4j', module: 'slf4j-log4j12'
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging' }
implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.springframework:spring-context-support"
implementation "org.springframework.boot:spring-boot-starter-data-jpa"
implementation "org.springframework.boot:spring-boot-starter-data-mongodb"
implementation "org.springframework.boot:spring-boot-starter-freemarker"
implementation "org.springframework.boot:spring-boot-starter-mail"
implementation "org.springframework.boot:spring-boot-starter-security"
implementation "org.springframework.boot:spring-boot-starter-web"
implementation "org.springframework.boot:spring-boot-starter-validation"
implementation "org.springframework.security:spring-security-oauth2-client"
implementation "org.springframework.security:spring-security-oauth2-jose"
implementation "org.springframework.security:spring-security-oauth2-resource-server"
implementation "ch.qos.logback:logback-classic:1.2.11"
implementation 'org.apache.logging.log4j:log4j-core:2.17.2'
btw, basing POI official introduction, it also supports other logging framework, so I also tried this jar
https://logging.apache.org/log4j/log4j-2.2/log4j-to-slf4j/index.html
but I still get error like below
Caused by: org.apache.logging.log4j.LoggingException: log4j-slf4j-impl cannot be present with log4j-to-slf4j
at org.apache.logging.slf4j.Log4jLoggerFactory.validateContext(Log4jLoggerFactory.java:60)
at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:44)
at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:33)
at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:53)
at org.apache.logging.slf4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:33)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:363)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:132)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:655)
at org.springframework.boot.SpringApplication.<clinit>(SpringApplication.java:174)
... 1 more
this really drives me crazy, could you help me on this?

Related

The method getRootLogger() is undefined for the type Logger migration from Log4j 1.x to 2.x

I’m remediating from log4j1.x to Log4j2.x and trying to convert below to Lg4j2.x compatible.
Actually below code is used in Test cases
#Mock
private AppenderSkeleton appender;
Logger.getRootLogger().addAppender(appender);
I went through suggestions like
Dynamically add appender with slf4j and log4j2
How to add Log4J2 appenders at runtime programmatically?
I change like below
LogManager.getRootLogger().addAppender(appender);
But I am not able to find the replacement of addAppender(appender);
But its actually should be working, that's why issue.

Spring-Integration-Kafka BOM

quick question. Currently spring-integration-kafka doesn't appear to be a part of the BOM for spring-integration, so that when specifying dependencies in gradle it's an oddball out for having to declare the version (when using the spring dependencies plugin).
Is there a BOM somewhere I should be importing? No big deal if not.
plugins {
id 'org.springframework.boot' version '2.0.1.RELEASE'
id 'io.spring.dependency-management' version '1.0.5.RELEASE'
}
dependencyManagement {
imports {
// Need something here for spring-integration-kafka?
}
}
dependencies {
// Spring
compile "org.springframework.boot:spring-boot-starter-web"
compile "org.springframework.boot:spring-boot-starter-data-jpa"
compile "org.springframework.boot:spring-boot-starter-integration"
compile "org.springframework.integration:spring-integration-jms"
compile "org.springframework.integration:spring-integration-kafka:3.0.1.RELEASE"
}
No, there is not such an inclusion into any existing BOM.
We are still in doubts to merge it into the Core project or not: https://jira.spring.io/browse/INT-3966.
However that might be a good argument to include it into the Spring Boot dependency management. Feel free to raise an issue against Spring Boot.
One of the reason might like like there is a strong compatibility between Spring Integration Kafka & Spring Kafka and Apache Kafka per se. See the table in the end of the page: https://projects.spring.io/spring-kafka/

gradle NoSuchMethodError: org.apache.log4j.PatternLayout.<init>(Ljava/lang/String;)

(My second Gradle problem...)
I'm trying to setup a call to Velocity in one of my tasks. Velocity does a direct call to log4j which Gradle somehow seems to divert to its log4j-over-slf4j-1.7.2.jar, causing a NoSuchMethodError.
So I have:
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath 'org.apache.velocity:velocity:1.7'
// ... asumes provided:
classpath 'log4j:log4j:1.2.12'
}
}
And then later in a task I do...
def template = Velocity.getTemplate('src\\jnlp\\jnlpTemplate.vm')
This raises an exception. And the last part of the stacktrace is
Caused by: java.lang.NoSuchMethodError: org.apache.log4j.PatternLayout.<init>(Ljava/lang/String;)V
at org.apache.velocity.runtime.log.Log4JLogChute.initAppender(Log4JLogChute.java:117)
at org.apache.velocity.runtime.log.Log4JLogChute.init(Log4JLogChute.java:85)
at org.apache.velocity.runtime.log.LogManager.createLogChute(LogManager.java:157)
at org.apache.velocity.runtime.log.LogManager.updateLog(LogManager.java:269)
at org.apache.velocity.runtime.RuntimeInstance.initializeLog(RuntimeInstance.java:871)
at org.apache.velocity.runtime.RuntimeInstance.init(RuntimeInstance.java:262)
at org.apache.velocity.runtime.RuntimeInstance.requireInitialization(RuntimeInstance.java:302)
at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1531)
at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1514)
at org.apache.velocity.runtime.RuntimeSingleton.getTemplate(RuntimeSingleton.java:299)
at org.apache.velocity.app.Velocity.getTemplate(Velocity.java:358)
at org.apache.velocity.app.Velocity$getTemplate.call(Unknown Source)
at build_49a099islbrnod06rkiudfavms$_run_closure1.doCall(C:\home\...\build.gradle:67)
My analysis so far is as follows:
The constructor PatternLayout(String), that is called by Velocity is part of log4j's PatternLayout class, but it seems Gradle ends up resolving PatternLayout to a class in $GRADLE_HOME/lib/log4j-over-slf4j-1.7.2.jar. And that jar's PatternLayout seems to be a very minimal implementation lacking the requested constructor.
Is there some workaround here? Did I make some beginners mistake?
You have to remove the log4j jar from your app: the bridge log4j-over-slf4j and the log4j have the same methods, with the same signature (there could be some issues caused by different loading order into the classpath). If you want to use the bridge you don't need the log4j lib, you have to choose another logging framework which implements slf4j (for example log-back).
It could be a version issue. The version 1.7.2 of the bridge could be too high, try to downgrade to a lower version.

Not able to use variables defined in classes within groovy annotations

I am trying to port some code from the Dropwizard examples from java to groovy.
I see that within java, I can use the following code without any issues:
package com.example.helloworld;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
#Produces(MediaType.APPLICATION_JSON)
public class HelloWorldService{
}
However, with the groovy compiler ( both 1.8 and 2.0.6 ), the class fails to compile with a noClassFoundException around MediaType.APPLICATION_JSON
If I change this code to use the actual string value
#Produces('application/json')
public class HelloWorldService{
}
everything works perfectly.
Are there any differences between the way groovy resolves annotations and the way that java does?
For completeness, this is part of a gradle project and here is my build.gradle ( the file goes under src/groovy/com/example/helloworld )
apply plugin: 'groovy'
// Set our project variables
project.ext {
dropwizardVersion = '0.6.1'
}
repositories {
mavenCentral()
}
dependencies {
compile group: 'com.yammer.dropwizard', name: 'dropwizard-core', version: dropwizardVersion
groovy group: 'org.codehaus.groovy', name: 'groovy-all', version: '1.8.7'
}
The compilation error is:
Caused by: java.lang.RuntimeException:
java.lang.ClassNotFoundException:
com.sun.ws.rs.ext.RuntimeDelegateImpl ... 17 more Caused by:
java.lang.ClassNotFoundException:
com.sun.ws.rs.ext.RuntimeDelegateImpl at
org.gradle.api.internal.tasks.compile.TransformingClassLoader.findClass(TransformingClassLoader.java:47)
The problem is caused by an unfortunate limitation of the Groovy compiler, namely that it uses reflection to access classes on the compile class path. This may in turn trigger other classes to get loaded, which may not be available on the compile class path. Typically (but not always) these are runtime dependencies.
In the concrete case, the Groovy compiler loads javax.ws.rs.core.MediaType via reflection, which ultimately results in com.sun.ws.rs.ext.RuntimeDelegateImpl being loaded via Class.forName (triggered by a static initializer), which isn't on the compile class path. The solution is to put that class on the compile class path. (In the longer run, the solution is to fix the standalone Groovy compiler not to use reflection, and from what I know this is already in the queue.) If your module's transitive dependencies aren't an issue, the simplest way to achieve this is:
dependencies {
compile "com.sun.jersey:jersey-client:1.15"
}
I suspect that the Eclipse Groovy compiler doesn't have this problem because it doesn't use reflection to access the compile class path. I'd expect GMaven to blow up like Gradle, unless it is configured to use the Eclipse compiler (which isn't currently supported by Gradle).

Configure CXF JAX-WS service to work with MOXY

Although I've added a jaxb.properties with MOXY factory and I see that the JAXB was switched to moxy, CXF has a method named createRIContext in the JAXBUtils class which loads hard coded the sun JAXB implementation.
Is there a way to override it and use moxy instead?
The problematic code is the following:
// fall back if we're using another jaxb implementation
try {
riContext = JAXBUtils.createRIContext(contextClasses
.toArray(new Class[contextClasses.size()]), tns);
}
It loads hard coded the "com.sun.xml.bind.v2.ContextFactory" class and use it to create a JAXB context.
The 3.0.0-milestone2 version of CXF should handle Moxy quite a bit better. That said, there are still bugs in Moxy that have prevented all of the CXF unit and system tests to pass with it so we don't have the same level of confidence with Moxy as we do with the JAXB RI.
(any help with testing 3.0.0 would be greatly appreciated)

Resources