Spring Puzzlers #02: The Happy Traveler

I really love traveling, and even more when I don’t know what my next destination will be. That’s one of my biggest passions, I have to admit it. If you also love traveling, you should consider using my TravelService for your next trip. Let me introduce you the second Spring Puzzler:

The TravelService will be our entry point. It has a method to print a destination picked by a DestinationPicker (shown below). Notice that the method is annotated with @Async to run it asynchronously in another thread:

public class TravelServiceImpl implements TravelService {
	private Logger logger = Logger.getLogger(TravelServiceImpl.class);
	
	private DestinationPicker destinationPicker;
	
	@Async
	public void printNextDestination() {
		logger.info("Running from thread: " + Thread.currentThread().getId());
		
		System.out.println("Your next holiday destination: " + 
							destinationPicker.getDestination());
	}

	public void setDestinationPicker(DestinationPicker destinationPicker) {
		this.destinationPicker = destinationPicker;
	}
}

This is the RandomDestinationPicker, which uses a really complex algorithm to choose the destination from a list of available destinations :). It uses the id field (increased in every object creation) to determine the location:

public class RandomDestinationPicker implements DestinationPicker {
	
	private static int instances = 0;
	
	private int id;
	private List<String> availableDestinations;	
	
	public RandomDestinationPicker(List<String> availableDestinations) {
		this.availableDestinations = availableDestinations;
		id = instances++;
	}
	
	public String getDestination() {
		return availableDestinations.get(id % availableDestinations.size());
	}
}

The next XML file has the configuration for our Application Context:
– It defines a list of destinations (a list of strings)
– It defines the DestinationPicker injecting the list of available destination and setting the scope of the bean to ‘puzzle’.
– It defines the TravelService injecting the DestinationPicker.
– It enables the @Async annotation (task:annotation-driven)
– It defines a new scope called ‘puzzle’ which is a thread scope

<?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"
	xmlns:task="http://www.springframework.org/schema/task"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">


	<bean id="travelService" class="com.sergialmar.springpuzzlers.sp02.TravelServiceImpl" 
							 p:destinationPicker-ref="destinationPicker"/>

	<bean id="destinationPicker" class="com.sergialmar.springpuzzlers.sp02.RandomDestinationPicker" 
								  scope="puzzle">
		<constructor-arg ref="destinationList"/>
	</bean>
								  
	<util:list id="destinationList">
		<value>San Francisco</value>
		<value>Kuala Lumpur</value>
		<value>Barcelona</value>
		<value>Mexico City</value>
		<value>Cape Town</value>
	</util:list>
	
	<task:annotation-driven/>

	<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
      <property name="scopes">
          <map>
              <entry key="puzzle">
                  <bean class="org.springframework.context.support.SimpleThreadScope"/>
              </entry>
          </map>
      </property>
  	</bean>
</beans>

The bootstrap class creates the application context and gets the TravelService bean, calling the printNextDestination method 4 times.

public class TravelBootstrap {

	public static void main(String... args) {
		ApplicationContext applicationContext = 
			new ClassPathXmlApplicationContext("com/sergialmar/springpuzzlers/sp02/app-context.xml");
		
		TravelService travelService = 
			applicationContext.getBean(TravelService.class);
		
		travelService.printNextDestination();
		travelService.printNextDestination();
		travelService.printNextDestination();
		travelService.printNextDestination();
	}
}

Time to vote! Which of the following statements is right:

Spring Puzzler #01 Solution

I guess it’s time for the solution of the first Spring Puzzler. I’ve received a total of 79 votes, 35% got it right.

The solution was: Bienvenido a Spring Puzzlers Sergi.

In case you want to download the code, you can find it here: https://github.com/salmar/SpringPuzzlers

Explanation

The first thing to notice is that SpanishWelcomePrinter was not annotated, that means the component scan will never pick it up and there won’t be any SpanishWelcomePrinter in the Application Context. Only one implementation of LocalizedWelcomePrinter will exist, the EnglishWelcomePrinter.

We can now safely discard the NoSuchBeanDefinitionException. But this was not the trap…even if we had the @Named in the SpanishWelcomePrinter, we would have gotten the same output.

The catch was in the ConsoleWelcomeService where we try to inject a static field. Static fields are omitted for dependency injection, in our case we are going to stick with SpanishWelcomePrinter, instantiated with the new operator and no DI will happen. We can discard the possibility to get the message in English now. NullPointerException cannot happen at any point…

The next Spring Puzzler will be published the 13th Oct.

Happy hacking!