Alex Collins is a enterprise Java developer and currently works in the UK. He has worked in the insurance, publishing, telecoms and supply chain. In his spare time he codes in Python, Clojure and Scala (but not at the same time) and enjoys a multitude of sports. His catchphrase is K.I.S.S! Alex has posted 20 posts at DZone. You can read more from them at their website. View Full User Profile

How do you configure Spring?

09.30.2010
| 10486 views |
  • submit to reddit

With Annotations, Java classes and XML all available for configuring your beans - what approach do you take?

XML Configuration

Given that XML has been the defacto for configuring Spring beans since the start, you'd be forgiven if you weren't aware of the other approaches. However, it does have its downsides as your code-base grows. Invariably as time goes on you'll have more interfaces with more 'impls, which means more bean definitions and more injections, which in turn leads to massive context configuration files with hundreds of lines of XML. It becomes painful to work with - your head swells as you stare at line upon line of <bean id="... and so on - and can be quite a merge nightmare on your hands should you have multiple workstreams ammending similar areas of your code.

In steps annotations. They really make Spring a breeze, as well as paving the way for some of the simplest MVC features you can find (although Stripes was there first I think) in most frameworks.

In defence of XML

It does have an advantage. It allows you to see - at a quick glance - all of the beans you have defined and their associated classes. This comes in handy when you have many beans with multiple implementations.

@Configuration

Spring 3 introduced the concept of configuration Java classes that instantiate the beans, which satisfies the 'all in one place' mantra. Using a few more annotations, you get a much simpler representation of your injection hierarchy, but without the XML bloat.

Take the following example;

@Configuration
public class AppContextConfiguration {
    public @Bean(name = "documentService")
    DocumentService getDocumentService() {
        return new FileBaseDocumentService();
    }
}

Now, that's a tasy way of wiring your beans together, and it's in something every Spring user will intrinsically understand: Java!

So, given the above, how do you configure your Spring contexts in the real world? Do you mix any of the above? Were you aware of some but not the other? Cast your vote below! 

Published at DZone with permission of its author, Alex Collins.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Alessandro Santini replied on Fri, 2010/10/01 - 7:02am

I am not a fan of XML configuration files, but I find them a lesser evil compared to DI annotations.

Alex Collins replied on Fri, 2010/10/01 - 8:53am in response to: Alessandro Santini

I'm with you on that one!

Lance Semmens replied on Fri, 2010/10/01 - 10:16am

It would be great if we could have the best of both worlds:

  1. Use annotations to specify your config
  2. Reverse engineer an annotation report (XML or other) from the java source

Step 2 could be done at build time with an ant task / maven mojo where you pass the list of annotation classes you want to create the report (XML file) on.

Anyone else think that this is a good idea?

Josh Marotti replied on Fri, 2010/10/01 - 10:32am

Annotations would be fantastic... if they were in the Java language, not spring.  Every spring based anotation you put in a java class that isn't already in the base java language creates a coupling between your file and spring.  This is also why I hate hibernate annotations.  If I want to make a domain class, or business logic method... I don't want it coupled to an API I happen to be using at the time!

Lance Semmens replied on Fri, 2010/10/01 - 10:41am

As an example of what I'm proposing, the following would produce 2 xml files. Each file containing all of the annotation information for hibernate and spring respectfully.

<taskdef name="annotation-report" classname="foo.bar.AnnotationReportTask"/>

<annotation-report type="xml" file="hibernateReport.xml">
    <src dir="src/main/java" />
    <annotations>
        <annotation name="org.hibernate.annotations.*" />
        <annotation name="javax.persistence.*" />
    </annotations>
    <classpath ref="..." />
</annotation-report>

<annotation-report type="xml" file="springReport.xml">
    <src dir="src/main/java" />
    <annotations>
        <annotation name="org.springframework.beans.factory.annotation.*" />
    </annotations>
    <classpath ref="..." />
</annotation-report>

Alessandro Santini replied on Fri, 2010/10/01 - 10:46am in response to: Lance Semmens

Nothing against the idea, I am simply convinced that annotations in this context break the concept of "loosely coupled".

Mladen Girazovski replied on Fri, 2010/10/01 - 11:08am

I like to use Annotation to specify where something gets injected (using @Resource on the Setter), my XML configs define the Beans that are being injected.

That way i get the best of both worlds, i can use Spring XML, Annotations or the just the Setters to Inject the depedency for a testcase (or a different setup, like OSGI + SpringDM or plain Java + Spring for the same Jars) and i keep the definition of the beans that are injected in XML for seperating configuration from the java code.

@Alessandro

You don't lose the "loose coupling" with XML configs only( which is merely a metric for dependencies, ie. depending on a concrete class or just an interface), you loose a bit flexibility since don't you have to recompile code if you changed an XML file, but i doubt that it's done this way very often.

I just love the fact that i can tell from the annotation in the javaclass that something is being injected, at one glance.

Erwin Mueller replied on Fri, 2010/10/01 - 3:03pm

Execuse me, but either you couple your code with Annotations or with XML, it's coupled anyway.

With XML you don't see an import, but you can change Annotations as fast as you can change the XML, if you need to use something different.

The only advantage is, that if you change the XML you don't need to recompile. But you do need to update the product at the client anyway. Either you update the XML files or the Java Jars, does it really makes a difference?

Plus, if you change the XML the client have to update the Jars in the most cases anyway, because you have new code.

I don't see any advantage in using XML, only the disadvatge of the need to update the code in two different places. Also, the difficulties with refactoring and the need of using two different languages.

Suresh Murthy replied on Fri, 2010/10/01 - 10:24pm in response to: Josh Marotti

@Josh, This has been my woe with any annotation based frameworks I have worked with. I don't want them to litter my code. They kinda intrude into my source code and if in future you want to move out of that framework, your source code takes a beating. Hence I am not a big proponent of using annotations until and unless it in the language itself.

Christopher Wong replied on Fri, 2010/10/01 - 10:32pm

I have never felt comfortable with the use of annotations for dependency injection. DI, after all, is one manifestation of Inversion of Control. The class does not specify where it gets its dependencies. It does not worry where they come from. They are magically injected. Moreover, Spring is all about POJOs. The ideology is that you write plain Java classes with no dependency on specific interfaces or frameworks. Annotation-based DI subverts all that. 

When you put an annotation in your plain Java code -- @Autowired or @Inject -- two things have changed:

  • Your class now contains instructions on where it gets its dependencies. They can be pretty detailed instructions if you use qualifiers. These annotations effectively pull in dependencies. You have now inverted your inversion of control. Bye bye IoC. 
  • Your class just sucked in a dependency on an external framework. It doesn't matter that it's @annotation: effectively, it functions like code.

JavaConfig and the original XML configuration does not fall into this trap. They keep all dependency configuration and injection logic out of your POJOs, keeping them clean. Your POJOs are absolutely unaware of the XML or Java injection code. That is where the decoupling happens. If some day you decide to toss Spring and wire up everything "by hand" (Java), you won't need to change a single line of code in your original POJOs. They are pure. By contrast, the annotations approach litters your code with crap that requires you keep those annotation jars around just to compile.

For the sake of completeness I will acknowledge that Spring now supports JSR 330, the javax.inject annotation standard. But this is still a JEE standard, so your annotated code would still be pulling in jar dependencies external to Java SE.

Zqudlyba Navis replied on Fri, 2010/10/01 - 11:37pm

It is very common to see a java class file to contain 80% annotations and 20% java code that actually does something. Ever seen Spring Roo generated java files ?

Liam Knox replied on Fri, 2010/10/01 - 11:57pm

Personally having used XML and Springs @Configuration and @Bean I can see absolutley no requirement for XML. I can see requirements for property substitution but what does configuring actual Java classes in a language other than Java actually give you?

In the counter argument I can state compile safety, type safetly, ease of navigation, natural refactoring etc. etc. I think basically XML became the default configuration mechanism due to lack on annotations but Guice and Springs adoption of annotations is a great evolutionary move in this domain.

Libor Šubčík replied on Sun, 2010/10/03 - 7:43am

@Liam

"I can see absolutley no requirement for XML ..."

I have worked on several projects where the same code base was deployed on multiple enviroments. The most often case has been intranet and internet (/extranet) deployments with slight differneces in security, a set of accessed data and so on. This things were usually solved as a set of aspects and multiple implementations of some of interfaces and the bean wiring set up in the environment specific xml configuration.

I admit that not every project needs this. Another important thing about xml configuration for me is that I can see all the wiring in one place and check that nothing gets out of hand. But fortunatly there are tools available (Eclipse Spring IDE) that can show both xml and annotation config together in one dependency graph. This is why I probably give it a try.

Wujek Srujek replied on Sun, 2010/10/03 - 3:57pm in response to: Libor Šubčík

JavaConfig is not about annotations all over the code, as your post suggests - it is a single (or a set) of @Configuration annotated classes that have methods that provide the bean definitions and are also factories for the beans themselves. It's actually pretty neat. It works pretty much the same way as Google Guice modules. What this means is: 1. your code in the business logic can be completely annotation-free 2. you still can have the configuration in one place, or you can have it in multiple classes logically connected 3. you can read the configuration easily, navigate the graph easily and so on - it is Java code, something that millions programmers will understand easily; there is no need (for new users, the mastahs don't have any problems with verbose XML, right?) to learn all the XML elements.

I did a small experiment with my little application in Guice (using only modules and producers, without its annotations) - it was enought for me to replace literally one class with the bindings, and the whole app was managed by a cimpletely different container! Aggreed, the application was not the most complex one, but it is still compelling.

Now compare it to CDI (jsr 299) and it completey decentralized binding model - every class is literally littered with annotations, qualifiers, scopes, and so on - how difficult it is to really know what is going on? I read that CDI will also support Guice-style configuration in a maintanance release, which is really cool.

Mwanji Ezana replied on Mon, 2010/10/04 - 4:37am in response to: Libor Šubčík

I have worked on several projects where the same code base was deployed on multiple enviroments. The most often case has been intranet and internet (/extranet) deployments with slight differneces in security, a set of accessed data and so on. This things were usually solved as a set of aspects and multiple implementations of some of interfaces and the bean wiring set up in the environment specific xml configuration.
Guice does not use XML, and yet it is easy to support multiple configurations: each environment has its own context definition. At build-time, the environment is passed in and the corresponding configuration is written to, in Guice's case, the web.xml.

Wujek Srujek replied on Sun, 2010/10/03 - 4:46pm

So you are saying that Guice is only about webapps (web.xml would suggest that)?

Liam Knox replied on Sun, 2010/10/03 - 5:57pm in response to: Libor Šubčík

The fundamental point here is there is nothing you are refering to that needs or indeed benefits from XML. Using JavaConfig I can support wiring per environment, per anything.

I think people are misunderstanding @Autowired and @Configuration. JavaConfig i.e. @Configuration, is about defining application contexts in code, not about magical bindings

In counter to your statement of wiring in one place, now the code is doing the wiring, it is type safe, navigatable in the IDE etc. And it is in one place

If you look at this also from a higher level, what is XML? It is simply data mixed with meta data. It is useless in defining behaviour or its own validation semantics. It is useless in enforcing types. I kind of feel sorry for the people who wrote Spring IDE as basically they have implemented a good tool based on a bad/legacy choice of configuration language.

Mwanji Ezana replied on Mon, 2010/10/04 - 4:36am in response to: Wujek Srujek

"So you are saying that Guice is only about webapps (web.xml would suggest that)?"

No, you could do the same thing from any application entry point. As Liam and Erwin have pointed out, XML has almost no advantage and a number of disadvantages.

With the current version Guice, you can have as little as one annotation per class. In the next version, I believe you'll be able to have none at all. And in the real world, when changing or removing a DI container, I doubt that the biggest pain point is going to be removing annotations from the code.

Libor Šubčík replied on Mon, 2010/10/04 - 5:28am in response to: Liam Knox

Sorry to mix up @Configuration type of config with @Autowired/@Resource annotations. @Configuration really solves the configuration per environment problem.

What do I mean by seeing configuration in one place is not one big xml config file. Imagine you have got an application with several modules, every module has several config files. This is when Spring IDE comes to play and gather all config info (from xml and annotations) into one bean explorer and can generate overall dependency graph.This is very handy when you there are lots of people working on the project and you want to check that nothing goes wrong in a design of the application.

Both xml and java spring config is easy to write (type safe auto-complete) and navigate (with proper tooling). I got used to writing xml configuration but I am open to @Configuration style if it brings some benefit to the application. I can imagine they can both work together. Reasons why I would choose one or another: 

xml - better tools, wide config options (property placeholders, namespaces), does not have to be on classpath (can be reloaded)

@Configuration - refactoring, more lightweight for smaller apps

 Maybe you could help me to find more pros for @Configuration style since I am not familiar with it.

Martijn Verburg replied on Mon, 2010/10/04 - 8:40am in response to: Christopher Wong

My understanding was that JSR-330 was aimed at Java SE, so no need to pull in JEE libs?  I think JSR-299 is seen as the JEE extension to JSR-330 (ignoring the politics)

Josh Marotti replied on Mon, 2010/10/04 - 2:35pm in response to: Erwin Mueller

Execuse me, but either you couple your code with Annotations or with XML, it's coupled anyway.

 

I don't follow?

How is using XML forcing coupling of your code?  It is an external file.  If I reuse the class in some other project, the XML does NOT have to come with.  I just set the beans by hand.  No coupling.

If I use a spring annotation, when I try to reuse the class, the class is broken at compile time because of the annotation import unless I import the spring jar.  That's tight coupling at its finest.

I'm guessing there is either a semantic difference you are using, or I'm not understanding what you mean by XML configuration is coupling your code to the spring framework?

Remember, coupling isn't bad for changes; coupling is bad for reuse!

Alexander Radzin replied on Mon, 2010/10/04 - 4:40pm

I think that serious advantage of external XML configuration is ability to use multiple configurations without changing even one character of java source code and even without re-compilation. I used it for unit testing. I created various subsets of system taking one or two real bean and mocking its neighborhood. I do not know a way to do this using annotations.

Witold Szczerba replied on Mon, 2010/10/04 - 6:49pm in response to: Mwanji Ezana

With the current version Guice, you can have as little as one annotation per class. In the next version, I believe you'll be able to have none at all. And in the real world, when changing or removing a DI container, I doubt that the biggest pain point is going to be removing annotations from the code.

This is not true.

Since the very beginning of Guice - one could wire entire application without adding any single annotation to application code. It is just so unconvinient, because without annotations __all__ the bindings are to be configured explicitly - which will make Guice configuration module looks like Spring's XML file(s) (although written in Java).

And for all those from anti-annotations camp: how is adding _semantic_ annotations into the code reverse the inversion of control? I just do not get it:

public class Car {
  @Inject
  public Car(Engine engine) {
    this.engine=engine;
  }
}

How is that annotation, by any means, reverse the inversion of control? This is just a semantic information. It says nothing more than: let "them" provide me the requested Engine _here_ - in the constructor. Since this is how you made that class working - the information should be anywhere but here - because the way this class works depends on the fact that engine is injected here.

And if you really do not like to import annotations from external libraries - you can always provide your own @Inject and say Guice to treat @my.company.Inject as @com.google.inject.Inject - so your classes do not depend on Guice any more.

Of course - as I said before - one can still wire everything without annotating classes - but that makes your configuration modules huge as spring XML files because everything would have to be configured manually. Not to mention that explicit wiring is a subject for constant updates when you change your classes - at least Guice module will fail to compile, so one won't discover exceeptions late at runtime but just after the change.

 

Christopher Wong replied on Mon, 2010/10/04 - 9:08pm in response to: Witold Szczerba

 

 How is that annotation, by any means, reverse the inversion of control?

 

I consider annotation-based injection to be the inversion of inversion of control simply because you are now including dependency information in the class. IoC means the class should not worry about where it gets its dependencies. But JSR 330 and Spring annotations all have qualifiers that embed information about the dependencies. Pretty soon the information about dependencies overwhelms the actual dependency itself:

@Inject

@MyCustomDependencyInjectionAnnotation

@RequestScoped

@Named("foo")

A a;

It's pointless trying to brush this off as "semantic information". They have all the downsides of non-IoC code:

  • This is unnecessary code: the dependent code does not need this logic to work. You clutter up the dependent class with logic about dependencies.
  • They are functionally real code: the annotations really control what ultimately gets there.
  • They are embedded code: this DI logic travels with the class. You cannot inject an arbitrarily different dependency in a different context without bypassing the DI container.

 

 

Liam Knox replied on Tue, 2010/10/05 - 1:01am in response to: Libor Šubčík

You have property name placeholders in JavaConfig. You also have type safeness, which you dont XML. You have compile safety and natural IDE navigation. You have a far more powerful way in expressing some derived dependency as you are in Java

Sure you can sort of can rely on Spring IDE to help in this with XML but I would question why? Certainly the derivation of value is far more natural not fudged into some static method that you then cludge a call to using XML

Also the classpath leads to one fundamental issue. Spring IDE relies on it to be able to validate anyway, so by ignoring this need you may aswell not use Spring IDE

I still dont see the argument on several files as by using @Import you are effectively doing the same, yet you have again natural IDE navigation.

Mladen Girazovski replied on Tue, 2010/10/05 - 6:05am

I consider annotation-based injection to be the inversion of inversion of control simply because you are now including dependency information in the class. IoC means the class should not worry about where it gets its dependencies.

 I disagree.

First, IoC is just a charecteristic of any Framework.

Second, with Annotations (i prefer @Resource) the class still doesn't need to know where it's depndencies comes from, since it is defined in XML, or another Class usingAnnotations again.

 I can see pro and contra of both apporaches, i already explained why i mix them, no approach is wrong by definition , they are all valid.

 This could turn into something like the attributes vs. elements argument of XML....

Dimitris Menounos replied on Wed, 2010/10/06 - 3:11am

XML for the data layer (daos and services). Annotations for the MVC layer.

James Baxter replied on Wed, 2010/10/06 - 7:05am in response to: Dimitris Menounos

XML for the data layer (daos and services). Annotations for the MVC layer.
I also divide my configuration along these lines.

Slava Lo replied on Thu, 2010/10/14 - 7:17am

With use of xml, you can mix and match different spring context files for particular case, such as defining sprign context for your web app in web.xml or wiring up a test context for your integration test.

 Is it possible to achieve the same result using @Configuration classes ?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.