Thread-safety of calling @Bean methods from returned annonymous inner classes
Is the following test method thread-safe, assuming that this is being called from multiple threads? Sometimes the println statement displays "null"
Code:
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import com.oanda.bi.rm.test.AnnotationConfigTest.Config;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { Config.class }, loader = AnnotationConfigContextLoader.class)
public class AnnotationConfigTest {
@Resource
Map<String, Value> map;
@Test
public void test() throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool( 10 );
for ( int i = 0; i < 10; i++ ) {
service.execute( new Runnable() {
@Override
public void run() {
// Is this thread-safe?
Value value = map.get( "value" );
// Sometimes null!
System.out.println( value.x );
}
} );
}
service.shutdown();
service.awaitTermination( 1, TimeUnit.MINUTES );
}
public static class Value {
@Resource
protected Integer x;
}
@Configuration
public static class Config {
@Bean
public Integer x() {
return 1;
}
@Bean
@Scope("prototype")
public Value value() {
return new Value();
}
@Bean
@SuppressWarnings("serial")
public Map<String, Value> map() {
// Return a Spring agnostic "bean factory" map
return Collections.unmodifiableMap( new HashMap<String, Value>() {
@Override
public Value get( Object obj ) {
String key = (String) obj;
if ( key.equals( "value" ) ) {
// Create new bean on demand
return value();
}
// Assume other similar branches here...
return null;
}
} );
}
}
}