Managing Dependencies for Spring Projects with Gradle

Managing Dependencies for Spring Projects with Gradle

Managing dependencies is hard. For Spring projects, Gradle and Maven are just two of the tools we can use to help make dependency management easier. They both handle dependency management effectively, but in very different ways. For example, Maven uses BOMs, and, until recently, Gradle didn’t have an equivalent concept. Because of this and other differences, the Spring Dependency Management plugin was created so that Gradle users who already knew Maven could manage dependencies in a way that was familiar to them.

For earlier versions of Gradle, the plugin’s version enforcement and dependency exclusion features were revolutionary and led to the Spring Dependency Management Plugin’s popularity in the Spring ecosystem and spread to other JVM-based communities such as Android. Now that Gradle 5.X includes native BOM support, users can replace parts of the plugin and take advantage of the productivity gains of the native support.

In this session, we’ll go over some basic use cases for Gradle native BOM support and show you how to use it to manage the dependencies of a Spring Boot application. We’ll also look at some scenarios where you’ll still want to use the Spring Dependency Management Gradle plugin.

1f28a0c1988421be3268026bd6bb6f49?s=128

jlstrater

May 16, 2019
Tweet

Transcript

  1. Andy Wilkinson @ankinson Managing Dependencies for Spring Projects with Gradle

    Jenn Strater @codeJENNerator
  2. Outline • Introduction to the Spring Dependency Management Gradle Plugin

    • Gradle 5 and beyond • Migration Tips
  3. Outline • Introduction to the Spring Dependency Management Gradle Plugin

    • Gradle 5 and beyond • Migration Tips
  4. None
  5. spring-boot-dependencies • Maven bill of materials (bom) • Manages dependency

    versions (and Maven plugin versions) • Both Spring and third-party dependencies • Over 150 version properties • Over 800 dependencies
  6. <properties> … <spring-framework.version>5.1.6.RELEASE</spring-framework.version> … <thymeleaf.version>3.0.10.RELEASE</thymeleaf.version> … </properties> <dependencyManagement> <dependencies> …

    <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>${thymeleaf.version}</version> </dependency> … </dependencies> </dependencyManagement> spring-boot-dependencies
  7. • Removes the need to think about versions when declaring

    dependencies • Provides a consistent version across a library’s modules • Avoids accidentally mixing acme-core 1.2 with acme-server 1.1 • Provides default versions that are tested and known to work together • Just an opinion • Override to meet a project’s needs Why is a bom a good thing?
  8. None
  9. None
  10. Importing a bom plugins { id 'io.spring.dependency-management' version '1.0.7.RELEASE' }

    dependencyManagement { imports { mavenBom 'o.s.b:spring-boot-dependencies:2.1.4.RELEASE' } }
  11. $ ./gradlew dependencyManagement > Task :dependencyManagement ------------------------------------------------------------ Root project ------------------------------------------------------------

    global - Default dependency management for all configurations … org.thymeleaf:thymeleaf 3.0.11.RELEASE org.thymeleaf:thymeleaf-spring5 3.0.11.RELEASE org.thymeleaf.extras:thymeleaf-extras-java8time 3.0.4.RELEASE org.thymeleaf.extras:thymeleaf-extras-springsecurity5 3.0.4.RELEASE … Importing a bom
  12. plugins { id 'org.springframework.boot' version '2.1.4.RELEASE' } apply plugin: 'io.spring.dependency-management'

    Spring Boot does this for you
  13. dependencies { runtime 'org.thymeleaf:thymeleaf-spring5' } Overriding a version runtimeClasspath -

    Runtime classpath of source set 'main'. \--- org.thymeleaf:thymeleaf-spring5 -> 3.0.11.RELEASE +--- org.thymeleaf:thymeleaf:3.0.11.RELEASE | +--- org.attoparser:attoparser:2.0.5.RELEASE | +--- org.unbescape:unbescape:1.1.6.RELEASE | \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26 \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26
  14. Overriding a version dependencies { runtime 'org.thymeleaf:thymeleaf-spring5:3.0.10.RELEASE' } runtimeClasspath -

    Runtime classpath of source set 'main'. \--- org.thymeleaf:thymeleaf-spring5:3.0.10.RELEASE +--- org.thymeleaf:thymeleaf:3.0.10.RELEASE -> 3.0.11.RELEASE | +--- org.attoparser:attoparser:2.0.5.RELEASE | +--- org.unbescape:unbescape:1.1.6.RELEASE | \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26 \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26
  15. Overriding a version ext['thymeleaf.version'] = '3.0.10.RELEASE' runtimeClasspath - Runtime classpath

    of source set 'main'. \--- org.thymeleaf:thymeleaf-spring5 -> 3.0.10.RELEASE +--- org.thymeleaf:thymeleaf:3.0.10.RELEASE | +--- org.attoparser:attoparser:2.0.5.RELEASE | +--- org.unbescape:unbescape:1.1.6.RELEASE | \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26 \--- org.slf4j:slf4j-api:1.7.25 -> 1.7.26
  16. Maven-style exclusions <groupId>example</groupId> <artifactId>exclusions</artifactId> <version>0.0.1</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.3.RELEASE</version>

    <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
  17. Maven-style exclusions <dependencies> <dependency> <groupId>example</groupId> <artifactId>exclusions</artifactId> <version>0.0.1</version> </dependency> <dependency> <groupId>org.springframework</groupId>

    <artifactId>spring-beans</artifactId> </dependency> </dependencies> dependencies { implementation 'example:exclusions:0.0.1' implementation 'org.springframework:spring-beans' }
  18. Maven-style exclusions +- example:exclusions:jar:0.0.1:compile | \- org.springframework:spring-core:jar:4.1.3.RELEASE:compile \- org.springframework:spring-beans:jar:4.1.3.RELEASE:compile +---

    com.example:exclusion-example:1.0 | \--- org.springframework:spring-core:4.1.3.RELEASE | \--- commons-logging:commons-logging:1.2 \--- org.springframework:spring-beans:4.1.3.RELEASE \--- org.springframework:spring-core:4.1.3.RELEASE (*)
  19. Outline • Introduction to the Spring Dependency Management Gradle Plugin

    • Gradle 5 and beyond • Migration Tips
  20. Outline • Introduction to the Spring Dependency Management Gradle Plugin

    • Gradle 5 and beyond • Migration Tips
  21. Native BOM Support

  22. Consuming Maven Dependencies https://docs.gradle.org/current/userguide/managing_transitive_dependencies.html#sec:bom_import dependencies { implementation enforcedPlatform('org.springframework.boot:spring-boot-dependencies:2.1.4.RELEASE') implementation ‘org.codehaus.groovy:groovy:2.5.7’

    }
  23. https://scans.gradle.com/s/dowsysqbnns44/dependencies?dependencies=groovy&expandAll

  24. Forcing specific versions https://docs.gradle.org/current/userguide/managing_transitive_dependencies.html#sec:bom_import dependencies { implementation enforcedPlatform('org.springframework.boot:spring-boot-dependencies:2.1.4.RELEASE') implementation(‘org.codehaus.groovy:groovy:2.5.7’) {

    force = true } }
  25. https://scans.gradle.com/s/25snam34zlriw/dependencies?dependencies=groovy&expandAll

  26. Using Gradle’s Conflict Resolution https://docs.gradle.org/current/userguide/managing_transitive_dependencies.html#sec:bom_import dependencies { implementation platform('org.springframework.boot:spring-boot-dependencies:2.1.4.RELEASE') implementation

    ‘org.codehaus.groovy:groovy:2.5.7’ }
  27. https://scans.gradle.com/s/bwcwoumww2dtw/dependencies?dependencies=groovy&expandAll

  28. Overriding Groups of Dependencies https://docs.gradle.org/current/userguide/customizing_dependency_resolution_behavior.html#sec:dependency_resolve_rules dependencies { implementation platform('org.springframework.boot:spring-boot-dependencies:2.1.4.RELEASE') implementation

    "org.codehaus.groovy:groovy:2.5.7" } configurations.all { resolutionStrategy.eachDependency { DependencyResolveDetails details -> if (details.requested.group == 'org.codehaus.groovy') { details.useVersion '2.5.7' details.because 'upgrade to take advantage of new features' } } }
  29. https://scans.gradle.com/s/4sgi5nsf2zp7g/dependencies?dependencies=groovy&expandAll

  30. Performance

  31. https://scans.gradle.com/s/lopzbvymh2vmo/dependencies?toggled=W1swXV0

  32. https://scans.gradle.com/s/lopzbvymh2vmo/dependencies?toggled=W1swXV0

  33. With Gradle Native BOM Support https://scans.gradle.com/s/s3w7tsxmtc6xw/dependencies?toggled=W1swXV0

  34. Maven Publish Plugin • 5.2+ Resolved Dependencies vs Declared Dependencies

  35. 5.2+ Publishing Platforms with the Java Platform Plugin https://docs.gradle.org/current/userguide/java_platform_plugin.html#sec:java_platform_publishing

  36. 5.3+ Feature Variants Maven optional dependencies and more!

  37. Feature Variants

  38. Gradle Module Metadata Format

  39. Outline • Introduction to the Spring Dependency Management Gradle Plugin

    • Gradle 5 and beyond • Migration Tips
  40. Outline • Introduction to the Spring Dependency Management Gradle Plugin

    • Gradle 5 and beyond • Migration Tips
  41. Exclusions dependencies { implementation('log4j:log4j:1.2.15') { exclude group: 'javax.jms', module: 'jms'

    exclude group: 'com.sun.jdmk', module: 'jmxtools' exclude group: 'com.sun.jmx', module: 'jmxri' } } configurations { implementation { exclude group: 'javax.jms', module: 'jms' exclude group: 'com.sun.jdmk', module: 'jmxtools' exclude group: 'com.sun.jmx', module: 'jmxri' } }
  42. Multi-scope platform enforcement https://github.com/micronaut-projects/micronaut-profiles/issues/124

  43. IDE Support • Tooling hasn’t caught up to new 5.0

    features • Issues are filed and should be fixed soon
  44. Overriding Version Properties • The Plugin’s behavior is unique. It

    goes beyond both Maven and Gradle features. • For upgrading, overriding is possible in Gradle. • For downgrading, use: ◦ • Dependency metadata rule to fix what the dependency declares and is wrong ◦ • Substitutions to replace a given version with another ◦ • Force ◦ • Exclude • Look for new Gradle releases to fix the remaining differences.
  45. Conclusion

  46. Thanks! Andy Wilkinson @ankinson Jenn Strater @codeJENNerator gradle.org/docs