Beware of using your own ThreadPoolTaskExecutor and @Autowired dependencies

I just want to share my experience after debugging a bug caused because my own implementation of ThreadPoolTaskExecutor was using @Autowired dependencies and so initializing to early the autowired beans, which caused that @Transactional, @PreAuthorize annotations wasn’t applying its proxies.

I had something like this:


public class MyThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {

@Autowired
SecurityService securityService; // this initializes SecurityService bean too early

@Override
public <T> Future<T> submit(final Callable<T> task) {
securityService.doSomething();
...
...
}
}

 

But it should be something like:

public class MyThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {

@Override
public <T> Future<T> submit(final Callable<T> task) {

// get access through a statically exposed spring context.

ServiceContext.getBean("securityService").doSomething();
...
...
}
}


 


public class ServiceContext implements ApplicationContextAware {

private static ApplicationContext applicationContext;


@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}

/**
* Get the bean from the Spring application context.
*
* @param beanName
* @return
*/
public static Object getBean(String beanName) {
if (applicationContext == null) {
throw new IllegalStateException(
"No Spring web application context found");
}
if (!applicationContext.containsBean(beanName)) {
{
throw new IllegalArgumentException("Spring bean not found: "
+ beanName);
}
}
return applicationContext.getBean(beanName);
}


}

 

It seems to be related to the fact that autowired dependencies (other beans) of beans of type org.springframework.beans.factory.InitializingBean don’t get proxied correctly

 

Leave a Reply

Your email address will not be published. Required fields are marked *