It seems it's impossible, these days, to write a decent-sized Java application without becoming reliant on fifty different library Jar files, culled from various open-source projects.
On one hand, this is great. It's great that Java has such a vibrant culture, and is producing such a large volume of helpful libraries. It's great that if you think "Hey, I'd like to do foo", there's probably a halfway decent free implementation of foo4j waiting for you to download it. Which brings us closer to that whole 'reuse' thing that everyone's been shouting about for years.
It also makes for frustratingly fragile applications.
You've got fifty libraries. Each may depend on, or plug in to some combination of the other libraries. Each has its own bugs (quickly fixed of course), and thus its own release schedule. New releases may change dependencies on other jars. We end up building tools to deal with this complexity, but then the tool just becomes another dependency.
And, of course, each library has its own configuration file. Configuration and properties files swarm over J2EE applications like kudzu, each with its own format, and each resisting to the end any attempt at centralisation or rationalisation. Want to have one big central switch that changes your app over from development to production mode? Well you'll have to script it externally, because the necessary changes are spread across two properties– and three XML files.
(And any attempt to provide a standard programmable configurability or configuration discovery mechanism would lead to: seven or eight competing implementations, arguments on the merits of which version of IOC is best for the task, flame-wars about the JCP/Jakarta/the EFnet #java ops, and yet another damn dependency!)
And you (OK, I) end up in situations where B is throwing a NullPointerException where it's being called from A (via the helpfully provided A->B plugin). Is it a bug in A? Is it a bug in B? Is it really a bug in C, the invisible piece of infrastructure that introduced A to B? Is it some missing or malformed piece of vital configuration that neither A, B nor C have warned me is wrong? Hello, several hours of fruitlessly debugging unfamiliar fragments of Other Peoples Code.
It's enough to do your head in.