paint-brush
Using Maven's Dependency Analyzer to Get Rid of Unused Dependencies is Dangerous Advice Todayby@nfrankel

Using Maven's Dependency Analyzer to Get Rid of Unused Dependencies is Dangerous Advice Today

by Nicolas Fränkel
Nicolas Fränkel HackerNoon profile picture

Nicolas Fränkel

@nfrankel

Developer Advocate, eternal learner, author

March 13th, 2025
Read on Terminal Reader
Read this story in a terminal
Print this story
Read this story w/o Javascript
Read this story w/o Javascript
tldt arrow
en-flagEN
Read this story in the original language, English!
es-flagES
Lee esta historia en Español!
zh-flagZH
用繁體中文閱讀這個故事!
ja-flagJA
この物語を日本語で読んでください!
qu-flagQU
Ñawinchay kay willakuyta en quechua!
ht-flagHT
Li istwa sa a an kreyòl ayisyen!
cs-flagCS
Přečtěte si tento příběh v češtině!
fa-AF-flagFA-AF
این داستان را به زبان دری بخوانید!
nl-flagNL
Lees dit verhaal in het Nederlands!
bg-flagBG
Прочетете тази история на български!
fi-flagFI
Lue tämä tarina suomeksi!
lv-flagLV
Izlasi šo stāstu latviešu valodā!
lt-flagLT
Skaitykite šią istoriją lietuvių kalba!
EN

Too Long; Didn't Read

The current state of the Maven analyzer doesn't offer any benefit to modern Spring Boot projects.

Companies Mentioned

Mention Thumbnail
Default
Mention Thumbnail
effect

Coin Mentioned

Mention Thumbnail
Arweave
featured image - Using Maven's Dependency Analyzer to Get Rid of Unused Dependencies is Dangerous Advice Today
1x
Read by Dr. One voice-avatar

Listen to this story

Nicolas Fränkel HackerNoon profile picture
Nicolas Fränkel

Nicolas Fränkel

@nfrankel

Developer Advocate, eternal learner, author

About @nfrankel
LEARN MORE ABOUT @NFRANKEL'S
EXPERTISE AND PLACE ON THE INTERNET.


Recently, my good friend Richard Fichtner advised using the mvn dependency:analyze command to get rid of declared but unused dependencies:


article preview
BLUESKY SOCIAL

Richard Fichtner 💻☕ (@richard.fichtner.dev)

There is another use case for mvn dependency:analyze It can show you the dependencies you use in your code but have not declared in your pom.xml. This works because you have a transitive dependency on your classpath. Either don't use the dependency or declare it.

While it was a great idea years ago, it's dangerous advice today. In this post, I'd like to explain what the plugin does and why you shouldn't use it but in the most straightforward projects.

The mvn dependency:analyze command

Maven uses a plugin architecture; in the above command, the plugin is maven-dependency-plugin. A plugin hosts several related goals. Here, it's analyze.


Analyzes the dependencies of this project and determines which are: used and declared; used and undeclared; unused and declared. This goal is intended to be used standalone, thus it always executes the test-compile phase - use the dependency:analyze-only goal instead when participating in the build lifecycle.


By default, maven-dependency-analyzer is used to perform the analysis, with limitations due to the fact that it works at bytecode level, but any analyzer can be plugged in through analyzer parameter.


-- dependency:analyze


maven-dependency-analyzer is a shared Maven component. Its description is quite descriptive:


Analyzes the dependencies of a project for undeclared or unused artifacts.

Warning: Because analysis is done on the bytecode rather than the source, some cases are not detected including constants, annotations with source-only retention, and links in Javadoc. This can lead to incorrect results when these are the only uses of a dependency.


The main component is ProjectDependencyAnalyzer, which uses ClassAnalyzer and DependencyAnalyzer.


-- maven-dependency-analyzer


The warning clearly shows that it works at the bytecode level. In particular, it explicitly mentions that it doesn't consider source-level annotations.

Spring Boot starters

I described how to design your own Spring Boot starter a long time ago, and it didn't change a lot since then. If you're new to Spring Boot starters, here's a summary.


SpringBoot relies on AutoConfiguration classes. AutoConfiguration classes are regular configuration classes, i.e., they contribute to the application classes. You can set specific activation criteria, such as the presence of a Spring property, but these are not specific to auto-configuration.


Here's a very simplified flow:


Simplified sequence diagram of the auto-configuration in Spring Boot

Simplified sequence diagram of the auto-configuration in Spring Boot


The JAR that automatically comes with Spring Boot is org.springframework.boot:spring-boot-autoconfigure. You can check the content of its META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:


...
org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.ReactiveMultipartAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.WebSessionIdResolverAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration


As an example, here's the RestClientAutoConfiguration:


@AutoConfiguration(after = { HttpClientAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class }) //1
@ConditionalOnClass(RestTemplate.class)                //2
@Conditional(NotReactiveWebApplicationCondition.class) //3
public class RestTemplateAutoConfiguration {

    // Class body
}
  1. Set the order of auto-configuration classes
  2. Activate if the RestTemplate class is on the classpath
  3. Activate if we aren't in a reactive web app context


Note that the class loader loads the RestTemplateAutoConfiguration class just fine, regardless of whether the RestTemplate class is on the classpath or not! Spring leverages this mechanism to its fullest, as seen above. In effect, the resolution of classes configured in annotations is deferred until they are explicitly accessed.

Bringing the maven-dependency-analyzer into the modern age

Committers designed the analyzer in 2007: here's how it looked like then. Spring Boot started later, in 2010. For this reason, the analyzer didn't take deferred class loading in annotations. Note that this is still not the case; the project doesn't get a lot of love.


When using the plugin on a Spring Boot project, you'll get a lot of false positives. I tried it with a simple Spring Boot project, using WebFlux and R2DBC on PostgreSQL.


Here's a slight excerpt of the output when I run mvn analyze:dependencies:


[WARNING] Unused declared dependencies found:
[WARNING]   org.springframework.boot:spring-boot-starter-data-r2dbc:jar:3.4.0:compile
[WARNING]   org.testcontainers:postgresql:jar:1.20.4:test
[WARNING]   org.testcontainers:r2dbc:jar:1.20.4:test


If I remove any of these dependencies, tests don't run.


What would be necessary to make the analyzer work with Spring Boot projects? Let's analyze the analyzer.


Analyzer class diagram

Analyzer class diagram


The plugin allows configuring another analyzer:


Specify the project dependency analyzer to use (plexus component role-hint). By default, maven-dependency-analyzer is used. To use this, you must declare a dependency for this plugin that contains the code for the analyzer. The analyzer must have a declared Plexus role name, and you specify the role name here.


  • Type: java.lang.String

  • Since: 2.2

  • Required: No

  • User Property: analyzer

  • Default: default


-- dependency:analyze


We can create an overall analyzer that reuses the above but adds one specific to Spring Boot.

Conclusion

The current state of the Maven analyzer doesn't offer any benefit to modern Spring Boot projects. The existing code is open to configuration and even extension. However, we would need to embed a lot of Spring Boot logic. For Quarkus and Micronaut projects, we would require dedicated code as well.


I don't know if it's worth the time and effort. If you think it is, I hope this blog post can serve as an early-stage analysis.


To go further:





Originally published at A Java Geek on March 9th, 2025

L O A D I N G
. . . comments & more!

About Author

Nicolas Fränkel HackerNoon profile picture
Nicolas Fränkel@nfrankel
Developer Advocate, eternal learner, author

TOPICS

THIS ARTICLE WAS FEATURED IN...

Arweave
Read on Terminal Reader
Read this story in a terminal
 Terminal
Read this story w/o Javascript
Read this story w/o Javascript
 Lite
Also published here
Hackernoon
Threads
Bsky

Mentioned in this story

X REMOVE AD