Spring Basics: Wiring Beans with XML Configuration

If you have to work with legacy Spring applications, chances are you will have know how XML-based configuration works. Although Java configuration is preferred for new applications, sometimes you just don’t have a choice.

This would wire a bean with the id running that is of type Running (which is a Habit). You can see why this is much more of a hassle to set up than using a simple @Component annotation on a class or a @Bean annotation in a @Configuration class. Those XML namespaces are nasty, but luckily most IDEs will help you with them.

Injecting Beans

To inject dependencies, we have two choices:

Constructor injection

Setter injection

Unlike with Java configuration, we cannot insert into fields when using XML-based configuration.

Constructor Injection

Suppose we want to insert one bean into another bean, for instance a HabitRepository that persists habits to the database into a HabitService. By using the <constructor-arg /> element and the ref property, we can accomplish this:

If we wanted to pass more arguments to the HabitService constructor, we must keep on eye on the order: it must be the same as the order in which they are declared in the class.

To ease working with constructor arguments and as a way to curtail the verbosity of the XML configuration, Spring offers the c XML namespace to help wire beans without the need to create a sub-element <constructor-arg />:

We define a bean of type java.time.LocalDate and we use the static factory method now() to get an instance of it. We then use the c namespace to pass it to the constructor of our PositiveStreak bean. c:startTime-ref="currentTime" should be read as: pass the reference to the bean with id currentTime to the constructor argument that has the name startTime.

So we can reference constructor arguments by name. We can also reference them by position. c:_0-ref="currentTime" would do the exact same thing. XML does not allow a digit as the first character of an attribute, so we have to use an underscore. If there is only a single argument to the constructor, we can even use the shorthand c:_-ref="currentTime". I would not want to promote this as readable, but it’s good to know it exists and might be used in the wild.

The <property> element has an attribute name that refers to the field name of the bean being set. In the current case, class Running has a field named streaks. As a child element of <property> we define a list of Streak references.

The usage of the p namespace is a lot like that of the c namespace. In this case, p:streaks-ref="streak" tells spring to wire a property named streaks with the bean that is referenced by the id streak. Now, the property streaks takes a List. If we pass only a single element to that list, the current syntax works and Spring will happily insert the single reference to streak into a List for us and pass that to the setter method. If we want to pass more than one element in a list, however, we have to create the list separately first, and then pass the id of that reference to the p property:

We need to add the util namespace and the location of the util schema definition to get this to work. You see that the XML becomes quite verbose the more you try to do with it. The util namespace allows us to create collections of literal values or beans. These collections can then be referenced by their id.

spring-test contains the SpringRunner JUnit runner, and the @ContextConfiguration that will tell Spring where to look for the application context that contains the beans that need to be wired. In this case, we tell it to look at the applicationContext.xml that we put in src/main/resources, so we can reference it by looking at the root of our classpath with the attribute locations = "classpath:applicationContext.xml".