If you’ve used Maven long enough you’ve seen this pattern.
- You work somewhere that breaks up development into several independent groups.
- Different teams have very different standards for dependencies and project organization.
- One team sends over a JAR file that has transitive dependencies on everything from testing frameworks to unnecessary JDBC drivers.
I call this pattern the “Someone Needs to Train that Team on Maven” pattern because that’s exactly what needs to happen. Usually this happens at large enterprises set up to support multiple levels of development, say one team is working on a project that supplies a client to another team. One team is developing a REST service and, as a convenience, they supply a JAR that contains a simple model object and some code to interact with the REST service.
Easy, right? Wrong. A good developer will make sure that this client artifact has as few dependencies as possible. Lean dependency signatures are key in large enterprises. If the interaction with that other system is via REST, then there’s no reason to include backend code to interact with a database or the code that actually implements the service. If the other team has a limited understanding of Maven dependencies – then there will be trouble. You will get a client JAR that happens to include everything and the kitchen sink – your 8 MB WAR file bloats up to 200 MB because it includes several versions of Spring (even though you don’t use Spring).
In Maven, dependency hell is often not due to the tool itself, it is self-inflicted and it quickly infects your entire organization’s Maven projects. One bad project, one developer with a weak understanding of when and where to declare dependencies can create a disaster that will bloat the dependency trees of projects that consume that artifact. Anyone who touches an artifact with bloated transitive dependencies gets bloated dependencies.
Jason van Zyl at Takari points to the solution.
In Maven 3.2.1, you can exclude all of the transitive dependencies for a dependency. This means that, if someone sends you a JAR artifact with an awful POM, you can cut the problem off at the root.
I’ve seen some people do similar things by declaring a dependency as “provided” in dependency management, but this is both time consuming and incorrect. The thinking here is that I can selectively cut out transitive dependencies by just declaring each transitive dependency as “provided”. It hacks at Maven’s model to get around this short-coming. Maven 3.2.1 has a more elegant solution to what I see as an unfortunate reality for most large-scale Maven projects.
And, that unfortunate reality is that most people using Maven have a limited understanding of how dependencies work. This is an ailment which is easily fixed with training.