Monday, August 20, 2012

Debugging an SLF4J error, mvn dependency:tree to the rescue

As a Java developer, I frequently add additional dependencies to maven as new features are being built.  Sometimes you don't know what will break your build, but here's my "stack trace", as I worked through solving an error from:

 peterdietz:dspace-3.0-SNAPSHOT-build peterdietz$ /dspace/bin/dspace dsrun  
 Exception in thread "main" java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;[Ljava/lang/Object;Ljava/lang/Throwable;)V  
      at org.apache.commons.logging.impl.SLF4JLocationAwareLog.info(SLF4JLocationAwareLog.java:159)  
      at org.springframework.context.support.AbstractApplicationContext.prepareRefresh(AbstractApplicationContext.java:456)  
      at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:394)  
      at org.dspace.servicemanager.spring.SpringServiceManager.startup(SpringServiceManager.java:207)  
      at org.dspace.servicemanager.DSpaceServiceManager.startup(DSpaceServiceManager.java:205)  
      at org.dspace.servicemanager.DSpaceKernelImpl.start(DSpaceKernelImpl.java:150)  
      at org.dspace.app.launcher.ScriptLauncher.main(ScriptLauncher.java:51)  


Basically the error above means that you've got two different (incompatible versions of slf4j present 1.6 and 1.5). If your build output has a lib/ directory, check that for jars that have slf4j in their name. If you've got two different versions, thats your problem. Your quick fix would be to delete one of the versions (most likely 1.6).

However, to actually fix your problem, you've got to stop Maven from including two different versions of SLF4J. You can "Find in Path" from your IDE to see if you are manually including two different versions of SLF4J, but thats likely not the case, you'll need to look at Maven's dependency tree to see what has snuck both versions into your build.

mvn dependency:tree

Maven Dependency Tree will process all of your imports, all dependency entries in your pom.xml files, and recursively give you a tree output that will show which parent project includes which sub-project, which includes some feature, which includes which JAR. In my case, I was hunting down jcl-over-slf4j-1.6.1.jar. And looking through the output of mvn dependency:tree, I found it.


[INFO] +- org.dspace:dspace-stats:jar:3.0-SNAPSHOT:compile
[INFO] |  +- org.apache.solr:solr-solrj:jar:3.5.0:compile
[INFO] |  |  +- org.codehaus.woodstox:wstx-asl:jar:3.2.7:runtime
[INFO] |  |  \- org.slf4j:jcl-over-slf4j:jar:1.6.1:compile

To solve it, I found my pom.xml for the dspace-stats project. And specifically, the import for solr-solrj

 <dependency>  
   <groupId>org.apache.solr</groupId>  
   <artifactId>solr-solrj</artifactId>  
   <version>${lucene.version}</version>  
 </dependency>  


This will include solr-solrj, and all of its neccessary dependencies, and according to the dependency:tree, this is where slf4j has snuck through. So, we need to exclude slf4j from coming through, luckily maven lets us do exactly that. So, add the <exclusions> block below to this <dependency>, and you should be able to rebuild, and be all set. 

 <dependency>  
   <groupId>org.apache.solr</groupId>  
   <artifactId>solr-solrj</artifactId>  
   <version>${lucene.version}</version>  
   <exclusions>  
     <exclusion>  
       <groupId>org.slf4j</groupId>  
       <artifactId>slf4j-api</artifactId>  
     </exclusion>  
     <exclusion>  
       <groupId>org.slf4j</groupId>  
       <artifactId>jcl-over-slf4j</artifactId>  
     </exclusion>  
   </exclusions>  
 </dependency>  
Good Luck!

1 comment:

  1. Thank you very much! I've been googling for help for my problem for the past 5-6 hours. This worked! Cheers!

    ReplyDelete

Note: Only a member of this blog may post a comment.