Last night, I worked until after midnight trying to get our application up and running after some seemingly inconsequential changes in Spring-XML configuration. Our application consists of a total of 32 modules (including 6 wars and one “server” module that packages them, and 11 modules that are shared with other projects). Most of these modules have Spring-XML fragments that are included in a few different ways, with the result that a nobody on the team actually understands how it fits together. My conclusion is that Spring-XML is at least as bad as the old ejb-jar.xml and similar regimes that is has tried to replace, and that it might be a sufficient reason to recommend not using Spring at all.
Spring: The good, the practical and the really, really ugly
As I see Spring, it consists of three ideas: The design principle of dependency injection, a class library to ease the use of Java EE functionality, and Spring XML configuration. The ideas can be adopted wholesale, or you can pick and choose. However, in my experience, people don’t pick and choose, but go wholesale for Spring.
Now, the design principle of dependency injection is a really good one, and I follow it even when I don’t use Spring. It simply means: Use setters on your service-objects to wire functionality together. Used correctly, I find that dependency injection makes it much easier to understand how a program fits together. It is important to notice, however, that there is no requirement to use XML to configure your dependencies. Doing so means you are committing one of the Modern Sins of Programming: Writing Code in XML.
Spring library classes are also unproblematic. As a matter of fact, they are among the most well-designed classes I have ever seen, and with a few exceptions, they are a joy to work with.
However, Spring-XML is a patently bad idea. If I could give some advise to the Spring team, it would be to separate out Spring-XML from the Spring project all together. Programmers in my organization have burned themselves badly on complex configuration, and it would be better if we could just say “Use Spring, but don’t use Gnirps.” Or maybe I just wish that two years ago, the option of using Spring-XML had not been made available to me.
A horror story: How to *not* use Bean Post Processors
Let me give a specific example of the mess we’re in: We use a ResourceBundleMessageSource to configure error messages to display (in log files, actually). Interestingly, if a message does not exist, this means that the
getMessage method will throw a MessageNotFoundException. However, many of our modules (actually only a few) have their own property files with message texts. Here is how they are combined:
- A messageSource bean is injected into classes that need to resolve messages. The bean doesn’t know which property files to read
- In the total configuration, we include the “module context” XML file for a number of modules into a full Spring XML application context.
- Some of the modules define a MessageSourceBobThingie with a filename for a message file
- A Bean Post Processor finds all MessageSourceBobThingies and set them on the single messageSource for the full application
This means that we forget to include a “module context”, a property file is not added to the messageSource. However, we only get this warning some time during runtime when a message is missing. The fact that each application context consists of roughly 15 Spring XML files makes it just about impossible to find out which message sources are actually imported. And because we don’t have extensive unit tests with the full configuration file, we don’t know if we have forgotten a property file until we’ve deployed the application.
What to do?
In conclusion, we have mechanisms for reuse and combination of Spring-XML files that are killing our applications slowly. I feel tempted to just delete the offending classes and Spring XML files, but that would kill us immediately.
I wish we hadn’t had Spring XML and “clever” programmers like myself.