M. Justin
M. Justin

Reputation: 21122

Why were Spring Boot starter dependencies designed to be used contrary to the stated intent of Maven's transitive dependency mechanisms?

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.

Spring Boot has a notion of "Starter" dependencies. 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 these 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.

Using this mechanism to transitively bring in compile-scoped dependencies 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

My question is why the Spring Boot starter pattern was designed in such a way to be directly contrary to the stated intent of the underlying build system. Are there any posted discussions on the topic, or explanations given anywhere?

Upvotes: 19

Views: 3717

Answers (2)

M. Justin
M. Justin

Reputation: 21122

This question was raised as an issue in the Spring Boot project as spring-boot#8341. Several Spring Boot developers responded to the issue to state their opinion that this is not actually a misuse of the Maven dependency mechanism.

Comment:

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?

IMO, you've read too much into a single sentence in Maven's docs. I think it's telling that to be even warned you have to opt in.

Is there a reason it was felt that this misuse is "OK"?

Misuse is rather subjective. I don't consider the starters to be a misuse. If you do, then you are free to declare all of your compile dependencies explicitly.

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?

I don't believe so, which could be one very good reason why transitive compile dependencies remain in the compile scope and no warnings are generated by default.

Comment:

You are overreading this and your point of view lack of practicability IMO. The dependency:analyze goal was a mean to offer users a way to detect that your compilation classpath only contains what you actually need. This sentence in the doc is merely there to explain why the compile scope is transitive as well.

[...]

In retrospective, you're having a Maven question and not a Spring Boot questions because tons of projects out there not using Spring Boot do not list all their compile dependencies themselves.

Based on this feedback, ticket MDEP-557 has been created in for the Maven Dependency Plugin to not warn on these transitive dependency usage.

So, to answer the question, the Spring Boot team feels this is an appropriate usage of transitive dependencies, and that it is that this is not contrary to the intent of Maven.

Upvotes: 1

Pushkar
Pushkar

Reputation: 571

Looks like you have configured dependency plugin to fail on warnings. I think dependency plugin spits out warning if you have not explicitly declared a transitive dependency.

Try changing <failOnWarning>true</failOnWarning> to <failOnWarning>false</failOnWarning>

Upvotes: 0

Related Questions