Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AsyncConfigurer implementations are loaded too early #27808

Closed
ipavkovic opened this issue Dec 13, 2021 · 2 comments
Closed

AsyncConfigurer implementations are loaded too early #27808

ipavkovic opened this issue Dec 13, 2021 · 2 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Milestone

Comments

@ipavkovic
Copy link

Affects: 5.3.3

We use an AsyncConfigurer that needs some beans. Spring wants to create a BeanPostProcessor asyncAdvisor at
org.springframework.scheduling.annotation.ProxyAsyncConfiguration. This bean post processor uses the instance variables this.executor and this.exceptionHandler

all AsyncConfigurer are autowired to ProxyAsyncConfiguration via the following method

org.springframework.scheduling.annotation.AbstractAsyncConfiguration

	@Autowired(required = false)
	void setConfigurers(Collection<AsyncConfigurer> configurers) {
		if (CollectionUtils.isEmpty(configurers)) {
			return;
		}
		if (configurers.size() > 1) {
			throw new IllegalStateException("Only one AsyncConfigurer may exist");
		}
		AsyncConfigurer configurer = configurers.iterator().next();
		this.executor = configurer::getAsyncExecutor;
		this.exceptionHandler = configurer::getAsyncUncaughtExceptionHandler;
	}

This leads to a prelimary instance creation of all asyncConfigurer and its dependent beans.

IMHO this should be changed to use an ObjectProvider instead:

    protected ObjectProvider<AsyncConfigurer> configurersProvider;

    @Autowired(required = false)
    void setConfigurers(ObjectProvider<AsyncConfigurer> configurers) {
        this.configurersProvider = configurers;
    }

    protected void evaluateAsyncConfigurer() {
        List<AsyncConfigurer> configurers = configurersProvider.orderedStream().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(configurers)) {
            return;
        }
        if (configurers.size() > 1) {
            throw new IllegalStateException("Only one AsyncConfigurer may exist");
        }
        AsyncConfigurer configurer = configurers.iterator().next();
        this.executor = configurer::getAsyncExecutor;
        this.exceptionHandler = configurer::getAsyncUncaughtExceptionHandler;
    }

method evaluateAsyncConfigurer() should be called before access to this.executor and this.exceptionHandler in child classes.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Dec 13, 2021
@snicoll snicoll self-assigned this Dec 13, 2021
@snicoll snicoll changed the title AbstractAsyncConfiguration -> prelimary instance creation before method call setConfigurers(Collection<AsyncConfigurer> configurers) AsyncConfigurer implementations are loaded too early Dec 14, 2021
@snicoll snicoll added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Dec 14, 2021
@snicoll snicoll added this to the 6.0.x milestone Dec 14, 2021
@snicoll
Copy link
Member

snicoll commented Dec 14, 2021

Thanks for the report, this is similar to #27751 for which I am working on a fix.

@ipavkovic
Copy link
Author

@snicoll ah, did not find that issue before, thanks for your feedback 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

3 participants