Skip to content

@Resource injection of singleton in prototype using AnnotationConfigApplicationContext is not thread-safe [SPR-9852] #14485

@spring-projects-issues

Description

@spring-projects-issues

Bob Tiernay opened SPR-9852 and commented

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();
                }
            };
        }

    }
}

Affects: 3.1.2

Reference URL: http://forum.springsource.org/showthread.php?130731-Thread-safety-of-calling-Bean-methods-from-returned-annonymous-inner-classes&p=426403#post426403

Issue Links:

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions