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 status: backported type: bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Sep 14, 2014

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

@spring-projects-issues spring-projects-issues commented Oct 22, 2014

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

@spring-projects-issues spring-projects-issues commented Oct 24, 2014

Max Hartmann commented

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

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Aug 13, 2015

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 status: backported type: bug
Projects
None yet
Development

No branches or pull requests

2 participants