renatoathaydes / ceylon-gradle-plugin

A simple Gradle plugin to manage Ceylon projects.
22 stars 6 forks source link

Support new feature: --fully-export-maven-dependencies #16

Closed DiegoCoronel closed 7 years ago

DiegoCoronel commented 7 years ago

Ceylon 1.3.1 was released and adds this new feature that changes how it deals with maven transitive dependencies.

You can see the thread about how it works from ceylon issue: https://github.com/ceylon/ceylon/issues/6597

DiegoCoronel commented 7 years ago

This issue is related to this questions in SO: http://stackoverflow.com/questions/40750544/error-compiling-ceylon-example-with-gradle

renatoathaydes commented 7 years ago

Thanks for letting me know... I saw Ceylon 1.3.1 was released just yesterday... good to know they made some Maven improvements, will see what I need to do to get it working again!

renatoathaydes commented 7 years ago

Hi @DiegoCoronel . The work the Ceylon team did on Maven dependencies seems to me to be orthogonal to Gradle. If you use this flag, you probably don't want to rely on Gradle sorting out your dependencies. Notice that the Gradle Plugin not only uses Gradle's dependency resolution mechanism (which is the best out there), it also builds a local repository with the resolved dependencies that is used to create a consistent, offline runtime. It then points the Ceylon compiler to that, so that it does not try to resolve dependencies itself.

So I don't see how adding support for this flag would be beneficial to Gradle users. Could you explain in what situation do you think that would be the case?

That said, the SO question seems to imply that Ceylon by default is turning on this flag?! Is that what caused the problem?

If so, I will have to make Gradle turn that flag off by default, right? So we don't run into this kind of problem?

renatoathaydes commented 7 years ago

@DiegoCoronel I don't know what's the problem. I've been able to run all test projects with Ceylon 1.3.1 without errors.

Adding this import (as in the SO question) to a Ceylon module also did not cause any problems:

import ceylon.interop.java "1.3.0";

Can you reproduce that SO question error??

DiegoCoronel commented 7 years ago

Hi @renatoathaydes , yes Im able to reproduce the error and because that i had in mind that it could be related to how your plugin works, using pure ceylon it does work but i was not able to make it work with your plugin.

Now a personal opinion: I think we could have only one way to deal with dependencies, if i remember you created this plugin at first because it was not easy to work with dependencies using only ceylon, but i believe now its not the case anymore and it can be a problem to have 2 ways to deals with dependencies and it can be confuse to new users.

renatoathaydes commented 7 years ago

Please send a link to the project you have which does not work with the Gradle plugin.

renatoathaydes commented 7 years ago

I think we could have only one way to deal with dependencies

That's the Ceylon way, but unfortunately that did never work with Maven... if you want to use Gradle and let Ceylon resolve dependencies, you can easily do that by not using this plugin. If you use this plugin, it means you want to use Gradle to resolve dependencies and create your runtime (which may have become obsolete now, which is fine!).

To also give my personal opinion: What the Ceylon team did with this flag is heroic, but honestly, I find it hard to believe they did a better job than Gradle on dependency resolution (a notoriously difficult problem) :) With Gradle, you have fine control over dependency resolution strategies, exclusions, repositories etc. So I think it's still a very valid option, even with the new Ceylon flag.

DiegoCoronel commented 7 years ago

Right, thanks for your feedback, I respect your opinion and I think its valid. This is the project: https://github.com/DiegoCoronel/ceylon-spring-boot/tree/gradle_with_ceylon , i created this branch with gradle and settings. The command i tried: gradle :gateway:compileCeylon even when i was able to compile (adding antlr/2.7.7 to module.ceylon) i was not able to run it.

renatoathaydes commented 7 years ago

It seems that the Ceylon compiler's behaviour has changed even when you do not use this flag.

When the Ceylon compiler resolves dependencies, it's no longer respecting the overrides file and the --rep flag in the same way... Even though Gradle correctly resolves the dependencies (as you would expect) and adds the jars/poms to the right places, Ceylon 1.3.1 seems to try to find them somewhere else and fails to?! At least in my machine, I can see that the Gradle plugin put the dependencies that Ceylon say it's missing in the local repo it built (and was pointed with the --rep:aether flag).

DiegoCoronel commented 7 years ago

Right, let link @quintesse to get some help with this question

renatoathaydes commented 7 years ago

ceylon compile succeeds, but ceylon run fails... It's a Ceylon bug because the dependency is available in the local repo. Why is it not finding it?

EDIT: and it works with Ceylon 1.3.0... only fails with Ceylon 1.3.1.

DiegoCoronel commented 7 years ago

I dont know if thats can be a ceylon bug because it does work using pure ceylon and fails using gradle, or am i wrong ?

renatoathaydes commented 7 years ago

Here's the more verbose Gradle output when I build using Ceylon 1.3.1:

Executing ceylon 'compile' in project spring-boot-sample
Running command: /Users/renato/.sdkman/candidates/ceylon/1.3.1/bin/ceylon compile --overrides /Users/renato/programming/projects/ceylon-gradle-plugin/ceylon-gradle-plugin-tests/spring-boot-sample/build/overrides.xml --flat-classpath --rep=aether:/Users/renato/programming/projects/ceylon-gradle-plugin/ceylon-gradle-plugin-tests/spring-boot-sample/build/maven-settings.xml --rep=/Users/renato/programming/projects/ceylon-gradle-plugin/ceylon-gradle-plugin-tests/spring-boot-sample/modules --out=/Users/renato/programming/projects/ceylon-gradle-plugin/ceylon-gradle-plugin-tests/spring-boot-sample/modules --source source --resource resource com.athaydes.springboot 
source/com/athaydes/springboot/module.ceylon:5: warning: use of old style Maven imports is deprecated, prefix with 'maven:'
    import "org.springframework.boot:spring-boot-starter-web" "1.3.0.RELEASE";
           ^
1 warning
Note: Created module com.athaydes.springboot/1.0.0
:spring-boot-sample:compileCeylon (Thread[Daemon worker,5,main]) completed. Took 2.487 secs.
:spring-boot-sample:runCeylon (Thread[Daemon worker,5,main]) started.
:spring-boot-sample:runCeylon
Putting task artifact state for task ':spring-boot-sample:runCeylon' into context took 0.0 secs.
Executing task ':spring-boot-sample:runCeylon' (up-to-date check took 0.0 secs) due to:
  Task has not declared any outputs.
Executing ceylon 'run' in project spring-boot-sample
Running command: /Users/renato/.sdkman/candidates/ceylon/1.3.1/bin/ceylon run --overrides /Users/renato/programming/projects/ceylon-gradle-plugin/ceylon-gradle-plugin-tests/spring-boot-sample/build/overrides.xml --flat-classpath --rep=aether:/Users/renato/programming/projects/ceylon-gradle-plugin/ceylon-gradle-plugin-tests/spring-boot-sample/build/maven-settings.xml --rep=/Users/renato/programming/projects/ceylon-gradle-plugin/ceylon-gradle-plugin-tests/spring-boot-sample/modules com.athaydes.springboot 
ceylon run: Could not find module: aopalliance/1.0
:spring-boot-sample:runCeylon FAILED
:spring-boot-sample:runCeylon (Thread[Daemon worker,5,main]) completed. Took 1.137 secs.

FAILURE: Build failed with an exception.

Notice Ceylon says it did not find aopalliance/1.0.

It seems to think aopalliance is a Ceylon dep, not a Maven dep?

This is a dependency of spring-aop and when you run gradle dep you see it's coordinates are aopalliance:aopalliance:1.0.

The local repo Gradle builds contains it in the correct place:

build/maven-repository/
├── aopalliance
│   └── aopalliance
│       └── 1.0
│           ├── aopalliance-1.0.jar
│           └── aopalliance-1.0.pom

So, not a bug in Gradle, definitely.

renatoathaydes commented 7 years ago

I dont know if thats can be a ceylon bug because it does work using pure ceylon and fails using gradle, or am i wrong ?

What fails is ceylon run, not the Gradle dependency resolution.

DiegoCoronel commented 7 years ago

But it fails when using ceylon run from gradle.. if i use ceylon run in console it does work.. but i think we could wait Tako to help with why we get different behavior

renatoathaydes commented 7 years ago

There's no such thing as ceylon run from Gradle... Gradle just calls Ceylon, see the output above... but it points it to the overrides and local repo it created... Here's the relevant part again:

Running command: /Users/renato/.sdkman/candidates/ceylon/1.3.1/bin/ceylon run --overrides /Users/renato/programming/projects/ceylon-gradle-plugin/ceylon-gradle-plugin-tests/spring-boot-sample/build/overrides.xml --flat-classpath --rep=aether:/Users/renato/programming/projects/ceylon-gradle-plugin/ceylon-gradle-plugin-tests/spring-boot-sample/build/maven-settings.xml --rep=/Users/renato/programming/projects/ceylon-gradle-plugin/ceylon-gradle-plugin-tests/spring-boot-sample/modules com.athaydes.springboot 
ceylon run: Could not find module: aopalliance/1.0
DiegoCoronel commented 7 years ago

Also linking @FroMage that did some work with maven interop

FroMage commented 7 years ago

OK, I found why it's happening: it's due to the fact that the module has no . in it and we take it for a namespace. That's a bug in ceylon, I'll report it and fix it.

FroMage commented 7 years ago

One thing I don't understand though is why the gradle plugin imports a Maven repo and a Ceylon repo containing the same things? The Ceylon repo is not use at all I think, since nobody imports those modules. What's the rationale?

FroMage commented 7 years ago

What's a puzzle to me is that the gradle build fails even during compilation, when the exact same command-line compilation works. The command-line run call will fail, though, so at least that one's obvious.

FroMage commented 7 years ago

In general, I think the pre-resolving done by the Gradle plugin is a good idea, in the (hopefully few) cases where Ceylon can't resolve it, but there's an issue with overrides because you can only specify one overrides, and in this case there is a user overrides file, which ends up ignored because the Gradle plugin specifies its own.

I think you can solve this by merging the two.

FroMage commented 7 years ago

Mmm, does the Gradle plugin have a problem with incremental compilation?

atlantis stephane 16:51 ceylon-spring-boot $ touch gateway/source/gateway/*.ceylon
atlantis stephane 16:52 ceylon-spring-boot $ ./gradlew :gateway:compileCeylon
:gateway:resolveCeylonDependencies
:gateway:createDependenciesPoms UP-TO-DATE
:gateway:createMavenRepo UP-TO-DATE
:gateway:generateOverridesFile UP-TO-DATE
:gateway:createModuleDescriptors UP-TO-DATE
:gateway:importJars UP-TO-DATE
:gateway:compileCeylon UP-TO-DATE

BUILD SUCCESSFUL

Total time: 1.041 secs
FroMage commented 7 years ago

What's a puzzle to me is that the gradle build fails even during compilation, when the exact same command-line compilation works.

It has to do with the gateway/.ceylon/config setting fullyexportmavendependencies=yes which is only read by the ceylon tool if it's in the CWD. I was running the compilation from the toplevel so it did not read that config file. I suspect the Gradle plugin sets the CWD to the module so it read it and that triggers the bug I mentionned. Puzzle solved.

renatoathaydes commented 7 years ago

Mmm, does the Gradle plugin have a problem with incremental compilation?

It uses a hash of the file to know if it was changed. You need to actually change the file, not just its timestamp.

renatoathaydes commented 7 years ago

One thing I don't understand though is why the gradle plugin imports a Maven repo and a Ceylon repo containing the same things?

The Maven repo is necessary for Ceylon to not attempt to connect to a remote server for dependency resolution. Even the poms are modified in a way that Ceylon will not see anything that is not in the local repo.

The Ceylon repo is just the result of trying to import the Maven modules as Ceylon modules. So the user can try to run with the JBoss module system on.

Hope that makes sense.

FroMage commented 7 years ago

It uses a hash of the file to know if it was changed. You need to actually change the file, not just its timestamp.

Ah OK, fine, thanks.

FroMage commented 7 years ago

The Maven repo is necessary for Ceylon to not attempt to connect to a remote server for dependency resolution. Even the poms are modified in a way that Ceylon will not see anything that is not in the local repo.

Yes, that makes total sense, I wasn't questioning that one.

The Ceylon repo is just the result of trying to import the Maven modules as Ceylon modules. So the user can try to run with the JBoss module system on.

Oh OK, fine, that's a good idea. Thanks.

renatoathaydes commented 7 years ago

If you don't want the ceylon repo (because you want to use only a flat classpath), use the importJars = false flag.

renatoathaydes commented 7 years ago

@FroMage is there anything I need to do to allow users to continue using the Gradle plugin as before?

FroMage commented 7 years ago

Well, there's several issues:

FroMage commented 7 years ago

As for the difference between Gradle and Ceylon resolving, the funny thing is that we do our resolving with Aether, so it should be fairly close to what Maven does. And we've seen in the past that for Maven modules not produced by Gradle (the vast majority unfortunately), there are things in the descriptors that Gradle just does not support and so for those cases, sometimes, Ceylon resolving is better, strictly because it adheres more to how the Maven artifacts were defined and meant to work.

For other cases, Gradle can be better. Surely it is if the imported module has been defined in Gradle itself. And also if you want to define your overrides in Gradle itself then that's more powerful than what we can do in Ceylon overrides, no doubt.

So it seems to me that it's great that there's two alternative resolving strategies with different strengths :)

renatoathaydes commented 7 years ago

If the user has his own overrides.xml file specified, your generated one takes over and so his overrides are lost. That's not right, you should find a way to support that by merging yours and his.

When using the Gradle plugin, you never need to use overrides. You can specify dependency overrides the Gradle way, in the Gradle dependencies section.

FroMage commented 7 years ago

Well, yes and no: AFAICT you only generate overrides for the first-level dependencies, so any deepest overrides will be ignored by Ceylon, no?

FroMage commented 7 years ago

Oh, unless those overrides end up in the generated pom.xml of the generated maven-repo?

FroMage commented 7 years ago

So I have fixed the issue in ceylon and I can compile, but not run yet, because the custom overrides are ignored. I need to remove logback. How can I do that in Gradle, so I can test?

I found https://discuss.gradle.org/t/how-to-exclude-transitive-dependency/2119/2 explaning this, but the build.gradle doesn't have any dependency that I can hook on to.

renatoathaydes commented 7 years ago

@FroMage I believe you're right that we generate overrides only for first-level dependencies, but that's not a problem because you can add any dependency at the top-level in the Gradle file, and that will override any transitive dependency (as you specified it yourself). I say "I believe" because I haven't verified that... will try some time.

EDIT: To make this clearer: All direct dependencies MUST be declared in the ceylon module file. The same dependency may be also declared in the Gradle file for purposes of overriding some transitive dependency. That's how the spring-boot sample removes the logback dependency (see next comment).

renatoathaydes commented 7 years ago

I need to remove logback. How can I do that in Gradle, so I can test?

@FroMage I do this on my Spring Boot sample:

dependencies {
    ceylonCompile "org.springframework.boot:spring-boot-starter-web:1.3.0.RELEASE", {
        exclude group: "ch.qos.logback"
    }
}
FroMage commented 7 years ago

Thanks, but it doesn't work for me:

plugins {
    id 'com.athaydes.ceylon' version '1.3.0' apply true
}

subprojects { subprj ->
    subprj.apply plugin: 'com.athaydes.ceylon'

    repositories {
        mavenCentral()
    }

    ceylon {
        module = subprj.name
        flatClasspath = true
        importJars = true
        forceImports = true
    }

dependencies {
    ceylonCompile "org.springframework.boot:spring-boot-starter-logging:1.4.1.RELEASE", {
        exclude group: "ch.qos.logback"
    }
}
}
./gradlew :gateway:dependencies:
:gateway:resolveCeylonDependencies
:gateway:dependencies

------------------------------------------------------------
Project :gateway
------------------------------------------------------------

ceylonCompile
+--- org.springframework.boot:spring-boot-starter-logging:1.4.1.RELEASE
|    +--- org.slf4j:jcl-over-slf4j:1.7.21
|    |    \--- org.slf4j:slf4j-api:1.7.21
|    +--- org.slf4j:jul-to-slf4j:1.7.21
|    |    \--- org.slf4j:slf4j-api:1.7.21
|    +--- org.slf4j:log4j-over-slf4j:1.7.21
|    |    \--- org.slf4j:slf4j-api:1.7.21
|    \--- ch.qos.logback:logback-classic:1.1.7
|         +--- ch.qos.logback:logback-core:1.1.7
|         \--- org.slf4j:slf4j-api:1.7.20 -> 1.7.21
+--- org.springframework.cloud:spring-cloud-starter-zuul:1.2.2.RELEASE
|    +--- org.springframework.cloud:spring-cloud-starter:1.1.5.RELEASE
|    |    +--- org.springframework.boot:spring-boot-starter:1.4.1.RELEASE
|    |    |    +--- org.springframework.boot:spring-boot:1.4.1.RELEASE
|    |    |    |    +--- org.springframework:spring-core:4.3.3.RELEASE
|    |    |    |    |    \--- commons-logging:commons-logging:1.2
|    |    |    |    \--- org.springframework:spring-context:4.3.3.RELEASE
|    |    |    |         +--- org.springframework:spring-aop:4.3.3.RELEASE
|    |    |    |         |    +--- org.springframework:spring-beans:4.3.3.RELEASE
|    |    |    |         |    |    \--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    |    |         |    \--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    |    |         +--- org.springframework:spring-beans:4.3.3.RELEASE (*)
|    |    |    |         +--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    |    |         \--- org.springframework:spring-expression:4.3.3.RELEASE
|    |    |    |              \--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    |    +--- org.springframework.boot:spring-boot-autoconfigure:1.4.1.RELEASE
|    |    |    |    \--- org.springframework.boot:spring-boot:1.4.1.RELEASE (*)
|    |    |    +--- org.springframework.boot:spring-boot-starter-logging:1.4.1.RELEASE (*)
|    |    |    +--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    |    \--- org.yaml:snakeyaml:1.17
|    |    +--- org.springframework.cloud:spring-cloud-context:1.1.5.RELEASE
|    |    |    \--- org.springframework.security:spring-security-crypto:4.1.3.RELEASE
|    |    +--- org.springframework.cloud:spring-cloud-commons:1.1.5.RELEASE
|    |    |    \--- org.springframework.security:spring-security-crypto:4.1.3.RELEASE
|    |    \--- org.springframework.security:spring-security-rsa:1.0.3.RELEASE
|    |         \--- org.bouncycastle:bcpkix-jdk15on:1.55
|    |              \--- org.bouncycastle:bcprov-jdk15on:1.55
|    +--- org.springframework.boot:spring-boot-starter-web:1.4.1.RELEASE
|    |    +--- org.springframework.boot:spring-boot-starter:1.4.1.RELEASE (*)
|    |    +--- org.springframework.boot:spring-boot-starter-tomcat:1.4.1.RELEASE
|    |    |    +--- org.apache.tomcat.embed:tomcat-embed-core:8.5.5
|    |    |    +--- org.apache.tomcat.embed:tomcat-embed-el:8.5.5
|    |    |    \--- org.apache.tomcat.embed:tomcat-embed-websocket:8.5.5
|    |    |         \--- org.apache.tomcat.embed:tomcat-embed-core:8.5.5
|    |    +--- org.hibernate:hibernate-validator:5.2.4.Final
|    |    |    +--- javax.validation:validation-api:1.1.0.Final
|    |    |    +--- org.jboss.logging:jboss-logging:3.2.1.Final
|    |    |    \--- com.fasterxml:classmate:1.1.0
|    |    +--- com.fasterxml.jackson.core:jackson-databind:2.8.3
|    |    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.8.0 -> 2.8.3
|    |    |    \--- com.fasterxml.jackson.core:jackson-core:2.8.3
|    |    +--- org.springframework:spring-web:4.3.3.RELEASE
|    |    |    +--- org.springframework:spring-aop:4.3.3.RELEASE (*)
|    |    |    +--- org.springframework:spring-beans:4.3.3.RELEASE (*)
|    |    |    +--- org.springframework:spring-context:4.3.3.RELEASE (*)
|    |    |    \--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    \--- org.springframework:spring-webmvc:4.3.3.RELEASE
|    |         +--- org.springframework:spring-aop:4.3.3.RELEASE (*)
|    |         +--- org.springframework:spring-beans:4.3.3.RELEASE (*)
|    |         +--- org.springframework:spring-context:4.3.3.RELEASE (*)
|    |         +--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |         +--- org.springframework:spring-expression:4.3.3.RELEASE (*)
|    |         \--- org.springframework:spring-web:4.3.3.RELEASE (*)
|    +--- org.springframework.boot:spring-boot-starter-actuator:1.4.1.RELEASE
|    |    +--- org.springframework.boot:spring-boot-starter:1.4.1.RELEASE (*)
|    |    \--- org.springframework.boot:spring-boot-actuator:1.4.1.RELEASE
|    |         +--- org.springframework.boot:spring-boot:1.4.1.RELEASE (*)
|    |         +--- org.springframework.boot:spring-boot-autoconfigure:1.4.1.RELEASE (*)
|    |         +--- com.fasterxml.jackson.core:jackson-databind:2.8.3 (*)
|    |         +--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |         \--- org.springframework:spring-context:4.3.3.RELEASE (*)
|    +--- org.springframework.cloud:spring-cloud-starter-hystrix:1.2.2.RELEASE
|    |    +--- org.springframework.cloud:spring-cloud-starter:1.1.5.RELEASE (*)
|    |    +--- org.springframework.cloud:spring-cloud-netflix-core:1.2.2.RELEASE
|    |    |    +--- org.springframework.boot:spring-boot:1.4.1.RELEASE (*)
|    |    |    \--- org.springframework.boot:spring-boot-autoconfigure:1.4.1.RELEASE (*)
|    |    +--- org.springframework.cloud:spring-cloud-starter-archaius:1.2.2.RELEASE
|    |    |    +--- org.springframework.cloud:spring-cloud-starter:1.1.5.RELEASE (*)
|    |    |    +--- org.springframework.cloud:spring-cloud-netflix-core:1.2.2.RELEASE (*)
|    |    |    +--- com.netflix.archaius:archaius-core:0.7.4
|    |    |    |    +--- com.google.code.findbugs:jsr305:3.0.1
|    |    |    |    +--- commons-configuration:commons-configuration:1.8
|    |    |    |    |    +--- commons-lang:commons-lang:2.6
|    |    |    |    |    \--- commons-logging:commons-logging:1.1.1 -> 1.2
|    |    |    |    +--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
|    |    |    |    +--- com.google.guava:guava:16.0 -> 18.0
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.4.3 -> 2.8.3
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.4.3 -> 2.8.3
|    |    |    |    \--- com.fasterxml.jackson.core:jackson-databind:2.4.3 -> 2.8.3 (*)
|    |    |    +--- commons-configuration:commons-configuration:1.8 (*)
|    |    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.8.3
|    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.8.3
|    |    |    +--- com.fasterxml.jackson.core:jackson-databind:2.8.3 (*)
|    |    |    \--- com.google.guava:guava:18.0
|    |    +--- com.netflix.hystrix:hystrix-core:1.5.6
|    |    |    +--- org.slf4j:slf4j-api:1.7.0 -> 1.7.21
|    |    |    +--- com.netflix.archaius:archaius-core:0.4.1 -> 0.7.4 (*)
|    |    |    +--- io.reactivex:rxjava:1.2.0
|    |    |    \--- org.hdrhistogram:HdrHistogram:2.1.9
|    |    +--- com.netflix.hystrix:hystrix-metrics-event-stream:1.5.6
|    |    |    +--- com.netflix.hystrix:hystrix-serialization:1.5.6
|    |    |    |    +--- com.fasterxml.jackson.module:jackson-module-afterburner:2.7.5
|    |    |    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.7.5 -> 2.8.3
|    |    |    |    |    \--- com.fasterxml.jackson.core:jackson-databind:2.7.5 -> 2.8.3 (*)
|    |    |    |    +--- com.netflix.hystrix:hystrix-core:1.5.6 (*)
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.7.5 -> 2.8.3
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-databind:2.7.5 -> 2.8.3 (*)
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.7.5 -> 2.8.3
|    |    |    |    \--- com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.7.5
|    |    |    |         \--- com.fasterxml.jackson.core:jackson-core:2.7.5 -> 2.8.3
|    |    |    \--- com.netflix.hystrix:hystrix-core:1.5.6 (*)
|    |    \--- com.netflix.hystrix:hystrix-javanica:1.5.6
|    |         +--- commons-collections:commons-collections:3.2.2
|    |         +--- org.apache.commons:commons-lang3:3.1
|    |         +--- org.ow2.asm:asm:5.0.4
|    |         +--- com.netflix.hystrix:hystrix-core:1.5.6 (*)
|    |         +--- org.aspectj:aspectjweaver:1.8.6 -> 1.8.9
|    |         \--- com.google.guava:guava:15.0 -> 18.0
|    +--- org.springframework.cloud:spring-cloud-starter-ribbon:1.2.2.RELEASE
|    |    +--- org.springframework.boot:spring-boot-starter-aop:1.4.1.RELEASE
|    |    |    +--- org.springframework.boot:spring-boot-starter:1.4.1.RELEASE (*)
|    |    |    +--- org.springframework:spring-aop:4.3.3.RELEASE (*)
|    |    |    \--- org.aspectj:aspectjweaver:1.8.9
|    |    +--- org.springframework.retry:spring-retry:1.1.4.RELEASE
|    |    |    \--- org.springframework:spring-core:4.0.4.RELEASE -> 4.3.3.RELEASE (*)
|    |    +--- org.springframework.cloud:spring-cloud-starter:1.1.5.RELEASE (*)
|    |    +--- org.springframework.cloud:spring-cloud-netflix-core:1.2.2.RELEASE (*)
|    |    +--- org.springframework.cloud:spring-cloud-starter-archaius:1.2.2.RELEASE (*)
|    |    +--- com.netflix.ribbon:ribbon:2.2.0
|    |    |    +--- com.netflix.ribbon:ribbon-core:2.2.0
|    |    |    |    +--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
|    |    |    |    +--- com.google.code.findbugs:annotations:2.0.0
|    |    |    |    +--- com.google.guava:guava:16.0 -> 18.0
|    |    |    |    +--- commons-configuration:commons-configuration:1.8 (*)
|    |    |    |    +--- commons-lang:commons-lang:2.6
|    |    |    |    \--- com.netflix.archaius:archaius-core:0.7.4 (*)
|    |    |    +--- com.netflix.ribbon:ribbon-transport:2.2.0
|    |    |    |    +--- com.netflix.ribbon:ribbon-core:2.2.0 (*)
|    |    |    |    +--- com.netflix.ribbon:ribbon-loadbalancer:2.2.0
|    |    |    |    |    +--- com.netflix.ribbon:ribbon-core:2.2.0 (*)
|    |    |    |    |    +--- com.netflix.netflix-commons:netflix-statistics:0.1.1
|    |    |    |    |    |    +--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
|    |    |    |    |    |    \--- com.google.code.findbugs:annotations:2.0.0
|    |    |    |    |    +--- io.reactivex:rxjava:1.0.9 -> 1.2.0
|    |    |    |    |    +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
|    |    |    |    |    +--- com.netflix.servo:servo-core:0.10.1
|    |    |    |    |    |    +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
|    |    |    |    |    |    +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    |    |    |    +--- com.google.code.findbugs:annotations:2.0.0
|    |    |    |    |    |    \--- com.netflix.servo:servo-internal:0.10.1
|    |    |    |    |    |         +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
|    |    |    |    |    |         +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    |    |    |         \--- com.google.code.findbugs:annotations:2.0.0
|    |    |    |    |    +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    |    |    +--- com.netflix.archaius:archaius-core:0.7.4 (*)
|    |    |    |    |    \--- com.netflix.netflix-commons:netflix-commons-util:0.1.1
|    |    |    |    |         \--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
|    |    |    |    +--- io.reactivex:rxjava:1.0.10 -> 1.2.0
|    |    |    |    +--- io.reactivex:rxnetty:0.4.9
|    |    |    |    |    +--- io.reactivex:rxjava:1.0.10 -> 1.2.0
|    |    |    |    |    +--- io.netty:netty-codec-http:4.0.27.Final
|    |    |    |    |    |    +--- io.netty:netty-codec:4.0.27.Final
|    |    |    |    |    |    |    \--- io.netty:netty-transport:4.0.27.Final
|    |    |    |    |    |    |         \--- io.netty:netty-buffer:4.0.27.Final
|    |    |    |    |    |    |              \--- io.netty:netty-common:4.0.27.Final
|    |    |    |    |    |    \--- io.netty:netty-handler:4.0.27.Final
|    |    |    |    |    |         +--- io.netty:netty-buffer:4.0.27.Final (*)
|    |    |    |    |    |         +--- io.netty:netty-transport:4.0.27.Final (*)
|    |    |    |    |    |         \--- io.netty:netty-codec:4.0.27.Final (*)
|    |    |    |    |    +--- io.netty:netty-transport-native-epoll:4.0.27.Final
|    |    |    |    |    |    +--- io.netty:netty-common:4.0.27.Final
|    |    |    |    |    |    +--- io.netty:netty-buffer:4.0.27.Final (*)
|    |    |    |    |    |    \--- io.netty:netty-transport:4.0.27.Final (*)
|    |    |    |    |    \--- org.slf4j:slf4j-api:1.7.6 -> 1.7.21
|    |    |    |    +--- io.reactivex:rxnetty-contexts:0.4.9
|    |    |    |    |    +--- io.reactivex:rxjava:1.0.10 -> 1.2.0
|    |    |    |    |    \--- io.reactivex:rxnetty:0.4.9 (*)
|    |    |    |    +--- io.reactivex:rxnetty-servo:0.4.9
|    |    |    |    |    +--- io.reactivex:rxjava:1.0.10 -> 1.2.0
|    |    |    |    |    +--- io.reactivex:rxnetty:0.4.9 (*)
|    |    |    |    |    \--- com.netflix.servo:servo-core:0.7.5 -> 0.10.1 (*)
|    |    |    |    +--- javax.inject:javax.inject:1
|    |    |    |    +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
|    |    |    |    +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    |    \--- com.netflix.archaius:archaius-core:0.7.4 (*)
|    |    |    +--- com.netflix.hystrix:hystrix-core:1.4.3 -> 1.5.6 (*)
|    |    |    +--- javax.inject:javax.inject:1
|    |    |    +--- io.reactivex:rxjava:1.0.10 -> 1.2.0
|    |    |    +--- io.reactivex:rxnetty:0.4.9 (*)
|    |    |    +--- commons-configuration:commons-configuration:1.8 (*)
|    |    |    +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    \--- com.netflix.archaius:archaius-core:0.7.4 (*)
|    |    +--- com.netflix.ribbon:ribbon-core:2.2.0 (*)
|    |    +--- com.netflix.ribbon:ribbon-httpclient:2.2.0
|    |    |    +--- com.netflix.ribbon:ribbon-core:2.2.0 (*)
|    |    |    +--- com.netflix.ribbon:ribbon-loadbalancer:2.2.0 (*)
|    |    |    +--- commons-collections:commons-collections:3.2.1 -> 3.2.2
|    |    |    +--- org.apache.httpcomponents:httpclient:4.2.1 -> 4.3.4
|    |    |    |    +--- org.apache.httpcomponents:httpcore:4.3.2
|    |    |    |    +--- commons-logging:commons-logging:1.1.3 -> 1.2
|    |    |    |    \--- commons-codec:commons-codec:1.6
|    |    |    +--- com.sun.jersey:jersey-client:1.19.1
|    |    |    |    \--- com.sun.jersey:jersey-core:1.19.1
|    |    |    |         \--- javax.ws.rs:jsr311-api:1.1.1
|    |    |    +--- com.sun.jersey.contribs:jersey-apache-client4:1.19.1
|    |    |    |    +--- org.apache.httpcomponents:httpclient:4.1.1 -> 4.3.4 (*)
|    |    |    |    \--- com.sun.jersey:jersey-client:1.19.1 (*)
|    |    |    +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
|    |    |    +--- com.netflix.servo:servo-core:0.10.1 (*)
|    |    |    +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    +--- com.netflix.archaius:archaius-core:0.7.4 (*)
|    |    |    \--- com.netflix.netflix-commons:netflix-commons-util:0.1.1 (*)
|    |    +--- com.netflix.ribbon:ribbon-loadbalancer:2.2.0 (*)
|    |    \--- io.reactivex:rxjava:1.1.10 -> 1.2.0
|    +--- org.springframework.cloud:spring-cloud-starter-archaius:1.2.2.RELEASE (*)
|    \--- com.netflix.zuul:zuul-core:1.3.0
|         +--- commons-io:commons-io:2.4
|         +--- org.slf4j:slf4j-api:1.7.6 -> 1.7.21
|         +--- com.netflix.archaius:archaius-core:0.6.0 -> 0.7.4 (*)
|         +--- com.netflix.servo:servo-core:0.7.2 -> 0.10.1 (*)
|         \--- com.netflix.netflix-commons:netflix-commons-util:0.1.1 (*)
\--- org.springframework.cloud:spring-cloud-starter-eureka:1.2.2.RELEASE
     +--- org.springframework.boot:spring-boot-starter-web:1.4.1.RELEASE (*)
     +--- org.springframework.cloud:spring-cloud-starter:1.1.5.RELEASE (*)
     +--- org.springframework.cloud:spring-cloud-netflix-core:1.2.2.RELEASE (*)
     +--- org.springframework.cloud:spring-cloud-netflix-eureka-client:1.2.2.RELEASE
     |    \--- org.springframework.cloud:spring-cloud-netflix-core:1.2.2.RELEASE (*)
     +--- com.netflix.eureka:eureka-client:1.4.11
     |    +--- org.codehaus.jettison:jettison:1.3.7
     |    |    \--- stax:stax-api:1.0.1
     |    +--- com.netflix.netflix-commons:netflix-eventbus:0.3.0
     |    |    +--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
     |    |    +--- com.netflix.netflix-commons:netflix-infix:0.3.0
     |    |    |    +--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
     |    |    |    +--- commons-jxpath:commons-jxpath:1.3
     |    |    |    +--- joda-time:joda-time:2.3
     |    |    |    +--- org.antlr:antlr-runtime:3.4
     |    |    |    |    +--- org.antlr:stringtemplate:3.2.1
     |    |    |    |    |    \--- antlr:antlr:2.7.7
     |    |    |    |    \--- antlr:antlr:2.7.7
     |    |    |    +--- com.google.code.findbugs:jsr305:3.0.1
     |    |    |    +--- com.google.guava:guava:14.0.1 -> 18.0
     |    |    |    \--- com.google.code.gson:gson:2.1
     |    |    +--- com.netflix.servo:servo-core:0.5.3 -> 0.10.1 (*)
     |    |    +--- com.netflix.archaius:archaius-core:0.3.3 -> 0.7.4 (*)
     |    |    \--- org.apache.commons:commons-math:2.2
     |    +--- com.thoughtworks.xstream:xstream:1.4.2 -> 1.4.9
     |    |    +--- xmlpull:xmlpull:1.1.3.1
     |    |    \--- xpp3:xpp3_min:1.1.4c
     |    +--- com.netflix.archaius:archaius-core:0.7.3 -> 0.7.4 (*)
     |    +--- javax.ws.rs:jsr311-api:1.1.1
     |    +--- com.netflix.servo:servo-core:0.10.1 (*)
     |    +--- com.sun.jersey:jersey-core:1.19 -> 1.19.1 (*)
     |    +--- com.sun.jersey:jersey-client:1.19 -> 1.19.1 (*)
     |    +--- com.sun.jersey.contribs:jersey-apache-client4:1.19 -> 1.19.1 (*)
     |    +--- org.apache.httpcomponents:httpclient:4.3.4 (*)
     |    +--- com.google.inject:guice:4.0
     |    |    +--- javax.inject:javax.inject:1
     |    |    +--- aopalliance:aopalliance:1.0
     |    |    \--- com.google.guava:guava:16.0.1 -> 18.0
     |    +--- com.netflix.governator:governator-api:1.12.10
     |    |    \--- javax.inject:javax.inject:1
     |    +--- com.fasterxml.jackson.core:jackson-annotations:2.5.4 -> 2.8.3
     |    +--- com.fasterxml.jackson.core:jackson-core:2.5.4 -> 2.8.3
     |    \--- com.fasterxml.jackson.core:jackson-databind:2.5.4 -> 2.8.3 (*)
     +--- com.netflix.eureka:eureka-core:1.4.11
     |    +--- com.netflix.eureka:eureka-client:1.4.11 (*)
     |    +--- com.netflix.governator:governator:1.12.10
     |    |    +--- com.netflix.governator:governator-api:1.12.10 (*)
     |    |    +--- com.netflix.governator:governator-core:1.12.10
     |    |    |    +--- com.netflix.governator:governator-api:1.12.10 (*)
     |    |    |    +--- javax.inject:javax.inject:1
     |    |    |    +--- org.slf4j:slf4j-api:1.6.3 -> 1.7.21
     |    |    |    +--- com.google.inject:guice:4.0 (*)
     |    |    |    +--- com.google.inject.extensions:guice-multibindings:4.0
     |    |    |    |    \--- com.google.inject:guice:4.0 (*)
     |    |    |    \--- com.google.inject.extensions:guice-grapher:4.0
     |    |    |         +--- com.google.inject.extensions:guice-assistedinject:4.0
     |    |    |         |    \--- com.google.inject:guice:4.0 (*)
     |    |    |         +--- com.google.inject.extensions:guice-multibindings:4.0 (*)
     |    |    |         \--- com.google.inject:guice:4.0 (*)
     |    |    +--- org.hibernate:hibernate-validator:4.1.0.Final -> 5.2.4.Final (*)
     |    |    +--- org.ow2.asm:asm:5.0.4
     |    |    \--- com.fasterxml.jackson.core:jackson-databind:2.4.3 -> 2.8.3 (*)
     |    +--- com.thoughtworks.xstream:xstream:1.4.2 -> 1.4.9 (*)
     |    +--- javax.ws.rs:jsr311-api:1.1.1
     |    \--- org.codehaus.woodstox:woodstox-core-asl:4.4.1
     |         +--- javax.xml.stream:stax-api:1.0-2
     |         \--- org.codehaus.woodstox:stax2-api:3.1.4
     +--- org.springframework.cloud:spring-cloud-starter-archaius:1.2.2.RELEASE (*)
     +--- org.springframework.cloud:spring-cloud-starter-ribbon:1.2.2.RELEASE (*)
     +--- com.netflix.ribbon:ribbon-eureka:2.2.0
     |    +--- com.netflix.ribbon:ribbon-core:2.2.0 (*)
     |    +--- com.netflix.ribbon:ribbon-loadbalancer:2.2.0 (*)
     |    +--- com.netflix.eureka:eureka-client:1.4.6 -> 1.4.11 (*)
     |    +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
     |    \--- com.netflix.archaius:archaius-core:0.7.4 (*)
     \--- com.thoughtworks.xstream:xstream:1.4.9 (*)

ceylonRuntime
+--- org.springframework.boot:spring-boot-starter-logging:1.4.1.RELEASE
|    +--- org.slf4j:jcl-over-slf4j:1.7.21
|    |    \--- org.slf4j:slf4j-api:1.7.21
|    +--- org.slf4j:jul-to-slf4j:1.7.21
|    |    \--- org.slf4j:slf4j-api:1.7.21
|    +--- org.slf4j:log4j-over-slf4j:1.7.21
|    |    \--- org.slf4j:slf4j-api:1.7.21
|    \--- ch.qos.logback:logback-classic:1.1.7
|         +--- ch.qos.logback:logback-core:1.1.7
|         \--- org.slf4j:slf4j-api:1.7.20 -> 1.7.21
+--- org.springframework.cloud:spring-cloud-starter-zuul:1.2.2.RELEASE
|    +--- org.springframework.cloud:spring-cloud-starter:1.1.5.RELEASE
|    |    +--- org.springframework.boot:spring-boot-starter:1.4.1.RELEASE
|    |    |    +--- org.springframework.boot:spring-boot:1.4.1.RELEASE
|    |    |    |    +--- org.springframework:spring-core:4.3.3.RELEASE
|    |    |    |    |    \--- commons-logging:commons-logging:1.2
|    |    |    |    \--- org.springframework:spring-context:4.3.3.RELEASE
|    |    |    |         +--- org.springframework:spring-aop:4.3.3.RELEASE
|    |    |    |         |    +--- org.springframework:spring-beans:4.3.3.RELEASE
|    |    |    |         |    |    \--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    |    |         |    \--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    |    |         +--- org.springframework:spring-beans:4.3.3.RELEASE (*)
|    |    |    |         +--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    |    |         \--- org.springframework:spring-expression:4.3.3.RELEASE
|    |    |    |              \--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    |    +--- org.springframework.boot:spring-boot-autoconfigure:1.4.1.RELEASE
|    |    |    |    \--- org.springframework.boot:spring-boot:1.4.1.RELEASE (*)
|    |    |    +--- org.springframework.boot:spring-boot-starter-logging:1.4.1.RELEASE (*)
|    |    |    +--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    |    \--- org.yaml:snakeyaml:1.17
|    |    +--- org.springframework.cloud:spring-cloud-context:1.1.5.RELEASE
|    |    |    \--- org.springframework.security:spring-security-crypto:4.1.3.RELEASE
|    |    +--- org.springframework.cloud:spring-cloud-commons:1.1.5.RELEASE
|    |    |    \--- org.springframework.security:spring-security-crypto:4.1.3.RELEASE
|    |    \--- org.springframework.security:spring-security-rsa:1.0.3.RELEASE
|    |         \--- org.bouncycastle:bcpkix-jdk15on:1.55
|    |              \--- org.bouncycastle:bcprov-jdk15on:1.55
|    +--- org.springframework.boot:spring-boot-starter-web:1.4.1.RELEASE
|    |    +--- org.springframework.boot:spring-boot-starter:1.4.1.RELEASE (*)
|    |    +--- org.springframework.boot:spring-boot-starter-tomcat:1.4.1.RELEASE
|    |    |    +--- org.apache.tomcat.embed:tomcat-embed-core:8.5.5
|    |    |    +--- org.apache.tomcat.embed:tomcat-embed-el:8.5.5
|    |    |    \--- org.apache.tomcat.embed:tomcat-embed-websocket:8.5.5
|    |    |         \--- org.apache.tomcat.embed:tomcat-embed-core:8.5.5
|    |    +--- org.hibernate:hibernate-validator:5.2.4.Final
|    |    |    +--- javax.validation:validation-api:1.1.0.Final
|    |    |    +--- org.jboss.logging:jboss-logging:3.2.1.Final
|    |    |    \--- com.fasterxml:classmate:1.1.0
|    |    +--- com.fasterxml.jackson.core:jackson-databind:2.8.3
|    |    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.8.0 -> 2.8.3
|    |    |    \--- com.fasterxml.jackson.core:jackson-core:2.8.3
|    |    +--- org.springframework:spring-web:4.3.3.RELEASE
|    |    |    +--- org.springframework:spring-aop:4.3.3.RELEASE (*)
|    |    |    +--- org.springframework:spring-beans:4.3.3.RELEASE (*)
|    |    |    +--- org.springframework:spring-context:4.3.3.RELEASE (*)
|    |    |    \--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |    \--- org.springframework:spring-webmvc:4.3.3.RELEASE
|    |         +--- org.springframework:spring-aop:4.3.3.RELEASE (*)
|    |         +--- org.springframework:spring-beans:4.3.3.RELEASE (*)
|    |         +--- org.springframework:spring-context:4.3.3.RELEASE (*)
|    |         +--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |         +--- org.springframework:spring-expression:4.3.3.RELEASE (*)
|    |         \--- org.springframework:spring-web:4.3.3.RELEASE (*)
|    +--- org.springframework.boot:spring-boot-starter-actuator:1.4.1.RELEASE
|    |    +--- org.springframework.boot:spring-boot-starter:1.4.1.RELEASE (*)
|    |    \--- org.springframework.boot:spring-boot-actuator:1.4.1.RELEASE
|    |         +--- org.springframework.boot:spring-boot:1.4.1.RELEASE (*)
|    |         +--- org.springframework.boot:spring-boot-autoconfigure:1.4.1.RELEASE (*)
|    |         +--- com.fasterxml.jackson.core:jackson-databind:2.8.3 (*)
|    |         +--- org.springframework:spring-core:4.3.3.RELEASE (*)
|    |         \--- org.springframework:spring-context:4.3.3.RELEASE (*)
|    +--- org.springframework.cloud:spring-cloud-starter-hystrix:1.2.2.RELEASE
|    |    +--- org.springframework.cloud:spring-cloud-starter:1.1.5.RELEASE (*)
|    |    +--- org.springframework.cloud:spring-cloud-netflix-core:1.2.2.RELEASE
|    |    |    +--- org.springframework.boot:spring-boot:1.4.1.RELEASE (*)
|    |    |    \--- org.springframework.boot:spring-boot-autoconfigure:1.4.1.RELEASE (*)
|    |    +--- org.springframework.cloud:spring-cloud-starter-archaius:1.2.2.RELEASE
|    |    |    +--- org.springframework.cloud:spring-cloud-starter:1.1.5.RELEASE (*)
|    |    |    +--- org.springframework.cloud:spring-cloud-netflix-core:1.2.2.RELEASE (*)
|    |    |    +--- com.netflix.archaius:archaius-core:0.7.4
|    |    |    |    +--- com.google.code.findbugs:jsr305:3.0.1
|    |    |    |    +--- commons-configuration:commons-configuration:1.8
|    |    |    |    |    +--- commons-lang:commons-lang:2.6
|    |    |    |    |    \--- commons-logging:commons-logging:1.1.1 -> 1.2
|    |    |    |    +--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
|    |    |    |    +--- com.google.guava:guava:16.0 -> 18.0
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.4.3 -> 2.8.3
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.4.3 -> 2.8.3
|    |    |    |    \--- com.fasterxml.jackson.core:jackson-databind:2.4.3 -> 2.8.3 (*)
|    |    |    +--- commons-configuration:commons-configuration:1.8 (*)
|    |    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.8.3
|    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.8.3
|    |    |    +--- com.fasterxml.jackson.core:jackson-databind:2.8.3 (*)
|    |    |    \--- com.google.guava:guava:18.0
|    |    +--- com.netflix.hystrix:hystrix-core:1.5.6
|    |    |    +--- org.slf4j:slf4j-api:1.7.0 -> 1.7.21
|    |    |    +--- com.netflix.archaius:archaius-core:0.4.1 -> 0.7.4 (*)
|    |    |    +--- io.reactivex:rxjava:1.2.0
|    |    |    \--- org.hdrhistogram:HdrHistogram:2.1.9
|    |    +--- com.netflix.hystrix:hystrix-metrics-event-stream:1.5.6
|    |    |    +--- com.netflix.hystrix:hystrix-serialization:1.5.6
|    |    |    |    +--- com.fasterxml.jackson.module:jackson-module-afterburner:2.7.5
|    |    |    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.7.5 -> 2.8.3
|    |    |    |    |    \--- com.fasterxml.jackson.core:jackson-databind:2.7.5 -> 2.8.3 (*)
|    |    |    |    +--- com.netflix.hystrix:hystrix-core:1.5.6 (*)
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.7.5 -> 2.8.3
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-databind:2.7.5 -> 2.8.3 (*)
|    |    |    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.7.5 -> 2.8.3
|    |    |    |    \--- com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.7.5
|    |    |    |         \--- com.fasterxml.jackson.core:jackson-core:2.7.5 -> 2.8.3
|    |    |    \--- com.netflix.hystrix:hystrix-core:1.5.6 (*)
|    |    \--- com.netflix.hystrix:hystrix-javanica:1.5.6
|    |         +--- commons-collections:commons-collections:3.2.2
|    |         +--- org.apache.commons:commons-lang3:3.1
|    |         +--- org.ow2.asm:asm:5.0.4
|    |         +--- com.netflix.hystrix:hystrix-core:1.5.6 (*)
|    |         +--- org.aspectj:aspectjweaver:1.8.6 -> 1.8.9
|    |         \--- com.google.guava:guava:15.0 -> 18.0
|    +--- org.springframework.cloud:spring-cloud-starter-ribbon:1.2.2.RELEASE
|    |    +--- org.springframework.boot:spring-boot-starter-aop:1.4.1.RELEASE
|    |    |    +--- org.springframework.boot:spring-boot-starter:1.4.1.RELEASE (*)
|    |    |    +--- org.springframework:spring-aop:4.3.3.RELEASE (*)
|    |    |    \--- org.aspectj:aspectjweaver:1.8.9
|    |    +--- org.springframework.retry:spring-retry:1.1.4.RELEASE
|    |    |    \--- org.springframework:spring-core:4.0.4.RELEASE -> 4.3.3.RELEASE (*)
|    |    +--- org.springframework.cloud:spring-cloud-starter:1.1.5.RELEASE (*)
|    |    +--- org.springframework.cloud:spring-cloud-netflix-core:1.2.2.RELEASE (*)
|    |    +--- org.springframework.cloud:spring-cloud-starter-archaius:1.2.2.RELEASE (*)
|    |    +--- com.netflix.ribbon:ribbon:2.2.0
|    |    |    +--- com.netflix.ribbon:ribbon-core:2.2.0
|    |    |    |    +--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
|    |    |    |    +--- com.google.code.findbugs:annotations:2.0.0
|    |    |    |    +--- com.google.guava:guava:16.0 -> 18.0
|    |    |    |    +--- commons-configuration:commons-configuration:1.8 (*)
|    |    |    |    +--- commons-lang:commons-lang:2.6
|    |    |    |    \--- com.netflix.archaius:archaius-core:0.7.4 (*)
|    |    |    +--- com.netflix.ribbon:ribbon-transport:2.2.0
|    |    |    |    +--- com.netflix.ribbon:ribbon-core:2.2.0 (*)
|    |    |    |    +--- com.netflix.ribbon:ribbon-loadbalancer:2.2.0
|    |    |    |    |    +--- com.netflix.ribbon:ribbon-core:2.2.0 (*)
|    |    |    |    |    +--- com.netflix.netflix-commons:netflix-statistics:0.1.1
|    |    |    |    |    |    +--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
|    |    |    |    |    |    \--- com.google.code.findbugs:annotations:2.0.0
|    |    |    |    |    +--- io.reactivex:rxjava:1.0.9 -> 1.2.0
|    |    |    |    |    +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
|    |    |    |    |    +--- com.netflix.servo:servo-core:0.10.1
|    |    |    |    |    |    +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
|    |    |    |    |    |    +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    |    |    |    +--- com.google.code.findbugs:annotations:2.0.0
|    |    |    |    |    |    \--- com.netflix.servo:servo-internal:0.10.1
|    |    |    |    |    |         +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
|    |    |    |    |    |         +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    |    |    |         \--- com.google.code.findbugs:annotations:2.0.0
|    |    |    |    |    +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    |    |    +--- com.netflix.archaius:archaius-core:0.7.4 (*)
|    |    |    |    |    \--- com.netflix.netflix-commons:netflix-commons-util:0.1.1
|    |    |    |    |         \--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
|    |    |    |    +--- io.reactivex:rxjava:1.0.10 -> 1.2.0
|    |    |    |    +--- io.reactivex:rxnetty:0.4.9
|    |    |    |    |    +--- io.reactivex:rxjava:1.0.10 -> 1.2.0
|    |    |    |    |    +--- io.netty:netty-codec-http:4.0.27.Final
|    |    |    |    |    |    +--- io.netty:netty-codec:4.0.27.Final
|    |    |    |    |    |    |    \--- io.netty:netty-transport:4.0.27.Final
|    |    |    |    |    |    |         \--- io.netty:netty-buffer:4.0.27.Final
|    |    |    |    |    |    |              \--- io.netty:netty-common:4.0.27.Final
|    |    |    |    |    |    \--- io.netty:netty-handler:4.0.27.Final
|    |    |    |    |    |         +--- io.netty:netty-buffer:4.0.27.Final (*)
|    |    |    |    |    |         +--- io.netty:netty-transport:4.0.27.Final (*)
|    |    |    |    |    |         \--- io.netty:netty-codec:4.0.27.Final (*)
|    |    |    |    |    +--- io.netty:netty-transport-native-epoll:4.0.27.Final
|    |    |    |    |    |    +--- io.netty:netty-common:4.0.27.Final
|    |    |    |    |    |    +--- io.netty:netty-buffer:4.0.27.Final (*)
|    |    |    |    |    |    \--- io.netty:netty-transport:4.0.27.Final (*)
|    |    |    |    |    \--- org.slf4j:slf4j-api:1.7.6 -> 1.7.21
|    |    |    |    +--- io.reactivex:rxnetty-contexts:0.4.9
|    |    |    |    |    +--- io.reactivex:rxjava:1.0.10 -> 1.2.0
|    |    |    |    |    \--- io.reactivex:rxnetty:0.4.9 (*)
|    |    |    |    +--- io.reactivex:rxnetty-servo:0.4.9
|    |    |    |    |    +--- io.reactivex:rxjava:1.0.10 -> 1.2.0
|    |    |    |    |    +--- io.reactivex:rxnetty:0.4.9 (*)
|    |    |    |    |    \--- com.netflix.servo:servo-core:0.7.5 -> 0.10.1 (*)
|    |    |    |    +--- javax.inject:javax.inject:1
|    |    |    |    +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
|    |    |    |    +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    |    \--- com.netflix.archaius:archaius-core:0.7.4 (*)
|    |    |    +--- com.netflix.hystrix:hystrix-core:1.4.3 -> 1.5.6 (*)
|    |    |    +--- javax.inject:javax.inject:1
|    |    |    +--- io.reactivex:rxjava:1.0.10 -> 1.2.0
|    |    |    +--- io.reactivex:rxnetty:0.4.9 (*)
|    |    |    +--- commons-configuration:commons-configuration:1.8 (*)
|    |    |    +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    \--- com.netflix.archaius:archaius-core:0.7.4 (*)
|    |    +--- com.netflix.ribbon:ribbon-core:2.2.0 (*)
|    |    +--- com.netflix.ribbon:ribbon-httpclient:2.2.0
|    |    |    +--- com.netflix.ribbon:ribbon-core:2.2.0 (*)
|    |    |    +--- com.netflix.ribbon:ribbon-loadbalancer:2.2.0 (*)
|    |    |    +--- commons-collections:commons-collections:3.2.1 -> 3.2.2
|    |    |    +--- org.apache.httpcomponents:httpclient:4.2.1 -> 4.3.4
|    |    |    |    +--- org.apache.httpcomponents:httpcore:4.3.2
|    |    |    |    +--- commons-logging:commons-logging:1.1.3 -> 1.2
|    |    |    |    \--- commons-codec:commons-codec:1.6
|    |    |    +--- com.sun.jersey:jersey-client:1.19.1
|    |    |    |    \--- com.sun.jersey:jersey-core:1.19.1
|    |    |    |         \--- javax.ws.rs:jsr311-api:1.1.1
|    |    |    +--- com.sun.jersey.contribs:jersey-apache-client4:1.19.1
|    |    |    |    +--- org.apache.httpcomponents:httpclient:4.1.1 -> 4.3.4 (*)
|    |    |    |    \--- com.sun.jersey:jersey-client:1.19.1 (*)
|    |    |    +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
|    |    |    +--- com.netflix.servo:servo-core:0.10.1 (*)
|    |    |    +--- com.google.guava:guava:16.0.1 -> 18.0
|    |    |    +--- com.netflix.archaius:archaius-core:0.7.4 (*)
|    |    |    \--- com.netflix.netflix-commons:netflix-commons-util:0.1.1 (*)
|    |    +--- com.netflix.ribbon:ribbon-loadbalancer:2.2.0 (*)
|    |    \--- io.reactivex:rxjava:1.1.10 -> 1.2.0
|    +--- org.springframework.cloud:spring-cloud-starter-archaius:1.2.2.RELEASE (*)
|    \--- com.netflix.zuul:zuul-core:1.3.0
|         +--- commons-io:commons-io:2.4
|         +--- org.slf4j:slf4j-api:1.7.6 -> 1.7.21
|         +--- com.netflix.archaius:archaius-core:0.6.0 -> 0.7.4 (*)
|         +--- com.netflix.servo:servo-core:0.7.2 -> 0.10.1 (*)
|         \--- com.netflix.netflix-commons:netflix-commons-util:0.1.1 (*)
\--- org.springframework.cloud:spring-cloud-starter-eureka:1.2.2.RELEASE
     +--- org.springframework.boot:spring-boot-starter-web:1.4.1.RELEASE (*)
     +--- org.springframework.cloud:spring-cloud-starter:1.1.5.RELEASE (*)
     +--- org.springframework.cloud:spring-cloud-netflix-core:1.2.2.RELEASE (*)
     +--- org.springframework.cloud:spring-cloud-netflix-eureka-client:1.2.2.RELEASE
     |    \--- org.springframework.cloud:spring-cloud-netflix-core:1.2.2.RELEASE (*)
     +--- com.netflix.eureka:eureka-client:1.4.11
     |    +--- org.codehaus.jettison:jettison:1.3.7
     |    |    \--- stax:stax-api:1.0.1
     |    +--- com.netflix.netflix-commons:netflix-eventbus:0.3.0
     |    |    +--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
     |    |    +--- com.netflix.netflix-commons:netflix-infix:0.3.0
     |    |    |    +--- org.slf4j:slf4j-api:1.6.4 -> 1.7.21
     |    |    |    +--- commons-jxpath:commons-jxpath:1.3
     |    |    |    +--- joda-time:joda-time:2.3
     |    |    |    +--- org.antlr:antlr-runtime:3.4
     |    |    |    |    +--- org.antlr:stringtemplate:3.2.1
     |    |    |    |    |    \--- antlr:antlr:2.7.7
     |    |    |    |    \--- antlr:antlr:2.7.7
     |    |    |    +--- com.google.code.findbugs:jsr305:3.0.1
     |    |    |    +--- com.google.guava:guava:14.0.1 -> 18.0
     |    |    |    \--- com.google.code.gson:gson:2.1
     |    |    +--- com.netflix.servo:servo-core:0.5.3 -> 0.10.1 (*)
     |    |    +--- com.netflix.archaius:archaius-core:0.3.3 -> 0.7.4 (*)
     |    |    \--- org.apache.commons:commons-math:2.2
     |    +--- com.thoughtworks.xstream:xstream:1.4.2 -> 1.4.9
     |    |    +--- xmlpull:xmlpull:1.1.3.1
     |    |    \--- xpp3:xpp3_min:1.1.4c
     |    +--- com.netflix.archaius:archaius-core:0.7.3 -> 0.7.4 (*)
     |    +--- javax.ws.rs:jsr311-api:1.1.1
     |    +--- com.netflix.servo:servo-core:0.10.1 (*)
     |    +--- com.sun.jersey:jersey-core:1.19 -> 1.19.1 (*)
     |    +--- com.sun.jersey:jersey-client:1.19 -> 1.19.1 (*)
     |    +--- com.sun.jersey.contribs:jersey-apache-client4:1.19 -> 1.19.1 (*)
     |    +--- org.apache.httpcomponents:httpclient:4.3.4 (*)
     |    +--- com.google.inject:guice:4.0
     |    |    +--- javax.inject:javax.inject:1
     |    |    +--- aopalliance:aopalliance:1.0
     |    |    \--- com.google.guava:guava:16.0.1 -> 18.0
     |    +--- com.netflix.governator:governator-api:1.12.10
     |    |    \--- javax.inject:javax.inject:1
     |    +--- com.fasterxml.jackson.core:jackson-annotations:2.5.4 -> 2.8.3
     |    +--- com.fasterxml.jackson.core:jackson-core:2.5.4 -> 2.8.3
     |    \--- com.fasterxml.jackson.core:jackson-databind:2.5.4 -> 2.8.3 (*)
     +--- com.netflix.eureka:eureka-core:1.4.11
     |    +--- com.netflix.eureka:eureka-client:1.4.11 (*)
     |    +--- com.netflix.governator:governator:1.12.10
     |    |    +--- com.netflix.governator:governator-api:1.12.10 (*)
     |    |    +--- com.netflix.governator:governator-core:1.12.10
     |    |    |    +--- com.netflix.governator:governator-api:1.12.10 (*)
     |    |    |    +--- javax.inject:javax.inject:1
     |    |    |    +--- org.slf4j:slf4j-api:1.6.3 -> 1.7.21
     |    |    |    +--- com.google.inject:guice:4.0 (*)
     |    |    |    +--- com.google.inject.extensions:guice-multibindings:4.0
     |    |    |    |    \--- com.google.inject:guice:4.0 (*)
     |    |    |    \--- com.google.inject.extensions:guice-grapher:4.0
     |    |    |         +--- com.google.inject.extensions:guice-assistedinject:4.0
     |    |    |         |    \--- com.google.inject:guice:4.0 (*)
     |    |    |         +--- com.google.inject.extensions:guice-multibindings:4.0 (*)
     |    |    |         \--- com.google.inject:guice:4.0 (*)
     |    |    +--- org.hibernate:hibernate-validator:4.1.0.Final -> 5.2.4.Final (*)
     |    |    +--- org.ow2.asm:asm:5.0.4
     |    |    \--- com.fasterxml.jackson.core:jackson-databind:2.4.3 -> 2.8.3 (*)
     |    +--- com.thoughtworks.xstream:xstream:1.4.2 -> 1.4.9 (*)
     |    +--- javax.ws.rs:jsr311-api:1.1.1
     |    \--- org.codehaus.woodstox:woodstox-core-asl:4.4.1
     |         +--- javax.xml.stream:stax-api:1.0-2
     |         \--- org.codehaus.woodstox:stax2-api:3.1.4
     +--- org.springframework.cloud:spring-cloud-starter-archaius:1.2.2.RELEASE (*)
     +--- org.springframework.cloud:spring-cloud-starter-ribbon:1.2.2.RELEASE (*)
     +--- com.netflix.ribbon:ribbon-eureka:2.2.0
     |    +--- com.netflix.ribbon:ribbon-core:2.2.0 (*)
     |    +--- com.netflix.ribbon:ribbon-loadbalancer:2.2.0 (*)
     |    +--- com.netflix.eureka:eureka-client:1.4.6 -> 1.4.11 (*)
     |    +--- org.slf4j:slf4j-api:1.7.12 -> 1.7.21
     |    \--- com.netflix.archaius:archaius-core:0.7.4 (*)
     \--- com.thoughtworks.xstream:xstream:1.4.9 (*)

default
No dependencies

BUILD SUCCESSFUL

Total time: 1.076 secs
renatoathaydes commented 7 years ago

Why you changed the dependency to org.springframework.boot:spring-boot-starter-logging?

As I said before, you can only override direct dependencies of your Ceylon module, so if your Ceylon module depends directly on spring-boot-starter-logging, this should work. But most likely your Ceylon project would depend on spring-boot-starter-web, like I did on my sample, and then it works fine.

FroMage commented 7 years ago

Oh, it's not transitive OK. Well the sample in question did not depend on -web, it was a transitive dep. Then I'm not sure how to make it work.

FroMage commented 7 years ago

And the :dependencies: target showed that it was pulled in by the -logging one.

FroMage commented 7 years ago

Even after I add the spring-boot-starter-logging dep to the module.ceylon Gradle ignores my exclusion. I simply can't get this to work at all.

renatoathaydes commented 7 years ago

Sorry that I did not make this clearer... I hope I can explain better this time.

The only file where direct dependencies are declared in Ceylon (and that's the same with the Gradle plugin) is module.ceylon. The only time you would use the Gradle file dependencies section is if you want to override transitive dependencies of your direct dependencies.

So, for example, if you have this declaration in your module.ceylon file:

module.ceylon

import "org.springframework.boot:spring-boot-starter-web" "1.3.0.RELEASE";

Then, you can do this to remove logback:

build.gradle

dependencies {
    ceylonCompile "org.springframework.boot:spring-boot-starter-web:1.3.0.RELEASE", {
        exclude group: "ch.qos.logback"
    }
}

You see it? You declare a direct dependency in the Ceylon module file, then you declare the same dependency in the Gradle file so you can override a transitive dependency (in this case, remove logback).

This absolutely works and I have tests to confirm this. And if you can show me a case where it doesn't, please file a bug so I can reproduce it and fix it.

When you added the logging dependency both in the Ceylon file and in the Gradle file, you might have forgotten to also override it in the starter-web dependencies? In that case, I don't think the Gradle plugin will exclude it because it was not excluded in at least one direct dependency. This is the expected behaviour.

If you declare a dependency in the Gradle file that is not declared also in the Ceylon module file, it will not override anything, even if the dependency is a transitive dependency of some dependency declared in the Ceylon module file. The dependency will be added to the runtime because that's what you seem to want, but it will not be part of the overrides generated for the Ceylon compiler.

Hope it works for you now.

FroMage commented 7 years ago

I did exactly as you said, but with the -logging dep because the module does not directly import the -web dep, and :dependencies: showed that it was the -logging dep that pulled logback, and that's precisely what does not work. I'm pretty sure I'm doing exactly what you said I should do, no?

plugins {
    id 'com.athaydes.ceylon' version '1.3.0' apply true
}

subprojects { subprj ->
    subprj.apply plugin: 'com.athaydes.ceylon'

    repositories {
        mavenCentral()
    }

    ceylon {
        module = subprj.name
        flatClasspath = true
        importJars = true
        forceImports = true
    }

    dependencies {
        ceylonCompile("org.springframework.boot:spring-boot-starter-logging:1.4.1.RELEASE") {
            exclude group: "ch.qos.logback"
            exclude module: "logback-classic"
        }
    }
}
native("jvm")
module gateway "1.0.0" {
    import ceylon.interop.java "1.3.0";
    import maven:"org.springframework.cloud:spring-cloud-starter-zuul" "1.2.2.RELEASE";
    import maven:"org.springframework.cloud:spring-cloud-starter-eureka" "1.2.2.RELEASE";
    import maven:"org.springframework.boot:spring-boot-starter-logging" "1.4.1.RELEASE";
}
FroMage commented 7 years ago

As I showed above with :dependencies:, logback is not imported directly by -starter-web, but by -starter-logging which is an indirect dep of -starter-web. At least, that's what Gradle tells me.

renatoathaydes commented 7 years ago

This was a tricky one.

Gradle saw your dependency on spring-boot-starter-logging twice. It ignored your override because you did not override it in both places.

I know Gradle saw it twice because when run with gradlew --info dep, it said:

Not adding transitive dependencies of module [name:org.springframework.boot:spring-boot-starter-logging, namespace:maven, version:1.4.1.RELEASE] as it already existed in the project

Looking carefully at the dependency tree, I saw that spring-cloud-starter-eureka actually depends on -starter-web which depends on starter-logging, though Gradle does not show repeated transitive dependencies so it's hard to see that.

I fixed this by simply removing a direct dependency on the logging framework in the Ceylon module, and adding the override on the starter-zuul dependency.

Here's module.ceylon:

native("jvm")
module gateway "1.0.0" {
    import ceylon.interop.java "1.3.0";
    import maven:"org.springframework.cloud:spring-cloud-starter-zuul" "1.2.2.RELEASE";
    import maven:"org.springframework.cloud:spring-cloud-starter-eureka" "1.2.2.RELEASE";
}

EDIT: I had forgotten to add both starter-zuul AND starter-eureka to the Gradle file because BOTH of them import starter-web. What crazy dependency tree is this?

Gradle file:

    dependencies {
        ceylonCompile("org.springframework.cloud:spring-cloud-starter-eureka:1.2.2.RELEASE") {
            exclude group: "ch.qos.logback"
        }
        ceylonCompile("org.springframework.cloud:spring-cloud-starter-zuul:1.2.2.RELEASE") {
            exclude group: "ch.qos.logback"
        }
    }

This is not a bug because the dependency was duplicate... even if I say it's a bug because of the inconvenience it may cause users, I cannot fix this easily because you're trying to override the dependency of another unrelated node in the tree of deps... which could have unintended consequences... I will try to come up with a solution to this. Please file a bug if you think it's a bug.

renatoathaydes commented 7 years ago

How about this:

ceylon {
    excludedDependencies group: 'ch.qos.logback'
}

I could make this work quite easily...

aalmiray commented 7 years ago

That would exclude all dependencies of the same group. What if you want to exclude a single dependency in a given group? Also, please make sure you can specify multiple entries. Either excludedDependencies accepts a Map, and a List of Maps, or it accepts several invocations in which case each invocation accumulates.

renatoathaydes commented 7 years ago

Wow, just learned that you can do this already using Gradle only:

configurations {
    compile.exclude module: 'commons'
    all*.exclude group: 'org.gradle.test.excludes', module: 'reports'
}

I just tried:

configurations {
    all*.exclude group: "ch.qos.logback"
}

It works! So this feature is unnecessary, luckily :)

FroMage commented 7 years ago

I wish it were that easy:

* What went wrong:
A problem occurred evaluating root project 'ceylon-spring-boot'.
> Could not get unknown property 'all' for object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.GradleScriptException: A problem occurred evaluating root project 'ceylon-spring-boot'.