JDK Version: 1.7 (latest update) Spring: 3.2.16-Release
I have a generic controller class, that can be reused for multiple functionality. Due to the limitations of annotation-based approach for such requirements, I am using the XML-based configuration. Also, I have disabled the component scan in XML.
I have configured multiple bean instances of the same class and used SimpleUrlHandlerMapping
for mapping URLs to controller. If I test the project with one controller enabled at a time, it works fine. However, when I enable the second instance, spring complains with following error:
ERROR: org.springframework.web.servlet.DispatcherServlet - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'deviceController' bean method
public java.lang.String com.smvc.pr05.controllers.SearchController.search(java.util.Locale,org.springframework.ui.ModelMap)
to {[],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'searchController' bean method
public java.lang.String com.smvc.pr05.controllers.SearchController.search(java.util.Locale,org.springframework.ui.ModelMap) mapped.
...
Caused by: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'installerController' bean method
public java.lang.String com.smvc.pr05.controllers.SearchController.search(java.util.Locale,org.springframework.ui.ModelMap)
to {[],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'deviceController' bean method
public java.lang.String com.smvc.pr05.controllers.SearchController.search(java.util.Locale,org.springframework.ui.ModelMap) mapped.
...
I have tried it with scope=singleton and scope=prototype for the controller bean definition. I have tried with enabling component scan (keeping manually defined bean in XML) and disabling the same. The error persists.
While this may be fixed, if I create concrete class per instance, I really want to keep it as last option. I have a strong belief in Spring capabilities, as I have used similar technique for non-controller classes.
Please let me know, what is that I am missing.
The spring configuration (EDITED with controller as singleton)
...
<beans:bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<beans:property name="mappings">
<beans:props>
<beans:prop key="/">homeController</beans:prop>
<beans:prop key="/deviceSearch/">deviceController</beans:prop>
<beans:prop key="/installerSearch/">installerController</beans:prop>
<beans:prop key="/customerSearch/">customerController</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
...
<beans:bean id="homeController" class="com.smvc.pr05.controllers.HomeController" >
</beans:bean>
<beans:bean id="deviceController" class="com.smvc.pr05.controllers.SearchController">
<beans:property name="metaModel" ref="deviceModel"/>
<beans:property name="searchService" ref="deviceService" />
</beans:bean>
<beans:bean id="installerController" class="com.smvc.pr05.controllers.SearchController" >
<beans:property name="metaModel" ref="installerModel"/>
<beans:property name="searchService" ref="installerService" />
</beans:bean>
<beans:bean id="customerController" class="com.smvc.pr05.controllers.SearchController" >
<beans:property name="metaModel" ref="customerModel"/>
<beans:property name="searchService" ref="customerService" />
</beans:bean>
The Java Controller Class:
...
@Controller
public class SearchController {
private static final Logger LOG = LoggerFactory.getLogger(SearchController.class);
private SearchService searchService; //Has explicit set() method
private MetaModel metaModel; //Has explicit set() method
@SuppressWarnings({ "unchecked" })
@RequestMapping(method = RequestMethod.POST)
public String search(Locale locale, ModelMap modelMap) {
...
}
public void setSearchService(SearchService searchService) {
this.searchService = searchService;
}
public void setMetaModel(MetaModel metaModel) {
this.metaModel = metaModel;
}
}