Compile classpath order

In a multi-project environment I recently changed the logging API using SLF4J instead of log4j. Now I get strange compile errors in one module, which has a compile dependency to an older jetty jar which comes with our used runtime Eclipse version: “org.eclipse.equinox.http.jetty_2.0.100.v20110502.jar”

Inside this Jetty jar I discovered older versions of SLF4J (org.slf4j.Logger and org.slf4j.LoggerFactory). Now, these slf4j versions have a very different api compared to the current version 1.7.9.

The compile errors I get obvioulsy are the result of the classpath order which Gradle gives to the compiler; if I print the compile classpath of the module, I can see that the Eclipse jars are listed first - with no respect to the order in which I declare the compile classpath in the “build.gradle”.

I have the impression, that the ordering of the classpath is not a map of the order of the declarations in “build.gradle”; Gradle does some ordering with respect to where it can find compile dependencies. The point here seems to be: I declared dependencies on the Eclipse jars (which Jetty is a part of) as filestore dependencies, and now these filestore dependencies are listed first:

:com.tsystems.favbg.ui.core:printCompileClasspath
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.core.commands_3.6.0.I20110111-0800.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.core.expressions_3.4.300.v20110228.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.core.runtime_3.7.0.v20110110.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.osgi_3.7.2.v20120110-1415.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.equinox.common_3.6.0.v20110523.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.equinox.registry_3.5.101.R37x_v20110810-1611.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.ui.workbench_3.7.1.v20120104-1859.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.swt.win32.win32.x86_3.7.2.v3740f.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.jface_3.7.0.v20110928-1505.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\net.sf.paperclips_1.0.4.200908120926.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\net.sf.paperclips.ui_1.0.4.200908120926.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.equinox.preferences_3.4.2.v20120111-2020.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.nebula.widgets_1.0.0.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.core.databinding_1.4.0.I20110111-0800.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.core.databinding.beans_1.2.100.I20100824-0800.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.core.databinding.observable_1.4.0.I20110222-0800.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.jface.databinding_1.5.0.I20100907-0800.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.core.jobs_3.5.101.v20120113-1953.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.draw2d_3.7.2.v20111017-2020.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.root\target_3.7\org.eclipse.equinox.http.jetty_2.0.100.v20110502.jar
Q:\gradleCache\caches\modules-2\files-2.1\org.apache.commons\commons-lang3.3.20a3822c38ec8c996e84c16a3477ef632cbc87a3\commons-lang3-3.3.2.jar
Q:\gradleCache\caches\modules-2\files-2.1\org.slf4j\slf4j-api.7.972ec63b41181e29ad5a3723f1417356e2d2c0f2\slf4j-api-1.7.9.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.util\build\libs\de.uvdms.util-0.0.1.jar
Q:\sources\branches\DEV\trunkSLF4J\de.uvdms.common\build\libs\de.uvdms.common-0.0.1.jar
(..)

whereas the dependencies declared in “build.gradle” are declared like this:

dependencies {
         compile(project(':de.uvdms.util'),
  project(':de.uvdms.common'),
  (...)
 )
      compile (libraries.commons_beanutils,
       libraries.commons_io,
        libraries.javax_jms,
       libraries.spring_framework)
     compile files (lib_eclipse.core_commands,
    lib_eclipse.databinding,
   (...)
                lib_eclipse.jetty)
                          }

So, the question is, how to resolve this problem? Is there a way to influence classpath orderings done by Gradle?

Wondering if there is nobody here to give me a tip? The first help for me would be a work around (okay, I could hack the problematic jar). But then, I also think my problem reflects a deeper one. I suppose it could be a nice thing if one could influence the order of the classpath jars in such situations (normally, it isn’t an issue).

Hi

I asked almost the same thing quite some time ago. http://forums.gradle.org/gradle/topics/how_can_i_change_the_returned_order_of_dependencies_inside_a_configuration

The answer was to manipulate the classpath inside the IDE. It seems this is not an easy one. However, I don´t quite understand why it isn´t requested more often to be able to manipulate the classpath order from inside Gradle.

Well, I’m not within IDE, but in a pure Gradle environment. I think in situations like mine there should be some possibility to reorder the compile configuration. Or, to exclude classes/packages which come with a dependency jar.

(I must admit the situation results from a badly designed jar: “org.eclipse.equinox.http.jetty_2.0.100.v20110502.jar” should not include classes from SLF4J!)

Possibly a better solution is to use a tool like jarjar to repackage the jetty jar by removing slf4j classes . You could then depend on the repackaged jar instead of the official jetty jar. This repackage step could be automated as part of your build.

Yeah but all those things are workarounds for not having control of the classpath order…