[SPR-9852] @Resource injection of singleton in prototype using AnnotationConfigApplicationContext is not thread-safe Created: 03/Oct/12  Updated: 04/Nov/12  Resolved: 04/Oct/12

Status: Closed
Project: Spring Framework
Component/s: Core:DI
Affects Version/s: 3.1.2
Fix Version/s: 3.1.3, 3.2 RC1

Type: Bug Priority: Critical
Reporter: Bob Tiernay Assignee: Juergen Hoeller
Resolution: Complete Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Relate
relates to SPR-9806 Autowired properties can remain unset... Closed
relates to SPR-9627 Regression: scoped beans being cached... Closed
Reference URL: http://forum.springsource.org/showthread.php?130731-Thread-safety-of-calling-Bean-methods-from-returned-annonymous-inner-classes&p=426403#post426403
Days since last comment: 5 years, 8 weeks, 1 day ago
Last commented by a User: false
Last updater: Chris Beams

 Description   

The attached test case demonstrates that @Resource of injection of singleton in prototype using AnnotationConfigApplicationContext is not thread-safe. However, changing @Resource to @Autowired seems to resolve the issue.

Please see http://stackoverflow.com/questions/12700239/thread-safety-of-calling-bean-methods-from-returned-annonymous-inner-classes/12700284#comment17146235_12700284 for more details

 
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
 
import javax.annotation.Resource;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.pentaho.di.core.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
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.AnnotationCallableConfigTest.Config;
 
/**
 * @see http://stackoverflow.com/questions/12700239/thread-safety-of-calling-bean-methods-from-returned-annonymous-inner-classes/12700284#comment17146235_12700284
 * @see http://forum.springsource.org/showthread.php?130731-Thread-safety-of-calling-Bean-methods-from-returned-annonymous-inner-classes&p=426403#post426403
 * @author btiernay
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { Config.class }, loader = AnnotationConfigContextLoader.class)
public class AnnotationCallableConfigTest {
 
    @Autowired
    Callable<Holder> callable;
 
    @Test
    public void test() throws InterruptedException, ExecutionException {
        final int threads = 10;
        ExecutorService service = Executors.newFixedThreadPool( threads );
 
        List<Future<Holder>> futures = new ArrayList<>();
        for ( int i = 0; i < threads; i++ ) {
            futures.add( service.submit( callable ) );
        }
 
        service.shutdown();
        service.awaitTermination( 1, TimeUnit.MINUTES );
 
        for ( Future<Holder> future : futures ) {
            final Holder holder = future.get();
            Assert.assertNotNull( holder.value );
        }
    }
 
    public static class Holder {
        // Changing this to @Autowired makes the test pass
        @Resource(name = "singleton")
        protected Integer value;
    }
 
    @Configuration
    public static class Config {
 
        @Bean
        public Integer singleton() {
            return 1;
        }
 
        @Bean
        @Scope("prototype")
        public Holder prototype() {
            return new Holder();
        }
 
        @Bean
        public Callable<Holder> function() {
            return new Callable<Holder>() {
                @Override
                public Holder call() {
                    return prototype();
                }
            };
        }
 
    }
}
 



 Comments   
Comment by Juergen Hoeller [ 04/Oct/12 ]

This very much looks like a variation of SPR-9806 and seems to be covered by that fix already. In any case, your test consistently passes for me after that fix.

Juergen

Generated at Fri Nov 24 22:11:47 UTC 2017 using JIRA 6.4.14#64029-sha1:ae256fe0fbb912241490ff1cecfb323ea0905ca5.