When using the h2o-genmodel.jar
(either from maven central or that is output when generating a mojo) SLF4j gives the error
SLF4J: Class path contains multiple SLF4J bindings
SLF4J: Found binding in [jar:file:~/.ivy2/cache/org.slf4j/slf4j-log4j12/jars/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
Using maven or SBT's transitive dependency exclusion doesn't work, so right now I'm using the jar output with the mojo and removing the dependencies from inside the jar by hand.
Is there some better way to use h2o modelgen without having to manually mess with the inside of the jar (using maven instead would be preferable)?
So this ended up being a case of too hasty to post on SO
Using maven or SBT's transitive dependency exclusion doesn't work
ended up not being true. I simply needed to refresh SBT one time more.
I'll leave this question up though for reference. mvnrepository.com might indicate that this is a pom dependency and you should include the dependency like
libraryDependencies += "ai.h2o" % "h2o-genmodel" % "3.18.0.11" % "runtime" pomOnly()
or
<dependency>
<groupId>ai.h2o</groupId>
<artifactId>h2o-genmodel</artifactId>
<version>3.18.0.11</version>
<type>pom</type>
<scope>runtime</scope>
</dependency>
but it seems from experimentation that that does not work, and hex.genmodel...
packages will not be available
To get the dependencies working and not pull in the slf4j binding you should use
libraryDependencies += "ai.h2o" % "h2o-genmodel" % "3.18.0.11" exclude("org.slf4j", "slf4j-log4j12")
or
<dependency>
<groupId>ai.h2o</groupId>
<artifactId>h2o-genmodel</artifactId>
<version>3.18.0.11</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
h2o-genmodel
it's a pom type dependency. That means you use it as an aggregator for multiple dependencies to make your life easier. Your problem arise from the fact that the ai.h2o:deepwater-backend-api:jar:1.0.4
dependency of h2o-genmodel
has a transient dependency to org.slf4j:slf4j-log4j12:jar:1.7.5
. You can debug the dependency hierarchy by using the dependency maven plugin, run the following command:
> mvn dependency:tree
...
[INFO] \- ai.h2o:h2o-genmodel:pom:3.18.0.11
[INFO] +- net.sf.opencsv:opencsv:jar:2.3
[INFO] +- com.google.code.gson:gson:jar:2.6.2
[INFO] +- com.google.protobuf.nano:protobuf-javanano:jar:3.1.0
[INFO] \- ai.h2o:deepwater-backend-api:jar:1.0.4
[INFO] \- org.slf4j:slf4j-log4j12:jar:1.7.5
[INFO] +- org.slf4j:slf4j-api:jar:1.7.5
[INFO] \- log4j:log4j:jar:1.2.17
To fix this, you can exclude the slf4j-log4j12
dependency from h2o-genmodel
dependency with this:
<dependency>
<groupId>ai.h2o</groupId>
<artifactId>h2o-genmodel</artifactId>
<version>3.18.0.11</version>
<type>pom</type>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
You can run again the maven dependency tree command to check how many slf4j bindings remained.
Because the error complains of multiple slf4j bindings I assume once you make sure there is only one slf4j binding in the dependency tree everything will be fine at runtime.
UPDATE:
More details why this solution works:
First, the ai.h2o:h2o-genmodel
dependency is declared as type pom is because this is how it is published. A maven artefact of type pom is used in two cases: as an aggregator for submodules or as an aggregator for dependencies. In this case, the pom type is used in second scenario, to pack dependencies for ai.h2o:h2o-genmodel
. To varify this, you can check your maven local repository (most likely at ${user.home}/.m2/repository/ai/h2o/h2o-genmodel/3.18.0.11 there is no jar file, only the .pom. Please read this documentation Introduction to the Dependency Mechanism and POM Relationships
Another issue, might be the fact that ai.h2o:h2o-genmodel
doesn't adhere to recommended way to wrap dependencies because it doesn't use <dependencyManagement>
, but instead is using <dependencies>
. Because of this, the details on maven documentation is not working exactly as expected. To overcome this, you have to use ai.h2o:h2o-genmodel
explicitly on <dependencies>
and adjust manually the scope of each dependency behind it. I strongly suggest to run the mvn dependency:tree
because will display the scope of each dependency. In my output I removed the scopes because I didn't want it to polute the answer.
In conclusion, why in my solution works with dependency declared as pom and in @kag0 not as pom is because the ai.h2o:h2o-genmodel
is of type pom and maven treat it in same way becaue when the <type>
is missing it infers it from the artefact pom.