I’ve spent the last two years and a half delivering the official SpringSource courses all over the world and during this time I’ve seen a lot of students coming across unexpected behaviors and wondering why. Based on Josh Bloch’s Java Puzzlers, I’m going to introduce you the Spring Puzzlers, a bunch of puzzlers ranging from Spring configuration gotchas to AOP and dynamic proxy voodoo, transactional enigmas…
So here’s the first one 🙂
Our entry point will be a WelcomeService, a really simple interface with a single method welcome:
public interface WelcomeService { void welcome(String name); }
The implementation uses a LocalizedWelcomePrinter to print the localized message to the console. I’ll be using JSR-330 annotations for the DI :
import javax.inject.Inject; import javax.inject.Named; @Named public class ConsoleWelcomeService implements WelcomeService { @Inject private static LocalizedWelcomePrinter printer = new SpanishWelcomePrinter(); public void welcome(String name) { printer.printWelcome(name); } }
There are 2 implementations of the LocalizedWelcomePrinter (a custom interface), one for Spanish:
public class SpanishWelcomePrinter implements LocalizedWelcomePrinter { public void printWelcome(String name) { System.out.println("Bienvenido a Spring Puzzlers " + name); } }
And one for English. Notice I’m using @Named here to autoregister the component in the application context:
@Named public class EnglishWelcomePrinter implements LocalizedWelcomePrinter { public void printWelcome(String name) { System.out.println("Welcome to Spring Puzzlers " + name); } }
So the configuration is quite straightforward, a single line enabling the component scanning:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.sergialmar.springpuzzlers" /> </beans>
And this is the class that bootstraps the system:
public class WelcomeBootstrap { public static void main(String... args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app-context.xml"); WelcomeService welcomeService = applicationContext.getBean(WelcomeService.class); welcomeService.welcome("Sergi"); } }
So…what will be the output after running this class? Choose the right answer from the below poll!
Yesterday I answered «Welcome to Spring Puzzlers Sergi»
Without reading the javadocs, I asumed that @Named annotation within the type EnglishWelcomePrinter could have some kind of preference.
It seems I was wrong, and SpanishWelcomePrinter instance in the ConsoleWelcomeService’s LocalizedWelcomePrinter attribute applies.
Then, I made some changes in order to see the English localized message, but it didn’t work at first.
I had problems with the LocalizedWelcomePrinter because it’s static. It doesn’t seem a problem according the javadoc, but I had to change it.
Can you comment this issue?
At last it worked with something like that:
@Inject @Named(«English»)
private LocalizedWelcomePrinter printer;// = new SpanishWelcomePrinter();
@Named(«English»)
public class EnglishWelcomePrinter implements LocalizedWelcomePrinter {
Greetings
Javier.
P.S.: actually the first output was:
Exception in thread «main» org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [app-context.xml]…
…
Caused by: java.io.FileNotFoundException: class path resource [app-context.xml] cannot be opened because it does not exist
😀
I created the project in STS using a Spring template that cretaes the context in /META-INF/spring/app-context.xml.
😉
Pingback: Spring Puzzler #01 Solution « Take me to the code above | Sergi Almar blog