Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 395 Vote(s) - 3.57 Average
  • 1
  • 2
  • 3
  • 4
  • 5
What causes "java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute"?

#1
<sub>This is meant to be an extensive canonical question & answer post for these types of questions.</sub>


---

I'm trying to write a Spring MVC web application where users can add movie names to an in-memory collection. It's configured like so

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[] { "/" };
}
}

and

@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;
}
}

There's a single `@Controller` class in the `com.example` package

@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` contains

<%@ 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>

The application is configured with context path `/Example`. When I send a GET request to

[To see links please register here]


the request fails, Spring MVC responds with a 500 status code, and reports the following exception and stack trace

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)

I expected the JSP to generate an HTML `<form>` with a single text input, for a `Movie` name, and a submit button, that I can use to send a POST request with a new `Movie`. Why does the JSP servlet instead fail to render Spring's `<form:form>` tag?
Reply

#2
To make things simple with the form tag just add a "commandName" which is a horrible name for what it is actually looking for...it wants the object you named in the MdelAttribute annotation. So in this case commandName="movie".

That'll save you reading long winded explanations friend.
Reply

#3
In my case, it worked by adding `modelAttribute="movie"` to the form tag, and prepending the model name to the attribute, something like `<form:input path="filmName" type="text" id="movie.name" />`
Reply

#4
Updating from Spring version 3 to Spring version 5, produces the same error. All answers were satisfied already in my code. Adding the annotation `@ControllerAdvice` solved the problem for me.
Reply

#5
I had this error on a screen with multiple forms that do a search. Each form posts to its own controller method with results shown on same screen.

Problem: I missed adding the other two forms as model attributes in each controller method causing that error when screen renders with results.

Form1 -> bound to Bean1 (bean1) -> Posting to /action1
Form2 -> bound to Bean2 (bean2) -> Posting to /action2
Form3 -> bound to Bean3 (bean2) -> Posting to /action3

```
@PostMapping
public String blah(@ModelAttribute("bean1") Bean1 bean, Model model){
// do something with bean object

// do not miss adding other 2 beans as model attributes like below.
model.addAttribute("bean2", new Bean2());
model.addAttribute("bean3", new Bean3());
return "screen";
}

@PostMapping
public String blahBlah(@ModelAttribute("bean2") Bean2 bean, Model model){
// do something with bean object
// do not miss adding other 2 beans as model attributes like below.
model.addAttribute("bean1", new Bean1());
model.addAttribute("bean3", new Bean3());
return "screen";
}

@PostMapping
public String blahBlahBlah(@ModelAttribute("bean3") Bean3 bean, Model model){
// do something with bean object
// do not miss adding other 2 beans as model attributes like below.
model.addAttribute("bean1", new Bean1());
model.addAttribute("bean2", new Bean2());
return "screen";
}
```
Reply

#6
I tried to migrate my application to Spring5 and noticed the same issue. It was caused by the moment that the 'commandName' attribute is not supported anymore and I had to use 'modelAttribute' instead.
Reply

#7
You're trying to use [Spring MVC's form tag][1].

> This tag renders an HTML `form` tag and exposes a binding path to
> inner tags for binding. It puts the command object in the `PageContext`
> so that the command object can be accessed by inner tags. [..]
>
> Let’s assume we have a domain object called `User`. It is a JavaBean
> with properties such as `firstName` and `lastName`. We will use it as the
> **form backing object** of our form controller which returns `form.jsp`.

In other words, Spring MVC will extract a _command object_ and use its type as a blueprint for binding `path` expressions for `form`'s inner tags, like [`input`][2] or [`checkbox`][3], to render an HTML `form` element.

This _command object_ is also called a model attribute and its name is specified in the `form` tag's `modelAttribute` or `commandName` attributes. You've omitted it in your JSP

<form:form>

You could've specified a name explicitly. Both of these are equivalent.

<form:form modelAttribute="some-example-name">
<form:form commandName="some-example-name">

**NOTE**: Spring 5 has removed the `commandName` attribute, see the upgrade notes, [here][4].

The [default attribute name is `command`][5] (what you see in error message). A model attribute is an object, typically a POJO or collection of POJOs, that your application supplies to the Spring MVC stack and which the Spring MVC stack exposes to your view (ie. the M to the V in MVC).

Spring MVC collects all model attributes in a [`ModelMap`][6] (they all have names) and, in the case of JSPs, transfers them to the [`HttpServletRequest`][7] attributes, where JSP tags and EL expressions have access to them.

In your example, your `@Controller` handler method which handles a `GET` to the path `/movies` adds a single model attribute

model.addAttribute("movies", movies); // not named 'command'

and then forwards to the `index.jsp`. This JSP then tries to render

<form:form>
...
<form:input path="name" type="text" id="name" />
...
</form:form>

While rendering this, [`FormTag`][8] (in reality, the [`InputTag`][9]) tries to find a model attribute named `command` (the default attribute name) so that it can produce an HTML `<input>` element with a `name` attribute constructed from the `path` expression and the corresponding property value, ie. the result of `Movie#getFilmName()`.

Since it cannot find it, it throws the exception you see

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute

The JSP engine catches it and responds with a 500 status code. If you want to take advantage of a `Movie` POJO to simply construct your form correctly, you can add a model attribute explicitly with

model.addAttribute("movie", new Movie());

or have Spring MVC create and add one for you (must have an accessible parameterless constructor)

@RequestMapping(path = "/movies", method = RequestMethod.GET)
public String homePage(@ModelAttribute("command") Movie movie, Model model) {...}

Alternatively, include a `@ModelAttribute` annotated method in your `@Controller` class

@ModelAttribute("command")
public Movie defaultInstance() {
Movie movie = new Movie();
movie.setFilmName("Rocky II");
return movie;
}

Note that Spring MVC will call this method and implicitly add the object returned to its model attributes for each request handled by the enclosing `@Controller`.

You may have guessed from this description that Spring's `form` tag is more suited for rendering an HTML `<form>` from an existing object, with actual values. If you want to simply create a blank `<form>`, it may be more appropriate to construct it yourself and not rely on any model attributes.

<form method="post" action="${pageContext.request.contextPath}/movies">
<input name="filmName" type="text" />
<input type="submit" value="Upload" />
</form>

On the receiving side, your `POST` handler method, will still be able to extract the `filmName` input value and use it to initialize a `Movie` object.

## Common Errors

As we've seen, `FormTag` looks for a model attribute named `command` by default or with the name specified in either `modelAttribute` or `commandName`. Make sure you're using the right name.

`ModelMap` has a [`addAttribute(Object)`][10] method which adds

> the supplied attribute to this `Map` using a [generated][11] name.

where the general convention is to

> return the uncapitalized short name of the [attribute's] `Class`, according to
> JavaBeans property naming rules: So, `com.myapp.Product` becomes
> `product`; `com.myapp.MyProduct` becomes `myProduct`; `com.myapp.UKProduct`
> becomes `UKProduct`

If you're using this (or a similar) method or if you're using one of the `@RequestMapping` [supported return types][12] that represents a model attribute, make sure the generated name is what you expect.

Another common error is to bypass your `@Controller` method altogether. A typical Spring MVC application follows this pattern:

1. Send HTTP GET request
2. `DispatcherServlet` selects `@RequestMapping` method to handle request
3. Handler method generates some model attributes and returns view name
4. `DispatcherServlet` adds model attributes to `HttpServletRequest` and forwards request to JSP corresponding to view name
5. JSP renders response

If, by some misconfiguration, you skip the `@RequestMapping` method altogether, the attributes will not have been added. This can happen

- if your HTTP request URI accesses your JSP resources directly, eg. because they are accessible, ie. outside `WEB-INF`, or
- if the `welcome-list` of your `web.xml` contains your JSP resource, the Servlet container will render it directly, bypassing the Spring MVC stack entirely

One way or another, you want your `@Controller` to be invoked so that the model attributes are added appropriately.

## What does `BindingResult` have to do with this?

A [`BindingResult`][13] is a container for initialization or validation of model attributes. The [Spring MVC documentation][14] states

> The `Errors` or `BindingResult` parameters have to follow the model object
> that is being bound immediately as the method signature might have
> more than one model object and Spring will create a separate
> `BindingResult` instance for each of them [...]

In other words, if you want to use `BindingResult`, it has to follow the corresponding model attribute parameter in a `@RequestMapping` method

@RequestMapping(path = "/movies", method = RequestMethod.POST)
public String upload(@ModelAttribute("movie") Movie movie, BindingResult errors) {

`BindingResult` objects are also considered model attributes. Spring MVC uses a simple naming convention to manage them, making it easy to find a corresponding regular model attribute. Since the `BindingResult` contains more data about the model attribute (eg. validation errors), the `FormTag` attempts to bind to it first. However, since they go hand in hand, it's unlikely one will exist without the other.


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

[4]:

[To see links please register here]

[5]:

[To see links please register here]

[6]:

[To see links please register here]

[7]:

[To see links please register here]

[8]:

[To see links please register here]

[9]:

[To see links please register here]

[10]:

[To see links please register here]

-
[11]:

[To see links please register here]

-
[12]:

[To see links please register here]

[13]:

[To see links please register here]

[14]:

[To see links please register here]

Reply

#8
If your Model object is correctly being passed to the GET API call but still have this error, you may look at the html or jsp page also to check whether correct variables names are provided and tags are used correctly. In my case, I forgot to include the objects under the closing ```<form>``` tag.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through