Reputation: 634
I must say I am a newbie on Spring, so most probably this would be easy to must of you reading this.
My example is very simple. I have the classes Main
, Business
and Client
, in order to getClients
from Business
I created the interface ClientInterface
that contains a <List>Client
, Autowired
to the list in beans.xml
.
What I am trying to do is to print the Clients that the Business has, but its throwing me the following error:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clients': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public java.util.List com.springcourse.practice.Client.listClients; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.springcourse.practice.Client] found for dependency [collection of com.springcourse.practice.Client]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=arrayClients)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1116)
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:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.springcourse.practice.Main.main(Main.java:9)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: public java.util.List com.springcourse.practice.Client.listClients; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.springcourse.practice.Client] found for dependency [collection of com.springcourse.practice.Client]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=arrayClients)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:514)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
... 13 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.springcourse.practice.Client] found for dependency [collection of com.springcourse.practice.Client]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=arrayClients)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:986)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:814)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:768)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486)
... 15 more
Here are the content of the code
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="com.springcourse.practice"></context:component-scan>
<bean id="arrayClients" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="firstClient"/>
<ref bean="secondClient"/>
<ref bean="thirdClient"/>
</list>
</constructor-arg>
</bean>
<bean id="firstClient" class="com.springcourse.practice.Client">
<property name="name" value="Client Name 1"/>
<property name="address" value="Somewhere 1"/>
</bean>
<bean id="secondClient" class="com.springcourse.practice.Client">
<property name="name" value="Client Name 2"/>
<property name="address" value="Somewhere 2"/>
</bean>
<bean id="thirdClient" class="com.springcourse.practice.Client">
<property name="name" value="Client Name 3"/>
<property name="address" value="Somewhere 3"/>
</bean>
</beans>
ClientInterface
package com.springcourse.practice;
import java.util.List;
public interface ClientInterface {
public List<Client> getClients();
}
Client
package com.springcourse.practice;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component("clients")
public class Client implements ClientInterface {
public String name;
public String address;
@Autowired
@Qualifier("arrayClients")
public List<Client> listClients;
public List<Client> getClients(){
return listClients;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Business
package com.springcourse.practice;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
@Component("business")
public class Business {
public String name = "Programmer City";
public String getName() {
return name;
}
public String getClients() {
@SuppressWarnings("resource")
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/beans.xml");
Client clients = (Client) context.getBean("clients");
StringBuilder sb = new StringBuilder("The business name is: " + this.getName() + "\n");
sb.append("The clients the business " + this.getName() + " has are: \n");
for(Client client: clients.getClients()) {
sb.append("Client: " + client.name + " located in " + client.address + "\n");
}
return sb.toString();
}
}
Main
package com.springcourse.practice;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/beans.xml");
Business business = (Business) context.getBean("business");
System.out.println(business.getClients());
context.close();
}
}
Can somebody please tell me what I am doing wrong? Here is a link of the project if someone wants to test it: https://www.dropbox.com/s/isqahsxmxw8uxc1/Cap2_PracticeBusinessLocations_2.zip?dl=0
It is very hard to understand the errors. Thank you very much to everyone!
Edit beans.xml after solving
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="com.springcourse.practice"></context:component-scan>
<bean id="arrayClients" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="firstClient"/>
<ref bean="secondClient"/>
<ref bean="thirdClient"/>
</list>
</constructor-arg>
</bean>
<bean id="firstClient" class="com.springcourse.practice.Client">
<property name="name" value="Client Name 1"/>
<property name="address" value="Somewhere 1"/>
</bean>
<bean id="secondClient" class="com.springcourse.practice.Client">
<property name="name" value="Client Name 2"/>
<property name="address" value="Somewhere 2"/>
</bean>
<bean id="thirdClient" class="com.springcourse.practice.Client">
<property name="name" value="Client Name 3"/>
<property name="address" value="Somewhere 3"/>
</bean>
<bean id="arrayClientsTheSecond" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="TheSecondfirstClient"/>
<ref bean="TheSecondsecondClient"/>
<ref bean="TheSecondthirdClient"/>
</list>
</constructor-arg>
</bean>
<bean id="TheSecondfirstClient" class="com.springcourse.practice.Client">
<property name="name" value="Client Name 4"/>
<property name="address" value="Somewhere 4"/>
</bean>
<bean id="TheSecondsecondClient" class="com.springcourse.practice.Client">
<property name="name" value="Client Name 5"/>
<property name="address" value="Somewhere 5"/>
</bean>
<bean id="TheSecondthirdClient" class="com.springcourse.practice.Client">
<property name="name" value="Client Name 6"/>
<property name="address" value="Somewhere 6"/>
</bean>
</beans>
When I execute the response is:
The business name is: Programmer City
The clients the business Programmer City has are:
Client: Client Name 1 located in Somewhere 1
Client: Client Name 2 located in Somewhere 2
Client: Client Name 3 located in Somewhere 3
Client: Client Name 4 located in Somewhere 4
Client: Client Name 5 located in Somewhere 5
Client: Client Name 6 located in Somewhere 6
But again, the two list are named different and the list elements too.
Upvotes: 0
Views: 288
Reputation: 1065
While there are many Java and Spring conventions that you could apply to improve your code (private fields instead of public, initializing a new ApplicationContext inside a bean method, etc.), I'll focus on the main issue.
You can simply remove the @Qualifier annotation on the autowired list - Spring can identify the required beans based on your configuration by their type.
The code works after this change.
Upvotes: 1