Not that I’m a big fan of the whole “Anti-Pattern” concept, but there is some subtle irony in the title of this post; some of my coworkers will actually understand. Sorry about the mystery for the rest of you, but I think this post is really relevant for those trying to use Spring for the first time. After building my first Spring-based application, I was on the fence concerning Spring’s actual value. Obviously, I made lots of mistakes in my first implementation; I think many of the following anti-patterns can typically happen on your first Spring project; my goal is to make you aware of these pitfalls, such that you can skip past the mistakes made by myself and others.
|Interesting Thought Tangent?
While looking for the title to my post, I have found a little snippet that calling “Spring a direct attack on J2EE“. I thought this was a unique way of describing the Spring Framework. For sometime now, I have been on the bandwagon to simplify the development practice through Spring (Spring Core, Security and Remoting). I never really thought about Spring as another religious battle front; such as the classic emacs/vi or mac/pc wars. In essence, I was picking a side: No more J2EE! I guess it was not obvious to me before today, as I really can’t escape the J2EE container; I’m are required to deploy in a J2EE container, even though I make no use of its capabilities; a Servlet container is all most of us really need! Just an interesting thought! Agree or Not?
So where to begin, I guess the first question is: Why do you want to use Spring? What service(s) will it provide for you? I think many developers simply wanted to slam it on their resume! Let’s start with the the most obvious use of Spring, Dependency Injection (WIKI, Fowler). I think this is the hardest thing for most developers to actually understand! If you think you are just writing XML code to create your instances rather than writing Java code, you have already missed the boat. I really believe that most developers have not actually taken advantage of DI in their applications. They just use Spring to create an alternative static (hard-wired) bean creation strategies. Just for fun, I thought I would highlight some anti-patterns I have seen used before and hopefully never again!
|Create a Factory.
Factories are so 1990. This is one hurdle that some developers have a tough time understanding. They continue to think about creating objects via factories. There is NO need to ever create a factory when using Spring. Spring is essentially the a super factory, plus it is actually responsible for the life-cycle of those vended objects. There are scenarios where you need to specifically create objects that Spring manages, in a loop for example; but these are very uncommon. The proper way to solve this problem, is to create a bean that is ApplicationContextAware. When this bean is created (by Spring itself), Spring will set the application context on this bean. Now, you have the ability to ask for any bean that Spring is managing.
|Ask Spring for objects.
This is probably the toughest habit to break and is easiest pattern to get stuck in. This is especially true if you are trying to integrate Spring into an existing project and is your first attempt at Inversion of Control. You will have a much better chance understanding these constructs, if you can start from a clean slate (or at least create a bunch of samples). Spring done right, is truly is a different way of thinking. For example, when working with a context-aware Servlet, you fundamentally NEVER need to ask Spring for a single instance; this is almost a perfect example of IOC and DI. The whole point of DI is the INJECTION. It is not about ASKING for an instance, it is about being GIVEN an instance; throw in the IOC principle and your bean will be invoked at the RIGHT time to provide the appropriate behavior.
|Domain Object DI.
This was an unusual one for me. I recently observed a project that used Spring to created multiple static Singleton factories to vend out a variety of instances, each factory with it’s own Spring context file. Needless to say, this application was far from easy to understand. To my surprise, there was even a factory specifically implemented for creating the business domain objects. Why this was done is still a mystery to me and seems to violate the true spirit of Spring. Why would I ever want to call DomainFactory.getNewWidget() or DomainFactory.getNewGadget()? The configuration had the domain beans defined in a separate Spring context file and oddly, used static methods to initialize specific properties of these new bean instances. There was no way which enabled the XML configuration to be overridden, allowing for different implementations. Worse yet, you were tied to the initialization behavior of the factory methods! Depending on your definition of a domain object, I see very little reason domain object dependency injection.
|Use Ant to create Spring Configurations.
This is an interesting use of Ant in a Spring-based application. The idea here is to generate the Spring configuration and properties file from an Ant task, to specifically configure the context files to each deployment environment. They values are essentially baked into the application and unchangeable. It is bad enough to substitute property file values, but some developers actually substitute bean name references. This might be a little hard to follow, but the Spring XML configuration would define two different implementations of the same basic function, each with its own name. When the application is built, the Ant tasks would substitute ref=”bean1” for some environments and ref=”bean2” for others; everywhere that implementation was referenced in the configuration files. Call me crazy, but I don’t think this what the Spring creators ever intended!
As I have developed a better understanding of Spring and how to take advantage of it features, we have evolved our Spring applications to a state of “environmental awareness”. Using this solution, all of the context and property files are packaged into the application, for all known environments at build time. This enables us to build the deployment image (jar/war file) one time, using simple Ant tasks, no more templates, no more substitutions, no complexity. At execution time, Spring is now intelligent and can determine it’s execution environment; we can use specific property files for specific environments, as well as use alternate implementations (via DI) for each environment. This is where DI really pays off, allowing us to use the appropriate objects, not just properties, but objects for each environment! No code changes, no crazy Ant tasks, you build once and deploy anywhere. I think this is actually pretty slick and what Spring (core functionality) is all about.
I do have to put in a plug in for testability. Taking advantage of jUnit 4.x annotations and Spring integration, makes unit testing a snap. Using the @Resouce annotation to inject everything (instances) you need into your unit test is amazingly elegant; unit testing could not be made any easier. This approach allows us to have highly controlled, customizable execution environments; we can seamlessly manage unique configurations for local development, continuous integration, as well as any actual deployment environment almost magically.