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

@Valid annotation can't establish dependency relationship between beans #29730

Closed
uphy opened this issue Dec 22, 2022 · 7 comments
Closed

@Valid annotation can't establish dependency relationship between beans #29730

uphy opened this issue Dec 22, 2022 · 7 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@uphy
Copy link

uphy commented Dec 22, 2022

We can't call @Validated bean's method on application shutdown because defaultValidator bean is destroyed first even though we are referring it.

Sample Application

  • MyBean with @Validated depends on defaultValidator implicitly through MethodValidationInterceptor
  • MyService depends on MyBean
  • MyService takes a while to destroy and it calls MyBean at last
  • But the call fails due to BeanCreationNotAllowedException
package com.example.demo;

import javax.annotation.PreDestroy;

import org.springframework.beans.factory.BeanCreationNotAllowedException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Service
    static class MyService {
        private final MyBean myBean;

        MyService(MyBean myBean) {
            this.myBean = myBean;
        }

        @PreDestroy
        void destroy() {
            System.out.println("MyService.destroy");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            try {
                myBean.method();
            } catch (BeanCreationNotAllowedException ex) {
                // This is thrown because defaultValidator has already been closed.
                ex.printStackTrace();
            }
        }

    }

    @Component
    @Validated
    // This is a workaround for this issue:
    // @DependsOn("defaultValidator")
    static class MyBean {

        void method() {
            System.out.println("MyBean.method");
        }

        @PreDestroy
        void destroy() {
            System.out.println("MyBean.destroy");
        }
    }

}

See the following link for the complete demo app code:
https://github.com/uphy/20231010_BeanCreationNotAllowedExceptionDemo

Workaround

  • Add @DependsOn("defaultValidator") to MyBean
  • Add @ConfigurationProperties annotation to MyBean (ref spring-projects/spring-boot@f60f3cb)
  • Use MethodValidationExcludeFilter to exclude method validation from MyBean

Environment

  • Spring Boot 2.7.6
  • Java 11
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Dec 22, 2022
@bclozel bclozel transferred this issue from spring-projects/spring-boot Dec 22, 2022
@sbrannen sbrannen added the in: core Issues in core modules (aop, beans, core, context, expression) label Jan 31, 2023
@sbrannen sbrannen changed the title BeanCreationNotAllowedException thrown on application shutdown BeanCreationNotAllowedException thrown on application shutdown when invoking @Validated bean method Jan 31, 2023
@vishalsingh2972
Copy link

@uphy @sbrannen can you assign this to me if it's still open ?

@uphy
Copy link
Author

uphy commented Apr 17, 2023

@vishalsingh2972 Thank you! I am not authorized to assign, so I will wait for @sbrannen's response.

@snicoll
Copy link
Member

snicoll commented Oct 5, 2023

@vishalsingh2972 thanks for the offer but we haven't triaged the issue yet so nobody can really work on it really. Except if you've found what the issue was?

@snicoll
Copy link
Member

snicoll commented Oct 5, 2023

@uphy I can't reproduce the issue that you have described. Both with framework 5.3 and 6.x, the shutdown is initiated with the sleep there and it ends up with:

2023-10-05 16:22:08.799  INFO 22703 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 0.558 seconds (JVM running for 0.744)
MyService.destroy
MyBean.method
MyBean.destroy

Going forward, please share a sample that we can run rather than code in text that we'll have to copy/paste anyway in a project to be able to investigate. You can do that by attaching a zip to the issue or sharing a link to a GitHub repository with the code.

I am going to close this but we can reopen if you manage to reproduce. Please provide more instructions in that case.

@snicoll snicoll closed this as not planned Won't fix, can't repro, duplicate, stale Oct 5, 2023
@snicoll snicoll added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Oct 5, 2023
@uphy
Copy link
Author

uphy commented Oct 10, 2023

@snicoll Thank you for checking. I could reproduce the issue again with latest environment.

See the following link for the complete demo project:
https://github.com/uphy/20231010_BeanCreationNotAllowedExceptionDemo

Could you reopen this issue?

@snicoll snicoll reopened this Oct 10, 2023
@snicoll snicoll self-assigned this Oct 10, 2023
@snicoll snicoll added status: waiting-for-triage An issue we've not yet triaged or decided on and removed status: invalid An issue that we don't feel is valid labels Oct 10, 2023
@snicoll snicoll changed the title BeanCreationNotAllowedException thrown on application shutdown when invoking @Validated bean method @Valid annotation can't establish dependency relationship between beans Oct 12, 2023
@snicoll snicoll added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Oct 12, 2023
@snicoll snicoll added this to the 6.2.x milestone Oct 12, 2023
@snicoll snicoll added in: core Issues in core modules (aop, beans, core, context, expression) and removed in: core Issues in core modules (aop, beans, core, context, expression) labels Oct 12, 2023
@snicoll
Copy link
Member

snicoll commented Oct 12, 2023

Thanks, I've reproduced it now. This is similar to #22526

@snicoll snicoll removed their assignment Oct 12, 2023
@jhoeller jhoeller self-assigned this Mar 1, 2024
@jhoeller
Copy link
Contributor

jhoeller commented Mar 4, 2024

As of 6.2, we leniently tolerate late retrieval of existing instances during destroySingletons(), making late bean interactions possible during destroy method invocations even for retrievals from an on-demand supplier or async worker etc. After all, such late interactions were already possible for bean instances that got stored directly, and late retrieval was possible for beans without destroy methods (even if they were part of a depends-on arrangement in the other direction), so we may also tolerate interactions when retrieved on demand now: typically for validators and transaction managers, late-bound and/or potentially late-qualified.

@jhoeller jhoeller modified the milestones: 6.2.x, 6.2.0-M1 Mar 4, 2024
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: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

6 participants