Skip to content

Auto-proxy creation should not consider GroovyObject as a user-specified interface [SPR-11715] #16337

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

Closed
spring-projects-issues opened this issue Apr 21, 2014 · 7 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Apr 21, 2014

Abhijit Sarkar opened SPR-11715 and commented

Groovy application with JSR-303 bean validation. Configured MethodValidationPostProcessor and LocalValidatorFactoryBean in groovy beans along with other beans. Application fails to start due to DI failure for beans using JSR-303 validation.
Relevant classes below. Actually using 4.0.4.BUILD-SNAPSHOT but JIRA won't let me choose that.

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private name.abhijitsarkar.moviedatabase.service.rip.MovieRipService name.abhijitsarkar.moviedatabase.service.facade.MovieFacade.movieRipService; nested exception is java.lang.IllegalArgumentException: Can not set name.abhijitsarkar.moviedatabase.service.rip.MovieRipService field name.abhijitsarkar.moviedatabase.service.facade.MovieFacade.movieRipService to com.sun.proxy.$Proxy50
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
	... 31 more

service-config.groovy

beans {
    ...
    validator(LocalValidatorFactoryBean)

    methodValidationPostProcessor(MethodValidationPostProcessor) {
        validator = ref('validator')
    }
}

MovieRipService.groovy

@Service
@Validated
class MovieRipService {
    ...
    Collection<MovieRip> getMovieRips(
            @ValidDirectory(message = 'Movie directory is not valid.') String movieDirectory) {
    ...
    }

MovieFacade.groovy

@Service
class MovieFacade {
    @Autowired
    MovieRipService movieRipService

Affects: 3.2.8, 4.0.3

Issue Links:

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

This looks like a proxy type mismatch, probably caused by your MethodValidationPostProcessor creating an interface proxy (for whatever interface it seems to detect here - could be an implicit Groovy interface)...

Does it help to call setProxyTargetClass(true) on your MethodValidationPostProcessor bean?

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

After some quick review here, it does seem like the presence of the GroovyObject interface on a Groovy bean class makes AbstractAdvisingBeanPostProcessor choose interface proxies - in that case, a proxy that just implements the GroovyObject interface :-(

In any case, setProxyTargetClass(true) should solve the immediate problem here. If it does, I'll turn this issue into a general AbstractAutoProxyCreator / AbstractAdvisingBeanPostProcessor enhancement to be smarter about GroovyObject there, not considering it as a user-specified interface and therefore choosing target-class proxies automatically if GroovyObject is the only interface being implemented.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Oliver Drotbohm commented

This seems to be a general issue with the eligibility check in AbstractAdvisingBeanPostProcessor as it checks bean target class for eligibility which might be a proxy target type only. In case the proxy interface implements additional interfaces, methods on these interfaces are not considered during the matching against the registered pointcuts. Also discoverable in Spring 3.2.x releases.

@spring-projects-issues
Copy link
Collaborator Author

Abhijit Sarkar commented

setProxyTargetClass(true) or it's Groovy equivalent proxyTargetClass = true does solve the issue. Since I shouldn't have to do this, making AbstractAdvisingBeanPostProcessor smarter about the Groovy interfaces seems like the way to go.

@spring-projects-issues
Copy link
Collaborator Author

Abhijit Sarkar commented

Instead of targeting the GroovyObject interface specifically, I'd suggest ignoring any interface in the groovy.lang package.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Actually, since there are a few strategy interfaces in groovy.lang as well, I'm rather inclined to target GroovyObject specifically indeed...

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

AbstractAutoProxyCreator and AbstractAdvisingBeanPostProcessor consistently don't consider configuration callbacks and internal language interfaces as reasonable proxy interfaces now, through reusing the evaluateProxyInterfaces algorithm from a new common ProxyProcessorSupport base class. This includes exclusion of the GroovyObject interface; to be extended for any further well-known language interfaces that are just meant for internal use.

Juergen

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

2 participants