Reputation: 126
I'm trying to do simple call to the method
BeanFactoryAnnotationUtils.qualifiedBeanOfType
Here the pom.xml of the project :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>beanfactoryannotationutils.sample</groupId>
<artifactId>BeanFactoryAnnotationUtilsProblem</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.1.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<!-- Spring boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
The Application.java class
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
ListableBeanFactory beanFactory = ctx.getBeanFactory();
// This is working ... (@Autowired with @Qualifier(...) too)
Map<String, QualifiedInterface> qualifiedBeans = beanFactory.getBeansOfType(QualifiedInterface.class);
System.out.println("Existing qualified beans ...");
for (QualifiedInterface qualifiedBean : qualifiedBeans.values()) {
System.out.println(" " + qualifiedBean.toString());
for (Annotation annotation : qualifiedBean.getClass().getAnnotations()) {
System.out.println(" - " + annotation.toString());
}
}
// This is working too ...
Map<String, Object> qualifiedBeansFromCtx = ctx.getBeansWithAnnotation(Qualifier.class);
System.out.println("Existing qualified beans from context ...");
for (Object qualifiedBean : qualifiedBeansFromCtx.values()) {
System.out.println(" " + qualifiedBean.toString());
for (Annotation annotation : qualifiedBean.getClass().getAnnotations()) {
System.out.println(" - " + annotation.toString());
}
}
// This is not ...
QualifiedInterface processor = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
beanFactory, QualifiedInterface.class, "QualifierA");
System.out.println("The selected processor should be A " + processor);
}
}
An interface QualifiedInterface.java
public interface QualifiedInterface {
}
Two beans QualifiedA.java
@Component
@Qualifier("QualifierA")
public class QualifiedA implements QualifiedInterface {
@Override
public String toString() {
return "QualifiedA";
}
}
and QualifiedB.java :
@Component
@Qualifier("QualifierB")
public class QualifiedB implements QualifiedInterface {
@Override
public String toString() {
return "QualifiedB";
}
}
The whole in the same package and application, now run it :
2015-12-24 15:08:34.468 INFO 9524 --- [ main] l.p.e.b.Application : Starting Application on DTBE-DEV4 with PID 9524 (D:\Workspace_netbeans\BeanFactoryAnnotationUtilsProblem\target\classes started by eguenichon in D:\Workspace_netbeans\BeanFactoryAnnotationUtilsProblem)
2015-12-24 15:08:34.478 INFO 9524 --- [ main] l.p.e.b.Application : No profiles are active
2015-12-24 15:08:34.618 INFO 9524 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@11e18e8c: startup date [Thu Dec 24 15:08:34 CET 2015]; root of context hierarchy
2015-12-24 15:08:37.516 INFO 9524 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2015-12-24 15:08:37.524 INFO 9524 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0
2015-12-24 15:08:37.672 INFO 9524 --- [ main] l.p.e.b.Application : Started Application in 3.715 seconds (JVM running for 4.355)
Existing qualified beans ...
QualifiedA
- @org.springframework.stereotype.Component(value=)
- @org.springframework.beans.factory.annotation.Qualifier(value=QualifierA)
QualifiedB
- @org.springframework.stereotype.Component(value=)
- @org.springframework.beans.factory.annotation.Qualifier(value=QualifierB)
Existing qualified beans from context ...
QualifiedA
- @org.springframework.stereotype.Component(value=)
- @org.springframework.beans.factory.annotation.Qualifier(value=QualifierA)
QualifiedB
- @org.springframework.stereotype.Component(value=)
- @org.springframework.beans.factory.annotation.Qualifier(value=QualifierB)
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'QualifierA' is defined: No matching QualifiedInterface bean found for qualifier 'QualifierA' - neither qualifier match nor bean name match!
at org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils.qualifiedBeanOfType(BeanFactoryAnnotationUtils.java:100)
at org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils.qualifiedBeanOfType(BeanFactoryAnnotationUtils.java:56)
at beanfactoryannotation.sample.beanfactoryannotationutilsproblem.Application.main(Application.java:45)
2015-12-24 15:08:37.684 INFO 9524 --- [ Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@11e18e8c: startup date [Thu Dec 24 15:08:34 CET 2015]; root of context hierarchy
2015-12-24 15:08:37.686 INFO 9524 --- [ Thread-1] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 0
2015-12-24 15:08:37.691 INFO 9524 --- [ Thread-1] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
The BeanFactoryAnnotationUtils.qualifiedBeanOfType doesn't seems to works as the qualified beans exists in the context but could not be retrieved. Do you have an idea of what's the problem is here ?
Thanks !
Upvotes: 4
Views: 1494
Reputation: 126
This is not provided before Spring 4.3 due to the default specification of the BeanFactoryAnnotationUtils class.
See : https://jira.spring.io/browse/SPR-13819
Upvotes: 2
Reputation: 96
While looking at the code behind the BeanFactoryAnnotationUtils.qualifiedBeanOfType(...) method, I noticed that the qualifier is checked from an AbstractBeanDefinition object. When I dump this object on our example I can notice that the "qualifiers" map is empty ?!?!?
It looks like a bug in the way Spring loads the bean definition with annotated qualifiers.
There is already an open issue that looks quite similar: https://jira.spring.io/browse/SPR-13452
I guess you could open another one specifically with your test case.
Upvotes: 1