It has been said that primary function of a compiler is to expose all of the errors in your otherwise beautiful code. And the purpose of a user is to find all of the bugs in the otherwise flawless code. Likewise, there's nothing more effective in helping find errata in a book than to send it to the printers and unleash it on the masses.
Despite the fact that Spring in Action, 2E went through a rigorous editing cycle and two different tech reviewers, some things still slip through the cracks. Today I've been informed of one such problem and wanted to post the fix for it here so that everyone can see.
Listing 1.9 shows the use of an XmlBeanFactory to load the beans from the knight example. That's fine and it works for everything up until that point. That's because the example up through Listing 1.9 only shows basic dependency injection. But in section 1.4, that changes and we start applying aspects to the example. Unfortunately a bean factory isn't sufficient for AOP; an application context is needed. Even more unfortunate, I failed to make the switch to an application context before going into the AOP examples.
To remedy the situation, I've submitted to Manning the following change to the "Seeing it work" section on page 21:
Seeing it work
In a Spring application, a bean factory loads the bean definitions and wires the beans together. We've already seen an example of how to load a Spring bean factory using XmlBeanFactory in Listing 1.4. We could use the same technique to load the beans for our knight example. But coming up in section 1.4, we're going to apply aspects to the knight example and a BeanFactory just won't do for AOP. So instead, listing 1.9 loads our knightly beans using a Spring application context.
Listing 1.9 Running the knight example*package com.springinaction.chapter01.knight; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class KnightApp { public static void main(String[] args) throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext( "com/springinaction/chapter01/knight/knight.xml"); Knight knight = (Knight) ctx.getBean("knight"); knight.embarkOnQuest(); } }An application context is the bean factory's much more powerful cousin. We'll take a closer look at how an application context compares to a bean factory in section 2.1.2. But for the the purposes of the knight example, suffice it to say that an application context is just another way to load bean definitions into Spring. In this case, I chose to use a ClasspathXmlApplicationContext to load the bean definitions from the root of the application's classpath.
Once the application has a reference to the Knight object, it simply calls the embarkOnQuest() method to kick off the knight's adventure. Notice that this class knows nothing about the quest the knight will take. Again, the only thing that knows which type of quest will be given to the knight is the knight.xml file.
It’s been a lot of fun sending knights on quests using dependency injection, but now let’s see how you can use DI in your real-world enterprise applications.
Of course, it's too late for those printed copies out there, but hopefully publishing it here and on the book's errata page will help clear up the confusion. Again, sorry for any confusion this may have caused.