-
Notifications
You must be signed in to change notification settings - Fork 41.4k
Description
From Spring Boot's own documentation (as well as the many examples of use I've seen both within Spring Boot's own examples and elsewhere), it is clear that starter dependencies are intended to transitively bring in numerous other dependencies to be used at both runtime and compile. Per Spring Boot's documentation:
Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop-shop for all the Spring and related technology that you need, without having to hunt through sample code and copy paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, just include the spring-boot-starter-data-jpa dependency in your project, and you are good to go.
The starters contain a lot of the dependencies that you need to get a project up and running quickly and with a consistent, supported set of managed transitive dependencies.
However, according to the Maven dependency documentation it is intended that all compile dependencies be explicitly listed, rather than transitively used at compile time:
it is intended that [transitive compile dependencies] should be runtime scope instead, so that all compile dependencies must be explicitly listed - however, there is the case where the library you depend on extends a class from another library, forcing you to have available at compile time. For this reason, compile time dependencies remain as compile scope even when they are transitive.
Using this mechanism to transitively bring in compile-scoped dependencies therefore seems to be at odds with the intent of how Maven officially intends them to be used. One place that makes this abundantly clear is the Maven dependency:analyze plugin goal, which displays warnings when the Maven starter dependencies are used directly. For instance, running mvn dependency:analyze
on Spring Boot's own "Getting Started" example generates the following output:
[WARNING] Used undeclared dependencies found:
[WARNING] org.springframework:spring-web:jar:4.3.6.RELEASE:compile
[WARNING] org.springframework.boot:spring-boot-test:jar:1.5.1.RELEASE:test
[WARNING] org.springframework.boot:spring-boot-test-autoconfigure:jar:1.5.1.RELEASE:test
[WARNING] org.springframework:spring-test:jar:4.3.6.RELEASE:test
[WARNING] org.springframework.boot:spring-boot:jar:1.5.1.RELEASE:compile
[WARNING] org.hamcrest:hamcrest-library:jar:1.3:test
[WARNING] org.springframework:spring-context:jar:4.3.6.RELEASE:compile
[WARNING] junit:junit:jar:4.12:test
[WARNING] org.springframework.boot:spring-boot-autoconfigure:jar:1.5.1.RELEASE:compile
[WARNING] org.springframework:spring-beans:jar:4.3.6.RELEASE:compile
[WARNING] Unused declared dependencies found:
[WARNING] org.springframework.boot:spring-boot-starter-web:jar:1.5.1.RELEASE:compile
[WARNING] org.springframework.boot:spring-boot-starter-test:jar:1.5.1.RELEASE:test
[WARNING] org.springframework.boot:spring-boot-starter-actuator:jar:1.5.1.RELEASE:compile
Why was the Spring Boot starter pattern was designed in such a way to be directly contrary to the intent of the underlying build system? Is there a reason it was felt that this misuse is "OK"? Is there a "correct" way that this functionality — conveniently providing a set of dependencies at set known versions with a single simple Maven configuration — would better be implemented?
Note that I first asked this question on StackOverflow per the Spring Boot question guidelines, but I received no responses and the question got closed as "too broad". — https://stackoverflow.com/questions/27994153