Learning Spring MVC has been challenging for me. I’ve encountered many problems along the way. The error in the title is a problem I’ve encountered several times for several reasons many of which have been mentioned in sites like Stack Overflow, but not all.
First, let me describe what I’m trying to accomplish. I’m building a Spring MVC and Hibernate JPA application to demonstrate the best design for mapping flattened data to relational data using Dozer. To accomplish this, I need several components. The ones I’m concerned with in this post are the Spring components: Controller, Service, and Repository. The Repository is injected (autowired) into the Service and the Service is injected into the Controller. Briefly, injection (@Inject or @Autowired) uses an interface in which to inject an implementing class in order to hide implementation details. I can inject a Service into my Controller to interact with the Repository, and in a JPA app, I can use the Repository to access the persistence layer.
This is only a fraction of what Spring does and yet it is very complex, especially the configuration. The old way to configure a Spring app is through XML. I’m using a combination of XML and annotations. There are many things that can go wrong when configuring a Spring MVC app, but there is one error that I’ve encountered several times.
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency
This means that upon attempting to inject a spring component, no implementation was found. Here are the reasons why this can happen.
The first reason is the most fundamental: you didn’t bother building the implementation class. You built the interface, autowired it, but never created a class which implements the Service, Component, or Repository interfaces you’ve built.
You must build a class which has the code “implements MyRepository” and implements all of it’s methods. Then you must annotate it with, for example, @Repository.
Speaking of annotations. A common cause of this error is that you’ve implemented the interfaces but you haven’t configured them. A controller should have @Controller at the Class signature. The service should have @Service or @Component. The Repository should have @Repository or @Component. These are hints to the Spring base scanner to load them when the server starts up.
Spring needs to know where to look for your Spring implementations. You’ll have a file called [mydispatcherservlet]-servlet.xml. In it, you must have the following:
<context:component-scan base-package=”com.mycompany.customer” />
This signals to Spring that the components are in com.mycompany.customer or it’s child packages.
Scanner base-package not catching spring components
You may have the component scanner, but your base package may not include all of your components. For example, you might have a repostory in com.mycompany.customer.repository, but your scan package might be com.mycompany.customer.controller. It will find the controller, but not the repository.
Another App Causing the Error
This is the one which I spent several hours debugging. It’s not common, and you won’t find it listed on other sites because it’s not a Spring specific issue, it is an app server/servlet containter issue.
I’m using Tomcat with Eclipse. In Eclipse, you can add or remove your web projects to the Tomcat server, but there may be other apps in the Tomcat webapps directory which never show up in the Eclipse Tomcat server node. I was having the above error and I tried all of the above solutions with no luck. I began to wonder if something else in Tomcat could be spitting out the errors so I removed my app from Tomcat. I surprised to see that the error continued.
Eventually, though, I looked in the Tomcat webapps directory and found a discarded version of the app. I deleted it, and the errors ceased. I redeployed my new version and it was fixed. Good grief!