We've been searching around a bit on both the internet and our paperback courses but can't seem to find a solution to our problem:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [services.GebruikerDAO] is defined: expected single matching bean but found 2: gebruikerDAO,GebruikerDAO
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:863)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:768)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486)
... 58 more
To sketch some background information: we have to make a small website using java jsp pages and all, together with spring security and maven using a DB to get information and check for information. Following will be all our files.
This is our GebruikerDAO class:
package services;
import domein.Gebruiker;
public interface GebruikerDAO extends GenericDao<Gebruiker>{
public Gebruiker getGebruikerByStamnummer(String stamnummer);
}
This is our JpaGebruikerDao class:
@Repository("gebruikerDAO")
public class JpaGebruikerDao extends GenericDaoJpa<Gebruiker> implements GebruikerDAO{
@PersistenceContext
private EntityManager em;
public JpaGebruikerDao()
{
super(Gebruiker.class);
}
/*@Override
@Transactional
public List<Gebruiker> findAll() {
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Gebruiker> criteriaQuery = criteriaBuilder.createQuery(Gebruiker.class);
Root<Gebruiker> gebruiker = criteriaQuery.from(Gebruiker.class);
criteriaQuery.orderBy(criteriaBuilder.desc(gebruiker.get(Gebruiker_.familienaam)));
// JPQL select
criteriaQuery.select(gebruiker);
TypedQuery<Gebruiker> query = em.createQuery(criteriaQuery);
return query.getResultList();
}*/
// CRUD methods
@Override
@Transactional
public Gebruiker update(Gebruiker gebruiker) {
return em.merge(gebruiker);
}
@Override
@Transactional(readOnly = true)
public Gebruiker get(String id) {
return em.find(Gebruiker.class, id);
}
@Override
@Transactional
public void insert(Gebruiker gebruiker) {
em.persist(gebruiker);
}
@Override
@Transactional
public void delete(Gebruiker gebruiker) {
em.remove(em.merge(gebruiker));
}
@Override
public Gebruiker getGebruikerByStamnummer(String stamnummer) {
return get(stamnummer);
}
}
This is our Controller class:
@Controller
public class PlanningController {
@Autowired
@Qualifier("GebruikerDAO")
private GebruikerDAO gebruikerDao;
@RequestMapping(value = "/planning", method = RequestMethod.GET)
public String listGuest(Model model)
{
List<Gebruiker> gebruikerlijst = gebruikerDao.findAll();
List<Student> studentlijst = new ArrayList<>();
for (Gebruiker s : gebruikerlijst) {
if (s instanceof Student){
Student student = (Student)s;
if(student.getLokaal() != null)
{
studentlijst.add(student);
}
}
}
// there is more but it just checks for if a timeslot is available in our planning
This is our spring-security file:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<beans:import resource="applicationContext.xml"/>
<http auto-config="true">
<intercept-url pattern="/admin*" access="hasAnyRole('ROLE_Student', 'ROLE_Promotor', 'ROLE_Coordinator')"/>
<logout logout-success-url="/planning.htm"/>
<access-denied-handler ref="accessDeniedHandler"/>
<remember-me/>
</http>
<authentication-manager>
<authentication-provider>
<password-encoder hash="sha-256"/>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select StamNummer, WachtwoordEncrypted, 'true' as enabled from gebruiker where StamNummer=?"
authorities-by-username-query="select StamNummer, Type as authority from gebruiker where StamNummer=?"
role-prefix="ROLE_"
/>
</authentication-provider>
</authentication-manager>
<beans:bean class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"/>
This is our applicationContext file:
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<bean name = "GebruikerDAO" class="services.JpaGebruikerDao"/>
</beans>
This is our dispatcher-servlet file:
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="controller"/>
<context:component-scan base-package="services"/>
<bean id="accessDeniedHandler" class="handler.MyAccessDeniedHandler">
<property name="accessDeniedUrl" value="403"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/bachelorproef"/> <!-- jdbc:mysql://localhost:3306/mysql?zeroDateTimeBehavior=convertToNull-->
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>domein</value>
</list>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="database" value="MYSQL"/>
</bean>
</property>
</bean>
<bean id="transactionManager"
class=" org.springframework.orm.jpa.JpaTransactionManager ">
<constructor-arg ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
</beans>
This is our web.xml file:
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web- app_2_4.xsd">
<display-name>Spring MVC Application</display-name>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml,
/WEB-INF/spring-security2.xml
</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
This is our Gebruiker class:
@Entity
@Table(name = "gebruiker")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "Type")
public abstract class Gebruiker implements Serializable {
@Id
@Column(name = "StamNummer")
private String stamNummer;
@Column(name = "Familienaam")
private String familienaam;
@Column(name = "Voornaam")
private String voornaam;
@Column(name = "Email")
private String email;
@Column(name = "Wachtwoord")
private String wachtwoord;
@Column(name = "Campus")
private String campus;
@Transient
private String naam;
public Gebruiker() {
}
(+ some extra getters, setters and generatePassword methods)
This is our Student class:
@Entity
@DiscriminatorValue("Student")
public class Student extends Gebruiker{
@ManyToOne
private Promotor promotor;
@OneToOne
@JoinColumn(name = "HuidigDossier_DossierId")
private Dossier dossier;
@Temporal(TemporalType.TIMESTAMP)
private Date datumPresentatie;
private String lokaal;
(+ some getters, setters and toString)
This is our Promotor class:
@Entity
@DiscriminatorValue("Promotor")
public class Promotor extends Gebruiker {
@OneToMany(mappedBy="promotor")
List<Student> studenten;
public Promotor(){
studenten = new ArrayList<>();
}
public List<Student> getStudenten() {
return studenten;
}
public void setStudenten(List<Student> studenten) {
this.studenten = studenten;
}
}
This is our BPCoordinator class:
@Entity
@DiscriminatorValue("Coordinator")
public class BPCoordinator extends Gebruiker{
public BPCoordinator(){
}
}
I know there is lots of information to be found if the NoUniqueBeanDefinitionException
error occurs, but this almost always refers to the entityManager, here he says both gebruikerDAO and GebruikerDAO or something are found and we have no idea where he gets them from or why this error occurs. Most of this code has been almost purely copy paste from other schoolprojects and paperbackcode (our course given by to us by our lectors)
Ideas where and how to fix the issue would be amazing.
2. Using Java Configuration. This is the simplest and easiest way to create multiple beans of the same class using annotations. In this approach, we'll use a Java-based configuration class to configure multiple beans of the same class.
It's worth noting that if both the @Qualifier and @Primary annotations are present, then the @Qualifier annotation will have precedence. Basically, @Primary defines a default, while @Qualifier is very specific.
Annotation Type PrimaryIndicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one 'primary' bean exists among the candidates, it will be the autowired value.
There are two possible solutions for this exception. 1- Either define the class only in the XML file and use @Qualifier:
public class PlanningController {
@Autowired
@Qualifier("GebruikerDAO")
private GebruikerDAO gebruikerDao;
In XML define a bean for PlanningController only
2- Or remove Qualifier annotation, and add getters and setters or constructor in PlanningController then in the XML define the context with the property:
<bean class="[path of PlanningController]">
<property name="gebruikerDao" ref="[GebruikerDAO implementation bean name]"/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With