[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: 6 years, 10 weeks, 6 days 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 Thu Dec 13 01:40:12 UTC 2018 using JIRA 7.9.2#79002-sha1:3bb15b68ecd99a30eb364c4c1a393359bcad6278.