web-dev-qa-db-fra.com

Quelles sont les causes "Java.lang.IllegalStateException: ni BindingResult, ni l'objet cible en clair pour le nom de bean 'commande' disponible en tant qu'attribut de demande"?

Ceci est censé être un article canonique complet de questions et réponses pour ces types de questions.


J'essaie d'écrire une application Web Spring MVC dans laquelle les utilisateurs peuvent ajouter des noms de film à une collection en mémoire. Il est configuré comme tel

public class Application extends AbstractAnnotationConfigDispatcherServletInitializer {
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] {};
    }
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { SpringServletConfig.class };
    }
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

et

@Configuration
@ComponentScan("com.example")
public class SpringServletConfig extends WebMvcConfigurationSupport {
    @Bean
    public InternalResourceViewResolver resolver() {
        InternalResourceViewResolver vr = new InternalResourceViewResolver();
        vr.setPrefix("WEB-INF/jsps/");
        vr.setSuffix(".jsp");
        return vr;
    }
}

Il y a une seule classe @Controller dans le package com.example

@Controller
public class MovieController {
    private final CopyOnWriteArrayList<Movie> movies = new CopyOnWriteArrayList<>();
    @RequestMapping(path = "/movies", method = RequestMethod.GET)
    public String homePage(Model model) {
        model.addAttribute("movies", movies);
        return "index";
    }
    @RequestMapping(path = "/movies", method = RequestMethod.POST)
    public String upload(@ModelAttribute("movie") Movie movie, BindingResult errors) {
        if (!errors.hasErrors()) {
            movies.add(movie);
        }
        return "redirect:/movies";
    }
    public static class Movie {
        private String filmName;
        public String getFilmName() {
            return filmName;
        }
        public void setFilmName(String filmName) {
            this.filmName = filmName;
        }
    }
}

WEB-INF/jsps/index.jsp contient

<%@ taglib prefix="c" uri="http://Java.Sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Movies</title>
</head>
<body>
    Current Movies:
    <c:forEach items="${movies}" var="movieItem">
        <ul>
            <li>${movieItem.filmName}</li>
        </ul>
    </c:forEach>
    <form:form>
        <div>Movie name:</div>
        <form:input path="filmName" type="text" id="name" />
        <input type="submit" value="Upload">
    </form:form>
</body>
</html>

L'application est configurée avec le chemin de contexte /Example. Lorsque j'envoie une demande GET à

http://localhost:8080/Example/movies

la demande échoue, Spring MVC répond avec un code d'état 500 et signale l'exception et la trace de pile suivantes

Java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
    org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.Java:144)
    org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.Java:168)
    org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.Java:188)
    org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.Java:154)
    org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(AbstractDataBoundFormElementTag.Java:117)
    org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(AbstractHtmlElementTag.Java:422)
    org.springframework.web.servlet.tags.form.InputTag.writeTagContent(InputTag.Java:142)
    org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.Java:84)
    org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.Java:80)
    org.Apache.jsp.WEB_002dINF.jsps.index_jsp._jspx_meth_form_005finput_005f0(index_jsp.Java:267)
    org.Apache.jsp.WEB_002dINF.jsps.index_jsp._jspx_meth_form_005fform_005f0(index_jsp.Java:227)
    org.Apache.jsp.WEB_002dINF.jsps.index_jsp._jspService(index_jsp.Java:142)
    org.Apache.jasper.runtime.HttpJspBase.service(HttpJspBase.Java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.Java:729)
    org.Apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.Java:438)
    org.Apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.Java:396)
    org.Apache.jasper.servlet.JspServlet.service(JspServlet.Java:340)
    javax.servlet.http.HttpServlet.service(HttpServlet.Java:729)
    org.Apache.Tomcat.websocket.server.WsFilter.doFilter(WsFilter.Java:52)
    org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.Java:168)
    org.springframework.web.servlet.view.AbstractView.render(AbstractView.Java:303)
    org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.Java:1257)
    org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.Java:1037)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:980)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:897)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:970)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.Java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.Java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.Java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.Java:729)
    org.Apache.Tomcat.websocket.server.WsFilter.doFilter(WsFilter.Java:52)

Je pensais que le JSP générerait un <form> HTML avec une seule entrée de texte, pour un nom Movie, et un bouton d'envoi que je pourrais utiliser pour envoyer une demande POST avec un nouveau Movie. Pourquoi le servlet JSP ne parvient-il pas à rendre la balise <form:form> de Spring?

18
Sotirios Delimanolis

Pour simplifier les choses avec la balise de formulaire, ajoutez simplement un "nom de commande", qui est un nom horrible pour ce qu’elle recherche réellement ... il veut que l’objet que vous avez nommé dans l’annotation MdelAttribute. Donc dans ce cas commandName = "movie".

Cela vous évitera de lire de longues explications, mon ami. 

1
Pasha Utt

Dans mon cas, cela a fonctionné en ajoutant modelAttribute="movie" à la balise de formulaire et en ajoutant le nom du modèle à l'attribut, par exemple <form:input path="filmName" type="text" id="movie.name" />.

0
Pedro Madrid