StaticLoggerBinder Linkage error when running development mode

208 views
Skip to first unread message

Colin Bester

unread,
Aug 11, 2016, 1:51:58 PM8/11/16
to Lift
I have an issue in how to setup a maven based liftweb project in order to run development mode (using mvn jetty:run) and to deploy to jetty server and not have logging issues.

Presently I can either have dev system working fine with warning on multiple binding found when running on jetty system or I can have development system failing to run due to linkage errors and deployed system working with no warnings.

In my maven pom file I have added logback-classic dependency to jetty-maven-plugin in order to include jar while when running in dev system but not in deployed WARf file.

With logback-classic dependency ONLY listed in plugin..

<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.2.v20140723</version>
<configuration>
        <httpConnector>
          <!--host>localhost</host-->
          <port>${jetty.http.port}</port>
        </httpConnector>
<webApp>
<contextPath>/bc</contextPath>
</webApp>
<webAppSourceDirectory>
${project.basedir}/src/main/webapp
</webAppSourceDirectory>
<scanIntervalSeconds>0</scanIntervalSeconds>
<reload>manual</reload>
<systemProperties>
<systemProperty>
<name>logback.configurationFile</name>
<value>./src/main/resources/logback.xml</value>
</systemProperty>
</systemProperties>
</configuration>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.3</version>
</dependency>
</dependencies>
</plugin>

If I don't include this dependency (in plugin) then when running (using mvn jetty:run) I get expected warning message:


SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".


However, when including this dependency I get linkage error:


java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader (instance of org/eclipse/jetty/webapp/WebAppClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of org/codehaus/plexus/classworlds/realm/ClassRealm) for resolved class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type LoggerFactory; used in the signature


If I add logback-classic as normal dependency in pom.xml (in addition to in plugin) and set Scope to compile then it works in development system but gives warnings in deployed system of multiple bindings found. If I set Scope to provided (as I'd expect) then dev system fails with linkage error above but no multiple bindings warning in deployed system.

Not sure if anyone else has dug into this or has ideas/suggestions on correct way to setup development system to avoid this issue.

Maybe I am worrying too much about the multiple bindings but it is something I want control on to ensure I know which jar files are being used.

Using scala-ide (eclipse), liftweb 2.6.3, scala 2.10.6 and mvn 3.3.9.

Diego Medina

unread,
Aug 11, 2016, 10:45:13 PM8/11/16
to Lift
I don't use maven but maybe this link will help track down the warning you get about multiple matches


Hope it helps.

Also, do you have to use maven? There is a lot of sample Lift projects with logging, but based on sbt, and as long as you don't want to do black magic with it, it's pretty simple to get going.

Thanks

Diego


--
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code

---
You received this message because you are subscribed to the Google Groups "Lift" group.
To unsubscribe from this group and stop receiving emails from it, send an email to liftweb+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Diego Medina
Lift/Scala Consultant
di...@fmpwizard.com
http://blog.fmpwizard.com/

Colin Bester

unread,
Aug 12, 2016, 8:14:32 AM8/12/16
to Lift
Thanks Diego, I had looked at that link as well, and like nearly 99% of similar responses it deals with deployment and not development side of the equation. Adding logback-classic with compile scope to dependency creates multiple binding warnings where solution is to set Scope to provided (which makes sense) but then development side fails (even with adding dependency to jetty plugin settings).

Strange thing is I only have this issue with liftweb project. I have scala spray restful projects using very similar mvn POM.xml files and they work as expected. Logger settings in maven are exactly the same across liftweb and spray projects. All my restful spray projects don't show this behavior, only my liftweb projects do, there has to be a clue there, but I don't see it.

On Thursday, August 11, 2016 at 9:45:13 PM UTC-5, fmpwizard wrote:
I don't use maven but maybe this link will help track down the warning you get about multiple matches


Hope it helps.

Also, do you have to use maven? There is a lot of sample Lift projects with logging, but based on sbt, and as long as you don't want to do black magic with it, it's pretty simple to get going.

Thanks

Diego

Matt Farmer

unread,
Aug 14, 2016, 10:37:02 AM8/14/16
to Lift
Hey Colin,

Can you humor me for a minute?

Can you try making the dependency "provided" and just finding the JAR file for it yourself and dropping it in some unmanaged class folder? For sbt this is normally "lib/" under the project's working directory.

Colin Bester

unread,
Aug 14, 2016, 11:06:25 AM8/14/16
to Lift

Thanks Matt, normally “provided" is what I’d set it to and supply the file via jetty maven plugin. I will check how to manually add with a maven based project and give it a try.


Also note that for other jetty based project this works, it’s only lift web project that doesn’t work while in dev environment.


Somehow, I think "org/codehaus/plexus/classworlds/realm/ClassRealm” is at play.

Matt Farmer

unread,
Aug 14, 2016, 4:09:31 PM8/14/16
to Lift
> Also note that for other jetty based project this works, it’s only lift web project that doesn’t work while in dev environment.

Yeah, I noticed that, but logback-classic is also marked as provided in our main dependency file.


So, something with the classpath is behaving strangely. Somehow your other projects are resolving the plugin classpath while your Lift project isn't.

Is this trivially reproducible? Like, if you start a project completely from scratch and wire up the plugin / dependencies does it reproduce?

Colin Bester

unread,
Aug 14, 2016, 4:23:27 PM8/14/16
to Lift
"provided" definitely does the job from a deployment point of view as when "provided" is set there are not duplicate binding warning when firing up deployment jetty. Also if I remove jar files from jetty lib/ext then I get error that library is not found (as expected).

If I have set dependency to provided in maven dependencies and do not include dependency in jetty maven plugin then I get error of no binding found when executing mvn jetty:run (dev system). If I do include dependency in jetty-plugin (as I do my other projects) I get error stated when executing mvn jetty:run. This would suggest to me that there is no duplicate binding (else it would fail to find binding if not declared in plugin configuration), and that it is doing something when it is included, but why different to my spray projects I have no idea (my spray projects and liftweb projects share the same parent POM but have their own jetty maven plugin setup (which are identical).

I have tried in past to create new projects and see the same behaviour. I will create new mvn liftweb project tomorrow and test and report back.

Colin Bester

unread,
Aug 15, 2016, 9:11:14 AM8/15/16
to Lift
I confirm I see the same behavior using new test project. I used one of the mvn arch types and updated versions to match.

In response to "humor me" test:

1) I added logback-classic-1.1.7.jar, logback-core-1.1.7 to webapp/WEB-INF/lib folder

Set scope to provided:

 <dependency>
   
<groupId>ch.qos.logback</groupId>
   
<artifactId>logback-classic</artifactId>

   
<version>${logback-classic.version}</version>
   
<scope>provided</scope>
 
</dependency>

Left dependency in jetty-maven-plugin

<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.2.v20140723</version>
<configuration>
        <httpConnector>
          <port>${jetty.http.port}</port>
        </httpConnector>
<webApp>
<contextPath>/bc</contextPath>
</webApp>
<webAppSourceDirectory>
${project.basedir}/src/main/webapp
</webAppSourceDirectory>
<scanIntervalSeconds>0</scanIntervalSeconds>
<reload>manual</reload>
<systemProperties>
<systemProperty>
<name>logback.configurationFile</name>
<value>./src/main/resources/logback.xml</value>
</systemProperty>
</systemProperties>
</configuration>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback-classic.version}</version>
</dependency>
</dependencies>
</plugin>


Executed with "mvn jetty:run"

Got expected dual binding warning:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/colinbes/coding/AdvancedBioWS/biocharger-cloud/src/main/webapp/WEB-INF/lib/logback-classic-1.1.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/colinbes/.m2/repository/ch/qos/logback/logback-classic/1.1.7/logback-classic-1.1.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]

2) Removed dependency setting from within jetty-maven-plugin

No dual binding, no warning of no binding.

Appears plugin is definitely loading the jar (else we wouldn't have the dual binding, but somehow if not included in path (either static via lib/ folder or via dependency scope set to 'compile' we have 

3) Added dependency back into jetty-maven-plugin (as per point 1), removed WEB-INF/lib folder:

[ERROR] Failed to execute goal org.eclipse.jetty:jetty-maven-plugin:9.2.10.v20150310:run (default-cli) on project web-application: Execution default-cli of goal org.eclipse.jetty:jetty-maven-plugin:9.2.10.v20150310:run failed: An API incompatibility was encountered while executing org.eclipse.jetty:jetty-maven-plugin:9.2.10.v20150310:run: java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader (instance of org/eclipse/jetty/webapp/WebAppClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of org/codehaus/plexus/classworlds/realm/ClassRealm) for resolved class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type LoggerFactory; used in the signature

[ERROR] -----------------------------------------------------

[ERROR] realm =    plugin>org.eclipse.jetty:jetty-maven-plugin:9.2.10.v20150310

[ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy

[ERROR] urls[0] = file:/Users/colinbes/.m2/repository/org/eclipse/jetty/jetty-maven-plugin/9.2.10.v20150310/jetty-maven-plugin-9.2.10.v20150310.jar

[ERROR] urls[1] = file:/Users/colinbes/.m2/repository/ch/qos/logback/logback-classic/1.1.7/logback-classic-1.1.7.jar

[ERROR] urls[2] = file:/Users/colinbes/.m2/repository/ch/qos/logback/logback-core/1.1.7/logback-core-1.1.7.jar

[ERROR] urls[3] = file:/Users/colinbes/.m2/repository/org/sonatype/sisu/sisu-inject-bean/2.1.1/sisu-inject-bean-2.1.1.jar

[ERROR] urls[4] = file:/Users/colinbes/.m2/repository/org/sonatype/sisu/sisu-guice/2.9.4/sisu-guice-2.9.4-no_aop.jar

[ERROR] urls[5] = file:/Users/colinbes/.m2/repository/org/codehaus/plexus/plexus-utils/2.0.6/plexus-utils-2.0.6.jar

[ERROR] urls[6] = file:/Users/colinbes/.m2/repository/org/sonatype/aether/aether-util/1.11/aether-util-1.11.jar

[ERROR] urls[7] = file:/Users/colinbes/.m2/repository/org/codehaus/plexus/plexus-interpolation/1.14/plexus-interpolation-1.14.jar

[ERROR] urls[8] = file:/Users/colinbes/.m2/repository/org/codehaus/plexus/plexus-component-annotations/1.5.5/plexus-component-annotations-1.5.5.jar

[ERROR] urls[9] = file:/Users/colinbes/.m2/repository/org/sonatype/plexus/plexus-sec-dispatcher/1.3/plexus-sec-dispatcher-1.3.jar

[ERROR] urls[10] = file:/Users/colinbes/.m2/repository/org/sonatype/plexus/plexus-cipher/1.4/plexus-cipher-1.4.jar

[ERROR] urls[11] = file:/Users/colinbes/.m2/repository/org/apache/maven/plugin-tools/maven-plugin-tools-api/3.1/maven-plugin-tools-api-3.1.jar

[ERROR] urls[12] = file:/Users/colinbes/.m2/repository/backport-util-concurrent/backport-util-concurrent/3.1/backport-util-concurrent-3.1.jar

[ERROR] urls[13] = file:/Users/colinbes/.m2/repository/org/eclipse/jetty/jetty-util/9.2.10.v20150310/jetty-util-9.2.10.v20150310.jar

[ERROR] urls[14] = file:/Users/colinbes/.m2/repository/org/eclipse/jetty/jetty-webapp/9.2.10.v20150310/jetty-webapp-9.2.10.v20150310.jar



On Sunday, August 14, 2016 at 9:37:02 AM UTC-5, Matt Farmer wrote:

Matt Farmer

unread,
Aug 15, 2016, 9:40:26 AM8/15/16
to Lift
Can you push this to a github repository for me to look at?


Matt Farmer | Blog | Twitter
GPG: CD57 2E26 F60C 0A61 E6D8  FC72 4493 8917 D667 4D07

--
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code

---
You received this message because you are subscribed to the Google Groups "Lift" group.
To unsubscribe from this group and stop receiving emails from it, send an email to liftweb+u...@googlegroups.com.

Colin Bester

unread,
Aug 15, 2016, 11:25:25 AM8/15/16
to Lift

Sorry this is turning out to be larger than I thought, I thought maybe I was doing something silly.


Note I am running on mac osx El Capitan, 10.11.6 and have eclipse running using jvm  jdk1.8.0_66.jdk.

Eclipse build 4.4.1-vfinal-2016-05-04T11:16:00Z-Typesafe

For testing, logback files are added to WEB-INF/lib folder. This is only for testing and not for deployement. I also included slf4j in case you wanted to test with it as well.

Matt Farmer

unread,
Aug 15, 2016, 1:32:10 PM8/15/16
to Lift
Excellent thanks. When I get a moment to take a break from work I’ll spin it up and take a look. :-)


Matt Farmer | Blog | Twitter
GPG: CD57 2E26 F60C 0A61 E6D8  FC72 4493 8917 D667 4D07

Matt Farmer

unread,
Aug 18, 2016, 10:26:53 AM8/18/16
to Lift
Sorry, got a little bit swamped at work this week. Cloning this repo now. Haha.


Matt Farmer | Blog | Twitter
GPG: CD57 2E26 F60C 0A61 E6D8  FC72 4493 8917 D667 4D07

Colin Bester

unread,
Aug 18, 2016, 10:54:49 AM8/18/16
to lif...@googlegroups.com
I fully understand :-)


You received this message because you are subscribed to a topic in the Google Groups "Lift" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/liftweb/kfGNW9FoM8Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to liftweb+u...@googlegroups.com.

Matt Farmer

unread,
Aug 18, 2016, 1:51:28 PM8/18/16
to Lift
Okay, tinkered with this for a few minutes. Things seem to behave for me if I make logback-classic a regular dependency and don’t mention it in the plugin dependencies though. I tested using a jetty:9.2 docker image and the mvn command and didn’t see any complaints from SLF4J….

I’m not sure why things got screwy there, but I don’t think it’s anything intentionally silly we’ve done.

Will this configuration work for you?


Matt Farmer | Blog | Twitter
GPG: CD57 2E26 F60C 0A61 E6D8  FC72 4493 8917 D667 4D07

Colin Bester

unread,
Aug 18, 2016, 2:08:07 PM8/18/16
to Lift

That would make sense except that in my case I am serving several web apps from one jetty instance and have the logback-classic jar file in lib/ext. I need no logback-classic (and it’s dependencies) in my war file (which is purpose of scope=provided, but then dev breaks as discussed).


If logbook-classic is a regular dependency then it will complain of multiple bindings - one in ext directory and other in war file.


If I was only serving one web application I wouldn’t add .jar file to lib/ext but seeing as there are several web apps (war files) for one jetty instance I prefer having fixed dependency and managed by jetty install and not by one of the war files.

Matt Farmer

unread,
Aug 18, 2016, 5:09:37 PM8/18/16
to lif...@googlegroups.com
Ahh. Okay. I'm starting to understand. Okay. Then the interesting bit here is that somehow the other apps are pulling log back into their development class path and that isn't happening with Lift. Hm. 

Yeah so in this case using some sort of unmanaged class path on your development machine is probably what I would do. That way it would work locally but not be thrown into your WAR. I need to think about why this doesn't cause problems for your other apps. 


Matt Farmer Blog | Twitter
GPG: CD57 2E26 F60C 0A61 E6D8  FC72 4493 8917 D667 4D07
--

Colin Bester

unread,
Aug 18, 2016, 5:14:11 PM8/18/16
to Lift
In the other apps, I include jar in development path by adding dependency to jetty-maven-plugin which adds jar only in dev environment running app via mvn jetty:run, same trick doesn't work in lift unless dependency is set to 'compile' (other apps have main dependency set to 'provided'.

Diego Medina

unread,
Aug 18, 2016, 10:57:44 PM8/18/16
to Lift
Now that I see more of the issue, this may be related to something I noticed using sbt + apache shiro, where using shirot in your Lift project would mean that you could not configure logback using the production | testing | default naming convention.


I know you are not using shiro, but maybe it will give you an idea of where to look, it may be that Lift and the maven jetty plugin are doing something diff with classpath search path.

I never figured out why Shiro was messing with Lift and then moved on to not using Shiro any more

Thanks

Diego



--
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code

---
You received this message because you are subscribed to the Google Groups "Lift" group.
To unsubscribe from this group and stop receiving emails from it, send an email to liftweb+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Matt Farmer

unread,
Aug 19, 2016, 8:30:39 AM8/19/16
to lif...@googlegroups.com
Yeah. The dependency for us is set to provided as well. So this should work the same. There's something bizarre going on here. Heh. 


Matt Farmer Blog | Twitter
GPG: CD57 2E26 F60C 0A61 E6D8  FC72 4493 8917 D667 4D07
Reply all
Reply to author
Forward
0 new messages