Here’s a little lesson that I had to relearn today: When using Spring use interfaces.
The premise was I had a DAO bean that was configured with Spring, and it was @Autowired into my controller (or test case in this instance). Because I only intended to have a single implementation of this class, and because this was the first iteration of the project, I made the DAO bean concrete. However, when I tried to inject it into the test case got an exception:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [userservices.jpa.TrackerEntryDao] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
This didn’t make any sense, but after I tried to extract the bean from the context it all became clear. The DAO object is wrapped in a @Transactional annotation, which causes the actual bean to be proxied (so the transaction can be managed). This means that the bean passed into the @Autowired variable isn’t of the concrete class anymore. But, if we are expecting an interface, then the proxy will also implement that interface.