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!

Spring Puzzler #01: Welcome

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!

Extending handler method argument resolution in Spring MVC

Spring MVC data binding is really flexible and powerful, it can bind request parameters, URI templates variables, cookie values, HTTP headers… directly into your domain objects, but what if you want a custom resolution mechanism?

I will show you how to do it with a simple example. Imagine you want to get the user country name directly in you controller. The handler method I want to have looks like the following:

@RequestMapping(value="/", method=RequestMethod.GET)
public String home(@Country String userCountry, Model model) {
    ...
}

Notice that we have a new annotation called @Country, this is our custom annotation that we are gonna use to know where to inject the country name. Let’s create the annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Country {
}

Don’t forget to set the retention to runtime, otherwise the annotation won’t be available. Now it’s time to define how we want to resolve the argument annotated with @Country. The HandlerAdapter takes care of this resolution but it delegates to the WebArgumentResolvers for this task. We’ll implement our custom WebArgumentResolver:

public class CountryWebArgumentResolver implements WebArgumentResolver {

    private static final String WS_URL = 
        "http://api.ipinfodb.com/v3/ip-city/?key={apiKey}&ip={userIp}&format=xml";
    private static final String API_KEY = "yourKey";
	
    private RestTemplate restTemplate = new RestTemplate();
	
    public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest nativeWebRequest) throws Exception {
        // Get the annotation		
        Country countryAnnotation = 
            methodParameter.getParameterAnnotation(Country.class);

        if(countryAnnotation != null) {
            HttpServletRequest request = 
                (HttpServletRequest) nativeWebRequest.getNativeRequest();
			
            // Get user IP
            String userIp = request.getRemoteAddr();
			
            // Call geolocalization web service
            HttpHeaders requestHeaders = new HttpHeaders();
            requestHeaders.set("Accept", "text/xml");

            HttpEntity<UserInfo> userInfo = restTemplate.exchange(WS_URL, HttpMethod.GET, new HttpEntity<UserInfo>(requestHeaders), UserInfo.class, API_KEY, userIp);

            return userInfo.getBody().getCountryName();
        }
		
        return UNRESOLVED;
    }
}

As you can see, it’s quite straightforward, we just need to implement a single method. What this resolver is doing, is basically checking if the parameter is annotated with @Country, getting the user IP and calling a web service to get geolocalization data of the user IP (notice that an extra class has been created, UserInfo, in order to bind the web service parameters). I’ll be using IPInfoDB as the geolocalization service.

We just have one step left: define our new resolver in the handler adapter. Our custom web argument resolver will kick in before any Spring MVC default resolver.

	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
		<property name="customArgumentResolver">
			<bean class="com.sergialmar.customresolver.web.support.CustomWebArgumentResolver"/>
		</property>
	</bean>

Note: if you are using the Spring 3 MVC namespace (

<mvc:annotation-driven/>

), remember to place your handler adapter definition on top of it.

In Spring 3.1, you can user the mvc namespace to register the argument resolver:

	<mvc:annotation-driven>
		<mvc:argument-resolvers>
			<bean class="com.sergialmar.customresolver.web.support.CustomWebArgumentResolver"/>
		</mvc:argument-resolvers>
	</mvc:annotation-driven>

We are now ready to use the @Country annotation in our controller 🙂

	@RequestMapping(value="/", method=RequestMethod.GET)
	public String home(@Country String userCountry, Model model) {
		
		String message = null;
		
		if(userCountry.equals("SPAIN")) {
			message = "It seems you are in the same country as I am, up for a beer?";
		} else {
			message = "It seems we are not close to each other, will let you know when I am in " + userCountry;
		}
		
		model.addAttribute("message", message);
		
		return "home";
	}