J'essaie de créer une application qui peut répertorier certaines valeurs de la base de données et modifier, ajouter, supprimer si nécessaire à l'aide de Spring 4 et recevoir l'erreur suivante (uniquement si l'annotation "@Controller" est présente dans mes deux fichiers de contrôleur, si je supprime l'annotation de l'un des fichiers, cela fonctionne mais je reçois un message dans la console "aucun mappage trouvé ... dans dispatcherservlet avec le nom ...):
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/edit/{id}],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public Java.lang.String com.bookReview.app.BookController.editBook(int,org.springframework.ui.Model)
WARN : org.springframework.web.context.support.XmlWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
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 'reviewController' bean method
public Java.lang.String com.bookReview.app.ReviewController.editReview(int,org.springframework.ui.Model)
to {[/edit/{id}],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'bookController' bean method
public Java.lang.String com.bookReview.app.BookController.editBook(int,org.springframework.ui.Model) mapped.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1574)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.Java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.Java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.Java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.Java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.Java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:480)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.Java:403)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.Java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.Java:106)
at org.Apache.catalina.core.StandardContext.listenerStart(StandardContext.Java:4728)
at org.Apache.catalina.core.StandardContext.startInternal(StandardContext.Java:5166)
at org.Apache.catalina.util.LifecycleBase.start(LifecycleBase.Java:150)
at org.Apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.Java:1409)
at org.Apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.Java:1399)
at Java.util.concurrent.FutureTask.run(FutureTask.Java:266)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1142)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:617)
at Java.lang.Thread.run(Thread.Java:745)
Caused by: Java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'reviewController' bean method
public Java.lang.String com.bookReview.app.ReviewController.editReview(int,org.springframework.ui.Model)
to {[/edit/{id}],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'bookController' bean method
public Java.lang.String com.bookReview.app.BookController.editBook(int,org.springframework.ui.Model) mapped.
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.Java:212)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.Java:184)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.Java:144)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet(AbstractHandlerMethodMapping.Java:123)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet(RequestMappingHandlerMapping.Java:126)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.Java:1633)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1570)
... 21 more
Ceci est mon fichier pom.xml
<project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bookReview.app</groupId>
<artifactId>BookReviewApp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>BookReviewApp</name>
<description>review app</description>
<!-- <properties>
Generic properties
<Java.version>1.8</Java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
Spring
<spring-framework.version>4.0.3.RELEASE</spring-framework.version>
Hibernate / JPA
<hibernate.version>4.3.5.Final</hibernate.version>
<hibernate.version>3.6.9.Final</hibernate.version>
Logging
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
</properties> -->
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.6.RELEASE</version>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.9.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.9.Final</version>
</dependency>
<!-- Apache Commons DBCP -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- Spring ORM -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.5</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.12</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.Sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.Sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-Java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
</dependencies>
</project>
Ceci est mon fichier web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://Java.Sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://Java.Sun.com/xml/ns/javaee http://Java.Sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app/servlet/sevlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Ceci est mon fichier sevlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<beans:bean id="dataSource" class="org.Apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
<beans:property name="url"
value="jdbc:mysql://localhost:3306/test" />
<beans:property name="username" value="serban" />
<beans:property name="password" value="serban" />
</beans:bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<beans:bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="annotatedClasses">
<beans:list>
<beans:value>com.bookReview.app.model.book</beans:value>
<beans:value>com.bookReview.app.model.review</beans:value>
</beans:list>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="bookDAO" class="com.bookReview.app.dao.bookDAOImpl">
<beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</beans:bean>
<beans:bean id="bookService" class="com.bookReview.app.service.BookServiceImpl">
<beans:property name="bookDAO" ref="bookDAO"></beans:property>
</beans:bean>
<beans:bean id="reviewDAO" class="com.bookReview.app.dao.reviewDAOImpl">
<beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</beans:bean>
<beans:bean id="reviewService" class="com.bookReview.app.service.ReviewServiceImpl">
<beans:property name="reviewDAO" ref="reviewDAO"></beans:property>
</beans:bean>
<!-- <default-servlet-handler/> -->
<context:component-scan base-package="com.bookReview.app" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</beans:bean>
</beans:beans>
Ceci est mon fichier BookController.Java
package com.bookReview.app;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.bookReview.app.model.book;
import com.bookReview.app.service.BookService;
@Controller
public class BookController {
private BookService bookService;
@Autowired(required=true)
@Qualifier(value="bookService")
public void setBookService(BookService bs){
this.bookService = bs;
}
@RequestMapping(value = "/books", method = RequestMethod.GET)
public String listBooks(Model model) {
model.addAttribute("book", new book());
model.addAttribute("listBooks", this.bookService.listBooks());
return "book";
}
//For add and update book both
@RequestMapping(value= "/book/add", method = RequestMethod.POST)
public String addBook(@ModelAttribute("book") book b){
if(b.getBookid() == 0){
//new book, add it
this.bookService.addBook(b);
}else{
//existing book, call update
this.bookService.updateBook(b);
}
return "redirect:/books";
}
@RequestMapping("/remove/{id}")
public String removeBook(@PathVariable("id") int id){
this.bookService.removeBook(id);
return "redirect:/books";
}
@RequestMapping("/edit/{id}")
public String editBook(@PathVariable("id") int id, Model model){
model.addAttribute("book", this.bookService.getBookById(id));
model.addAttribute("listBooks", this.bookService.listBooks());
return "book";
}
}
Et voici mon fichier ReviewController.Java
package com.bookReview.app;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.bookReview.app.model.review;
import com.bookReview.app.service.ReviewService;
@Controller
public class ReviewController {
private ReviewService reviewService;
@Autowired(required=true)
@Qualifier(value="reviewService")
public void setReviewService(ReviewService rs){
this.reviewService = rs;
}
@RequestMapping(value = "/reviews", method = RequestMethod.GET)
public String listReviews(Model model) {
model.addAttribute("book", new review());
model.addAttribute("listReviews", this.reviewService.listReviews());
return "review";
}
//For add and update review both
@RequestMapping(value= "/review/add", method = RequestMethod.POST)
public String addReview(@ModelAttribute("review") review r){
if(r.getId() == 0){
//new review, add it
this.reviewService.addReview(r);
}else{
//existing review, call update
this.reviewService.updateReview(r);
}
return "redirect:/reviews";
}
@RequestMapping("/remove/{id}")
public String removeReview(@PathVariable("id") int id){
this.reviewService.removeReview(id);
return "redirect:/reviews";
}
@RequestMapping("/edit/{id}")
public String editReview(@PathVariable("id") int id, Model model){
model.addAttribute("review", this.reviewService.getReviewById(id));
model.addAttribute("listReviews", this.reviewService.listReviews());
return "review";
}
}
Je vous remercie
Tu devrais écrire
@Controller("/review")
public class ReviewController {
et
@Controller("/book")
public class BookController {
parce que dans votre code vous avez les deux méthodes sans chemin explicite/unique pour le mappage (par exemple, si nous avons un appel/edit/1, il est impossible de déterminer clairement la méthode d'un contrôleur à partir de votre editBook BookController
ou ReviewController editReview
Si le problème concerne une méthode ambiguë, le problème devrait probablement être le @RequestMapping
. Passez de @RequestMapping ( name = ...) à @RequestMapping ( value = ...)
@RequestMapping(name = "xxx.htm", method = RequestMethod.GET)
à
@RequestMapping(value = "xxx.htm", method = RequestMethod.GET)
Pour moi, ajouter l'attribut "params" dans @RequestMapping a fonctionné comme indiqué
@ResponseBody
@RequestMapping(method = RequestMethod.GET, params = {"id"})
public User getUserById(final @RequestParam(name="id", required = true) String Id)
throws InvalidArgumentException {
return userService.getUserById(UUID.fromString(Id));
}
/**
* REST service endpoint.
* @param name Unique name for the user in the system.
* @return Object of type {@link User} if exists otherwise null.
*/
@ResponseBody
@RequestMapping(method = RequestMethod.GET, params = {"name"})
public User getUserByName(final @RequestParam(name="name", required = true) String name)
throws InvalidArgumentException {
return userService.getUserByName(name);
}
Cependant, l'ajout simultané des deux paramètres dans la chaîne de requête générera une erreur 500 avec le message suivant:
Méthodes de gestionnaire ambiguë mappées pour le chemin HTTP
Dans ce cas, vous pouvez avoir une autre méthode de contrôleur prenant les deux paramètres, mais vous n’en utilisez qu’un, ce qui, à mon avis, n’est pas nécessaire.