Question

I have a very strange problem. I'm using Spring 3.2.4 and have a Spring Java Config class which is part of a larger mix of Java and XML configuration files.

The file uses 6 resources defined in other config files to construct an @Async bean. When I add "implements AsyncConfigurer" to the file, some of the @Resource fields appear as null, but when I leave the implementation off, they are populated. This is confusing, since the AsyncConfigurer is just supposed be used for configuring your asynchronous executor, it shouldn't do anything funky like cause your configuration to be loaded asynchronously.

When I set a debugger on the construction method, I can see that the beans are in fact null. It seems to be a race condition of some kind, because out of the 6 beans, the 4th one was once null, and then populated the next time.

My file looks like:

public class UserBackgroundProcessorConfiguration implements AsyncConfigurer {

    @Resource(name="bean1")
    MyBean bean1;

    // in reality there are 6 @Resources defined...

    @Resource(name="bean6")
    MyBean bean6;

    @Bean(name="backgroundProcessor")
    public BackgroundProcessor getBackgroundProcessor() {
        BackgroundProcessor backgroundProcess = new BackgroundProcessor();
        backgroundProcess.setBean1(bean1);
        // beans 1-3 are always populated
        // bean 4 seems to sometimes be populated, sometimes null
        // beans 5&6 are always null
        backgroundProcess.setBean6(bean6);

        return backgroundProcess;
    }

    @Override
    @Bean(name="executor")
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(40);
        executor.setQueueCapacity(25);
        executor.setThreadNamePrefix("BackgroundProcessor-");
        return executor;
    }
}

Again, when I remove "implements AsyncConfigurer" and comment out getAsyncExecutor, the problem goes away.

According to the documentation

Interface to be implemented by @Configuration classes annotated with @EnableAsync that wish to customize the Executor instance used when processing async method invocations.

So I don't see how that cause the behavior I am seeing.

Was it helpful?

Solution 2

I solved this problem by removing the @Resource annotations from the Java configuration file:

public class UserBackgroundProcessorConfiguration implements AsyncConfigurer {

    @Bean(name="backgroundProcessor")
    public BackgroundProcessor getBackgroundProcessor() {
        BackgroundProcessor backgroundProcess = new BackgroundProcessor();
        return backgroundProcess;
    }

    @Override
    @Bean(name="executor")
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(40);
        executor.setQueueCapacity(25);
        executor.setThreadNamePrefix("BackgroundProcessor-");
        return executor;
    }
}

And then adding @Resource annotations to the BackgroundProcessor class:

public class BackgroundProcessor {
    @Resource private MyBean bean1;
    // 4 more
    @Resource private MyBean bean6;
}

For some reason this works fine. I don't like this as much, because I would prefer my classes not have a dependency on the IOC annotations, but I'll go with this solution for now.

OTHER TIPS

It appears that your backgroundProcessor bean is depending on your 6 resource beans.

Try annotating the method signature with:

@Bean(name="backgroundProcessor")
@DependsOn("bean1","bean2","bean3","bean4","bean5","bean6")
public BackgroundProcessor getBackgroundProcessor() {..}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top