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

@Qualifier resolution fails with Spring Batch parent/child context arrangement [SPR-12191] #16805

Closed
spring-projects-issues opened this issue Sep 14, 2014 · 3 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

Max Hartmann opened SPR-12191 and commented

When I use a GenericContextFactory with a parent context and in the childContext there is a quite simple @Qualifier constellation the startup of the context fails. If I use @Autowired without a qualifier all is fine.

Sample:
AnnotationConfigApplicationContext parentContext = new AnnotationConfigApplicationContext();
parentContext.register(String.class);
parentContext.refresh();
GenericApplicationContextFactory factory = new GenericApplicationContextFactory(ExampleService.class, SubExampleService.class);
factory.setApplicationContext(parentContext);
factory.createApplicationContext();

public class ExampleService {

@Autowired
@Qualifier("subExampleService")
SubExampleService subExampleService;

public String echo(String echo) {
	return subExampleService.echo(echo);
}

}

exception:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'exampleService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: de.codecentric.batch.item.SubExampleService de.codecentric.batch.item.ExampleService.subExampleService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'subExampleService' is defined
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1147)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:633)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.batch.core.configuration.support.GenericApplicationContextFactory$ResourceAnnotationApplicationContext.<init>(GenericApplicationContextFactory.java:209)
at org.springframework.batch.core.configuration.support.GenericApplicationContextFactory.createApplicationContext(GenericApplicationContextFactory.java:68)
at org.springframework.batch.core.configuration.support.AbstractApplicationContextFactory.createApplicationContext(AbstractApplicationContextFactory.java:170)
at de.codecentric.batch.Application.main(Application.java:30)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: de.codecentric.batch.item.SubExampleService de.codecentric.batch.item.ExampleService.subExampleService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'subExampleService' is defined
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
... 14 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'subExampleService' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:575)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1111)
at org.springframework.beans.factory.support.AbstractBeanFactory.getType(AbstractBeanFactory.java:572)
at org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver.checkQualifier(QualifierAnnotationAutowireCandidateResolver.java:249)
at org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver.checkQualifiers(QualifierAnnotationAutowireCandidateResolver.java:183)
at org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver.isAutowireCandidate(QualifierAnnotationAutowireCandidateResolver.java:157)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.isAutowireCandidate(DefaultListableBeanFactory.java:564)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.isAutowireCandidate(DefaultListableBeanFactory.java:531)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:916)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:860)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:775)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489)
... 16 more

thx


Affects: 3.2.10, 4.0.6, 4.1 GA

Backported to: 4.0.8, 3.2.12

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

It's still not clear to me how the algorithm can run into a scenario where it is trying to check the type of a non-existing bean definition in the current factory... It seems to be rather specific to Spring Batch's setup there.

That said, due to the decoupled SPI arrangement, it doesn't hurt to make QualifierAnnotationAutowireCandidateResolver more defensive and simply catch and swallow a NoSuchBeanDefinitionException from BeanFactory.getType - for 4.1.2, 4.0.8 and 3.2.12.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Max Hartmann commented

it works with the last snapshot ;-) "defense wins championships"
thx
Max

@spring-projects-issues
Copy link
Collaborator Author

Mark Ingram commented

A workaround for those unable to update Spring versions:

   private static class GenericApplicationContextFactoryEx extends GenericApplicationContextFactory
    {
        public GenericApplicationContextFactoryEx(Class<?> configurationClass) {
            super(configurationClass);
        }

        @Override
        protected void prepareBeanFactory(ConfigurableListableBeanFactory parent, ConfigurableListableBeanFactory beanFactory) {
            super.prepareBeanFactory(parent, beanFactory);
            //avoid reusing the parent contexts autowire resolver to work around SPR-12191
            if (beanFactory instanceof DefaultListableBeanFactory) {
                ((DefaultListableBeanFactory)beanFactory).setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
            }
        }
    }

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) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants