Inspired by spring data awesomeness I wanted to create a abstract RESTController that I could extend for a lot of my controllers. I created the following class:
@Controller
public abstract class RESTController>
{
@Autowired
private R repository;
@RequestMapping(method=RequestMethod.GET, params={"id"})
@ResponseBody
public E getEntity(@RequestParam PK id)
{
return repository.findOne(id);
}
...
}
I was hoping that the generics would allow me to @Autowired in the repository but I get the following error:
SEVERE: Allocate exception for servlet appServlet
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.data.repository.PagingAndSortingRepository] is defined: expected single matching bean but found 3: [groupRepository, externalCourseRepository, managedCourseRepository]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:800)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
I understand what the error is telling me, there is more than one match for the @Autowired. I am confused because I thought by creating the following controller it would work:
@Controller
@RequestMapping(value="/managedCourse")
public class ManagedCourseController extends RESTController
{
...
}
This is easy enough to work around by doing having a method like this in the RESTController:
protected abstract R getRepository();
and then doing this in your implementing class:
@Autowired
private ManagedCourseRepository repository;
@Override
protected ManagedCourseRepository getRepository()
{
return repository;
}
I was just wondering if someone had any thoughts of how I could get this to work.
Also I found this interesting aritcle.
解决方案
I would actually recommend XML-based wiring over annotations in this case. It seems to me you're trying to avoid a lot of needless duplication in your controller instances. If you had a single REST controller class, the container can then instantiate as many instances as you need, mapping each to a different URI.
Annotations are more of a shorthand for cases where you plan to create a single instance. This happens to cover about 90% of form-based J2EE session beans, but it's not a panacea.