1
votes

I'm using Play framework with a custom logger (Log4j2) replacing the default Play logger (Logback).

I followed the procedure described in the documentation : https://www.playframework.com/documentation/2.6.x/SettingsLogger

In build.sbt:

lazy val root = (project in file("."))
  .enablePlugins(PlayJava)
  .disablePlugins(PlayLogback)
libraryDependencies ++= Seq(
  "org.apache.logging.log4j" % "log4j-slf4j-impl" % "2.4.1",
  "org.apache.logging.log4j" % "log4j-api" % "2.4.1",
  "org.apache.logging.log4j" % "log4j-core" % "2.4.1"
)

Everything works well, until I try to add a custom module written for Play: https://github.com/alexanderjarvis/play-jongo

Being a Play module, it also has a build.sbt where the Logback isn't disabled.

When trying to run my software with the imported module, I get this error:

java.lang.ClassCastException: org.apache.logging.slf4j.Log4jLoggerFactory cannot be cast to ch.qos.logback.classic.LoggerContext
    at play.api.libs.logback.LogbackLoggerConfigurator.configure(LogbackLoggerConfigurator.scala:92)
    at play.api.libs.logback.LogbackLoggerConfigurator.init(LogbackLoggerConfigurator.scala:31)
    at play.core.server.DevServerStart$.$anonfun$mainDev$1(DevServerStart.scala:88)
    at play.utils.Threads$.withContextClassLoader(Threads.scala:21)
    at play.core.server.DevServerStart$.mainDev(DevServerStart.scala:59)
    at play.core.server.DevServerStart$.mainDevHttpMode(DevServerStart.scala:49)
    at play.core.server.DevServerStart.mainDevHttpMode(DevServerStart.scala)
    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 play.runsupport.Reloader$.startDevMode(Reloader.scala:230)
    at play.sbt.run.PlayRun$$anonfun$playRunTask$1$$anonfun$apply$2$$anonfun$apply$3.devModeServer$lzycompute$1(PlayRun.scala:79)
    at play.sbt.run.PlayRun$$anonfun$playRunTask$1$$anonfun$apply$2$$anonfun$apply$3.play$sbt$run$PlayRun$$anonfun$$anonfun$$anonfun$$devModeServer$1(PlayRun.scala:79)
    at play.sbt.run.PlayRun$$anonfun$playRunTask$1$$anonfun$apply$2$$anonfun$apply$3.apply(PlayRun.scala:102)
    at play.sbt.run.PlayRun$$anonfun$playRunTask$1$$anonfun$apply$2$$anonfun$apply$3.apply(PlayRun.scala:65)
    at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
[trace] Stack trace suppressed: run last compile:run for the full output.
[error] (compile:run) java.lang.reflect.InvocationTargetException
[error] Total time: 1 s, completed 18 juin 2018 16:04:02

Obviously there is a conflict between the Logback transitive dependency from the module and the imported log4j2.

So I tried to exclude Logback when importing the jongo module:

"uk.co.panaxiom" %% "play-jongo" % "2.1.0-jongo1.3" exclude("ch.qos.logback", "logback-classic")

Then got a completely different error:

[WARN] [06/18/2018 15:59:12.432] [pool-6-thread-1] 
[EventStream(akka://play-dev-mode)] Logger log1-Slf4jLogger did not respond within Timeout(5000 milliseconds) to     InitializeLogger(bus)
error while starting up loggers
akka.ConfigurationException: Logger specified in config can't be loaded 
[akka.event.slf4j.Slf4jLogger] due to 
[akka.event.Logging$LoggerInitializationException: Logger log1-Slf4jLogger did not respond with LoggerInitialized, sent instead [TIMEOUT]]

Has anyone had the same issue when importing Play modules while using a custom logger? Or do you have any idea on how to solve this issue?

Thanks for any (helpful) advice on this :)

1

1 Answers

0
votes

The PlayLogback plugin causes the "com.typesafe.play" %% "play-logback" % Play-Version module to be added to the libraryDependencies. Indeed play-jongo has this dependency: http://www.mvnrepository.com/artifact/uk.co.panaxiom/play-jongo_2.12/2.1.0-jongo1.3

You need to exclude this component from the dependencies to prevent that Play's LogbackLoggerConfigurator is trying to start.

edit:

To exclude a Scala dependency, you have to include the scala binary version in its name:

"uk.co.panaxiom" %% "play-jongo" % "2.1.0-jongo1.3" exclude("com.typesafe.play", "play-logback_2.12")