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.
I could not agree more.
There is no reason why you should bother programming in XML just to wire your system together. Although Spring might seem like a good fit here, you will most likely end up in a configuration nightmare caused y exposing spring-configuration files as part of your public interface.
The thing you are referring to Johannes as the module context is most likely the public API that you want to expose from your module. I have seen this quite a few other places as well. Although Spring framework classes like JdbcTemplate is a perfect example of a very good framework API, there is not reason why you should use spring to perform dependency injection when there is really no need to.
If you need to wire the dependencies between two modules A and B together, typically in web-application C, do it in java, create your own code to wire these dependencies together implementing a customized ApplicationContext intead of using spring.
I really wonder how we ended up in this mess. For years now, we laugh at code samples from the EJB era where we needed 10 lines of code just to invoke a stupid method on some java class using home/remote interfaces. Now when we see code fragments like:
we say, “Wow cool, it works”. I have very much respect for the creators of the spring-framework, and it provides excellent value when provided correctly. When it comes to dependency injection and XML, I really must say that I wonder how we ended up here….
Thanks for the comment. I think your sentiments here are right on the money. XML (or DSLs, for that matter) is not the solution. I hope that new language features like annotations will make it easier to raise the abstraction level in Java, instead of trying to invent a new notation. For some things (e.g. @Transactional), annotations is probably the best solution, for other things, it can help make the wiring code more maintainable, but, like you say, it may not belong in the business logic.
[Christian Rørdam] - May 17, 2007
I totally agree with you, Johannes and Bjørn. There is absolutely no reason why you should program in XML if you can do it in Java. I think there is a general misunderstanding among many people that separating the wiring code (or the business rules for that matter) from the rest of the code means that one should use a different format. Rubbish! Just put it in a separate place.
I haven’t tried the annotation style, but I don’t like the idea, as it is intrusive. I think the best thing is to have a separate module/package with Java code that wires up the other modules.
[Kukenspeil] - May 14, 2007
I completely agree. The whol project is a disaster and lots of it has to do with the complete clusterfuck of spring XML.
[Per Spilling] - May 7, 2007
Have you had a look at this? http://blog.interface21.com/main/2006/11/28/a-java-configuration-option-for-spring/
Rod showed me the pure Java configuration about a year ago. Since we’re still in the process of adopting Java 5, I have not used it yet, so I can’t comment on it.
But getting teams to stop using Spring XML will be a Good Thing. And the annotation based configuration could potentially help.