Maven transitive dependencies from a module design perspective
Maven's transitive dependencies are unforgiving of mistakes in module design. Let's look at what to take into account. Suppose we have a module Foo. We use it on the server as part of a web application and locally as part of a command-line tool. Foo has several dependencies of its own. Let's say one is shared between environments, and there are two distinct sets, one for each environment, as the following diagram shows.

Because of how Maven handles transitive dependencies, adding Foo to a WAR brings in all its dependencies, including the local ones in the yellow boxes. Conversely, if we generate a classpath for local use, it includes dependencies needed only on the server. If there are only a few dependencies, this probably doesn't matter. Once there are more, we need to deal with it.
The first and best approach is to refactor Foo into three parts. Foo server holds the server logic, Foo local holds the logic for local use, and Foo common holds what both parts share. We create the last module only if there's shared logic. Splitting Foo into these modules also splits its dependencies. The next diagram shows the ideal arrangement.

We don't live in an ideal world, and Foo might be difficult or even impossible to refactor if it's legacy code. In that case we have two options. Wherever we want to use Foo, we can stop unwanted dependencies by excluding them explicitly. The drawback is repeating this manual step everywhere Foo is used. If Foo needs a new dependency later and it conflicts with either the server or the local environment, we have to add it to the exclusions by hand.
The other option is to use optional dependencies, which don't form part of the transitive closure. In the next diagram, dashed lines mark optional dependencies. Modules won't pick them up as part of the transitive closure, but they still have to declare them explicitly where needed. The following diagram shows this with the WAR explicitly adding its optional dependencies.

This has the same drawback. Every place that uses Foo must repeat the optional dependencies manually, with the same trouble adding more later. One trick can remove that drawback. Introduce a special module for each environment whose sole purpose is to group dependencies. That centralizes dependency management for each environment in one place. Use these ad hoc modules in place of the original Foo module.

This grouping workaround can help fix almost any unsuitable dependency arrangement and can be combined with explicit exclusions. It's a pity Maven has no better way to reconcile dependencies. You could also look at it as Maven enforcing a sound division into modules and deliberately making it hard to work around.
Related articles
Related CZ Podcast episodes
- #3 · Java 6 SE, Vývoj webových aplikací
Dagi and Filemon discuss Java 6 and web application frameworks. · Czech audio
- #1 · Vývojová prostředí v Javě
The first CZ Podcast episode looks at Java development environments. · Czech audio