Slide 1

Slide 1 text

Surviving Dependency Hell With Maven

Slide 2

Slide 2 text

2 @aalmiray @saturnism Ray Tsang Developer Advocate @ Google Java Champion Spring Cloud GCP JDeferred Contributors to JLBP.dev @saturnism | saturnism.me

Slide 3

Slide 3 text

3 @aalmiray @saturnism Robert Scholte Java Champion Founder, Source Ground Apache Maven PMC Chair Member Expert Group JSR 376 - Jigsaw @rfscholte

Slide 4

Slide 4 text

4 @aalmiray @saturnism Andres Almiray Seasoned Sourceror @ Oracle Java Champion Hackergarten JDeferred & many others! @aalmiray | andresalmiray.com

Slide 5

Slide 5 text

5 @aalmiray @saturnism Let's see the code

Slide 6

Slide 6 text

6 @aalmiray @saturnism NoSuchMethodError NoSuchFieldError NoClassDefFoundError

Slide 7

Slide 7 text

7 @aalmiray @saturnism mvn dependency:tree mvn dependency:tree -Dverbose=true mvn dependency:tree -Dverbose=true -Dincludes=...

Slide 8

Slide 8 text

8 @aalmiray @saturnism Example 1 Translate Truth Guava 19 Guava 21 Which version to use?

Slide 9

Slide 9 text

9 @aalmiray @saturnism Any dependency there can be only ONE version Classpath - First class wins Maven - Nearest wins

Slide 10

Slide 10 text

10 @aalmiray @saturnism Maven does not understand Semver Nor compatibility

Slide 11

Slide 11 text

11 @aalmiray @saturnism Use Maven Enforcer Convergence vs Upper bound http://maven.apache.org/enforcer/enforcer-rules/dependencyConvergence.html (See Code!)

Slide 12

Slide 12 text

12 @aalmiray @saturnism Ensuring only ONE version of the dependency in tree Exclusions, or Dependency Management (See Code)

Slide 13

Slide 13 text

13 @aalmiray @saturnism Upper bound if higher version is backwards compatible [JLBP-7] Make breaking transitions easy [JLBP-10] Maintain API stability as long as needed for consumers (Guava 21 and up are backwards compatible)

Slide 14

Slide 14 text

14 @aalmiray @saturnism If upper version is breaking lower version… Or, system classpath has an incompatible version (Hadoooooop)

Slide 15

Slide 15 text

15 @aalmiray @saturnism Shade + Relocation :( Classloaders OSGi

Slide 16

Slide 16 text

16 @aalmiray @saturnism GA libraries don't depend on non-GA APIs alpha, beta, RC, 0.xx, @UnstableApi, @Beta, @Internal [JLBP-4] Avoid dependencies on unstable libraries and features

Slide 17

Slide 17 text

17 @aalmiray @saturnism Major release, breaking changes Use new Group ID or Artifact ID - different coordinate! AND Use a new package name [JLBP-6] Rename artifacts and packages together

Slide 18

Slide 18 text

18 @aalmiray @saturnism How do we change versions in transitive dependencies?

Slide 19

Slide 19 text

19 @aalmiray @saturnism Maven Dependency Management

Slide 20

Slide 20 text

20 @aalmiray @saturnism Let's see Example 3e

Slide 21

Slide 21 text

21 @aalmiray @saturnism Example 1 PubSub Firebase guava-jdk5 17.0 guava 28.0

Slide 22

Slide 22 text

22 @aalmiray @saturnism Ban Duplicate Classes https://www.mojohaus.org/extra-enforcer-rules/banDuplicateClasses.html

Slide 23

Slide 23 text

23 @aalmiray @saturnism 2 artifacts should not have overlapping classes [JLBP-5] Avoid dependencies that overlap classes with other dependencies [JLBP-19] Place each package in only one module

Slide 24

Slide 24 text

24 @aalmiray @saturnism [JLBP-11] Keep dependencies up to date!

Slide 25

Slide 25 text

25 @aalmiray @saturnism Let's fix all of these And see the next example 3c

Slide 26

Slide 26 text

26 @aalmiray @saturnism Example Pubsub Trace grpc-stub 1.10.1 grpc-all 1.0.1 grpc-core 1.0.1 grpc-... 1.0.1

Slide 27

Slide 27 text

27 @aalmiray @saturnism Version Misalignment

Slide 28

Slide 28 text

28 @aalmiray @saturnism How do we change versions in transitive dependencies?

Slide 29

Slide 29 text

29 @aalmiray @saturnism Example Pubsub Trace grpc-stub 1.10.1 grpc-all 1.10.1 grpc-core 1.10.1 grpc-... 1.10.1 grpc-bom 1.10.1

Slide 30

Slide 30 text

30 @aalmiray @saturnism Multi-module projects Produce a BOM! [JLBP-15] Publish a BOM for multi-module projects

Slide 31

Slide 31 text

31 @aalmiray @saturnism See an example!

Slide 32

Slide 32 text

32 @aalmiray @saturnism Power → Responsibility BOM should not overreach! ONLY modules within the multi-project project

Slide 33

Slide 33 text

33 @aalmiray @saturnism gRPC also uses another method Strict Version Ranges for inter-module dependencies, e.g. [1.10.1]

Slide 34

Slide 34 text

34 @aalmiray @saturnism Linkage Checker Static Analysis to identify missing links https://github.com/GoogleCloudPlatform/cloud-opensource-java/tree/master/enforcer-rules

Slide 35

Slide 35 text

35 @aalmiray @saturnism Bigger issues with Dependency Management...

Slide 36

Slide 36 text

36 @aalmiray @saturnism What you build & test with Is not what consumers get!

Slide 37

Slide 37 text

37 @aalmiray @saturnism Flatten the POM https://github.com/mojohaus/flatten-maven-plugin/pull/93

Slide 38

Slide 38 text

38 @aalmiray @saturnism Bonus mvn dependency:analyze - find dependencies you don't need Maven 3.6.3 - fixes our exclusion fix in Maven 3.6.2

Slide 39

Slide 39 text

39 @aalmiray @saturnism Enforcer Rules Enforcer Version Convergence or Upperbound Ban Duplicate Classes Linkage Checker Manage Transitive Versions BOM for Multi-Module Import BOM Maven Flatten Plugin

Slide 40

Slide 40 text

40 @aalmiray @saturnism Visit the best practices at JLBP.dev Thanks! Andres Almiray @aalmiray Ray Tsang @saturnism Maven used by 60% to 80% of Java projects 92 projects, 50+ plugins, lots of libraries - Contribution Appreciated!