0

I am having an issue where I wrote a fairly simple Spring Boot app and it runs using it's embedded Tomcat container just fine. Now I have to deploy it to my org's Glassfish (v3.1.2) and am running into the infamous "SLF4J: The requested version 1.6 by your slf4j binding is not compatible with [1.5.5, 1.5.6]"-error. I have also tried to deploy the same app to a standalone Tomcat with the same issue.


DISCLAIMER: I am by no means an expert in either Maven nor Spring-Boot; but I have googled and experimented until I am blue in the face and am unsure what's going on. Some guidance would be very appreciated.


So I downloaded the Spring-Boot sample app "gs-convert-jar-to-war" (https://github.com/spring-guides/gs-convert-jar-to-war) and it deploys just fine.

So then I tried to simply add spring-ldap-test to my dependencies and it won't deploy.

My POM:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.springframework</groupId>
<artifactId>gs-convert-jar-to-war</artifactId>
<version>0.1.0</version>
<packaging>war</packaging>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.0.0.RC5</version>
</parent>

<dependencies>


    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>


    <!-- <dependency>
      <groupId>org.springframework.ldap</groupId>
      <artifactId>spring-ldap-test</artifactId>
      <version>2.0.1.RELEASE</version>        
    </dependency> -->


</dependencies>

<properties>
    <start-class>hello.Application</start-class>
</properties>

<build>
    <plugins>
        <plugin> 
            <artifactId>maven-compiler-plugin</artifactId> 
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>http://repo.spring.io/libs-milestone</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
    <repository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>http://repo.spring.io/libs-snapshot</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>
<pluginRepositories>
    <pluginRepository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>http://repo.spring.io/libs-milestone</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </pluginRepository>
    <pluginRepository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>http://repo.spring.io/libs-snapshot</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </pluginRepository>
</pluginRepositories>
</project>

Now, this deploys just fine... other than there are a number of strange errors about the container not being able to find a bunch of things I'm not using (Mongo, Spring Batch, etc). I'm not sure what these are about, but the app does deploy. If anyone knows what these are and how to get rid of them, I'd love the feedback! These errors are similar to this one:

[#|SEVERE|glassfish3.1.2|Class [ com/mongodb/Mongo ] not found. Error while loading [ class org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration ]|#]

Like I said, though, the app does deploy just fine with these errors; that's not the crux of my problem.

The real problem is now I go and uncomment the spring-ldap-test dependency and try and deploy the app again. This time, however, no deploy. Right at the end of the attempted deploy, I see this error (some detail removed for readability):

[#|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|SLF4J: The requested version 1.6 by your slf4j binding is not compatible with [1.5.5, 1.5.6]|#]

So what's going on here? I included a single dependency, Spring-LDAP-Test, and suddenly everything is all screwy with SLF4J and my app won't deploy?

Here's my maven dependency graph (filtered for SLF):

localHost:complete butah$ mvn dependency:tree -Dincludes="*slf*"
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building gs-convert-jar-to-war 0.1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ gs-convert-jar-to-war ---
[INFO] org.springframework:gs-convert-jar-to-war:war:0.1.0
[INFO] +- org.springframework.boot:spring-boot-starter-thymeleaf:jar:1.0.0.RC5:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-web:jar:1.0.0.RC5:compile
[INFO] |  |  \- org.springframework.boot:spring-boot-starter:jar:1.0.0.RC5:compile
[INFO] |  |     \- org.springframework.boot:spring-boot-starter-logging:jar:1.0.0.RC5:compile
[INFO] |  |        +- org.slf4j:jul-to-slf4j:jar:1.7.6:compile
[INFO] |  |        \- org.slf4j:log4j-over-slf4j:jar:1.7.6:compile
[INFO] |  \- org.thymeleaf:thymeleaf-spring4:jar:2.1.2.RELEASE:compile
[INFO] |     \- org.slf4j:slf4j-api:jar:1.7.6:compile
[INFO] \- org.springframework.ldap:spring-ldap-test:jar:2.0.1.RELEASE:compile
[INFO]    \- org.springframework.ldap:spring-ldap-core:jar:2.0.1.RELEASE:compile
[INFO]       \- org.springframework.data:spring-data-commons:jar:1.7.1.RELEASE:compile
[INFO]          \- org.slf4j:jcl-over-slf4j:jar:1.7.6:compile

Note: I am trying to deploy this to a fresh stock install of GF. The only thing I have changed in it is I did define some JNDI stuff.

Based on my maven dependency graph, the only SLF4J stuff being used in 1.7.6 -- but my log claims there is a 1.5.5/6 version in the mix. Where could this be coming from, and how do I kill it? My thinking was perhaps it's in spring-ldap-test -- but if so, shouldn't that be showing up in my graph?

I'm at a loss. I'm hoping some of you Spring-Boot experts can help me get off the ground with my org's first Spring-Boot project.

:)

Bane
  • 1,772
  • 3
  • 21
  • 28

1 Answers1

1

So, not being a Maven or SpringBoot expert, but getting a tip from a sysops guy he pointed out that Spring-Ldap-Test depends on ApacheDS-ALL and that that project in turn depends on SLF4J stuff. Once he deleted the SLF4J stuff from the ApacheDS jar in the WAR, it deployed just fine.

So this reminded me that I'd seen similar SLF4J issues on another Apache-project previously... ApacheMQ. I learned that ApacheMQ-ALL "shades in" their dependency to SLF4J and that this causes the version conflict. In that case, rather than declaring ApacheMQ-ALL as my dependency, I declared the specific ApacheMQ modules I needed instead. That worked.

In this case I can't do that because my project isn't the one depending on ApacheDS-ALL, I'm depending instead on Spring-Ldap-Test (who depends on ApacheDS-ALL). So what I did instead was explicitly declare my dependence on ApacheDS-ALL but use a newer version (which happens to pick up a newer SLF4J that's compatible).

In other words, my POM now has this:

    <!-- NOTE: Spring-Ldap-Test includes ApacheDS-ALL but this
         version gets ApacheDS 1.5.5 and ApacheDS-ALL "shades"
         in SLF4J, which can cause conflicts if your project is
         using a different version of SLF4J elsewhere.
     -->
    <dependency>
      <groupId>org.springframework.ldap</groupId>
      <artifactId>spring-ldap-test</artifactId>
      <version>2.0.1.RELEASE</version>                
    </dependency>
    <!-- Explicitly declare a newer version of ApacheDS-ALL in order to
         inherit a newer version of SLF4J because Spring-Ldap-Test was
         using an older SLF4J and that was conflicting with the newer
         version in use by Spring-Boot   
     -->
    <dependency>
        <groupId>org.apache.directory.server</groupId>
        <artifactId>apacheds-all</artifactId>
        <version>2.0.0-M16</version>
    </dependency> 

I have no idea if this is the ideal solution, but it does seem to work. If someone more knowledgable than I could chime in, would be much appreciated.

Personally, I've been bit by Apache's "ALL" projects now twice, and I think it sucks. I don't know why they choose to make those, but I think if they are going to do that they should have huge disclaimers to tell other library-builders to not use that version.

And it seems Spring-ldap-test should not be using that module.

Bane
  • 1,772
  • 3
  • 21
  • 28
  • 1
    Very useful to know that. If I were you I'd try and exclude the "-all" dependency completely and replace it with a saner choice of clean dependencies. What that is depends on what you need to do I guess. See [here](https://jira.spring.io/browse/LDAP-301) for an issue I raised with Spring LDAP. – Dave Syer Apr 03 '14 at 06:52
  • @DaveSyer saw that, thanks so much for doing that! I'll have to try ur suggestion here bc mine didn't work in my real project; the API between v2 and 1.5 isn't equivalent enough. SpringLdapTest is expecting class org/apache/directory/server/core/partition/Partition but v2 apparently doesn't have that class any longer (getting a NoClassDefFoundError). Will try ur suggest and report. – Bane Apr 03 '14 at 15:10