HI am starting to use spring 3 mvc and have run into a problem that don't know how to solve;
I am trying to validate a url #pathvariable using:
public String showGsscFormWithVenueId (#Valid
#Pattern(regexp="(0?[1-9]*)",message="venueid.not.number")
#PathVariable String venueId, BindingResult result, Model model) {
However I am getting an exception saying:
Errors/BindingResult argument declared without preceding model attribute. Check your handler method signature!
I've read about it on the internet and it says that bindingresult has to be after your model but my model is the pathVariable.
The only reason that I am using binding result is because I want to show the message="venueid.not.number" on the jsp. Therefore, could you please let me know if there is any other way ?
If the #PathVariable parameter fails validation, then Spring will add the error to the request's BindingResult automatically, you don't need to do that yourself.
As the error suggests, you can only declare an explicit BindingResult parameter when you're using form-base model objects. It's not intended to be used with #PathVariable.
Related
In my code I have a requirement that when user registers itself on the website, apart from standard validation of registration form, I need to ensure that the email provided by the user has not been registered already. I found the method addError(ObjectError) on the existing BindingResult object that I have. My challenge is how to create this new ObjectError and what values should I pass in it's construction mainly, the parameter (String objectName).
I am referring to the following API:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/ObjectError.html
Many Thanks
What are the advantages of using #ModelAttribute and #Valid?
Which are the differences?
Is it possible to use them together?
#ModelAttribute is used to map/bind a a method parameter or method return type to a named model attribute. See #ModelAttributes JavaDoc. This is a Spring annotation.
#Valid is an annotation that marks an object for JSR-303 bean validation. See #Valids JavaDoc. It is part of JavaEE 6, but I think Hibernate has an earlier implementation that most people use instead.
The advantage of using #ModelAttribute is that you can map a form's inputs to a bean. The advantage of #Valid is that you can utilize JSR-303 bean validation to ensure that the bean that is made is validated against some set of rules.
Yes you can use #ModelAttribute and #Valid together.
The best way to transfer data from a form (sic View) to the a Model object is to follow the typical/traditional MVC design pattern using Spring. My personal preferred way is to have a form in a JSP with Spring JSTL <form:*> tags, with a modelAttribute set. On the Controller, have a handler to accept the POST from the form that has a matching #ModelAttribute that is a bean that represents the form's input. I would then pass that "Form Bean" to a service layer to do some things, including translating the "Form Bean" into any models if needed (not necessary if the form is creating your model objects directly) and saving/updating/etc via a DAO. This is but one way to do things, but it's probably the bulk of what I do with Spring in my day-to-day job.
I would highly recommend reading the Spring reference materials and following the tutorials. The reference materials are very well written, easy to follow, and includes lots of examples on the various ways you can do things in Spring, and there are usually quite a few options on how you do things in Spring.
please check the below part fro spring reference documentation:
In addition to data binding you can also invoke validation using your own custom validator passing the same BindingResult that was used to record data binding errors. That allows for data binding and validation errors to be accumulated in one place and subsequently reported back to the user:
#RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(#ModelAttribute("pet") Pet pet, BindingResult result) {
new PetValidator().validate(pet, result);
if (result.hasErrors()) {
return "petForm";
}
// ...
}
Or you can have validation invoked automatically by adding the JSR-303 #Valid annotation:
#RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(#Valid #ModelAttribute("pet") Pet pet, BindingResult result) {
if (result.hasErrors()) {
return "petForm";
}
// ...
}
I have been reading this forum for quite awhile and find it VERY useful, thank you to the contributors. I have a question that has plagded me for several weeks. And here it goes.
#RequestMapping(value="updateNote.htm",method=RequestMethod.POST)
public String updateNote(#ModelAttribute("note")NoteBean nb, BindingResult res,Model model){
daoobj.updateNote(nb.getName(),nb.getPath(), nb.getNote());
model.addAttribute("note",daoobj.getByName(nb.getName()));
return("success");
}
#RequestMapping(value="updateNote.htm",method=RequestMethod.GET)
public String updateNote(#ModelAttribute("note")NoteBean nb,Model model){
populateNoteBean();
model.addAttribute("note",daoobj.getByName(nb.getName()));
return("editNote");
}
#ModelAttribute("WHAT")
public NoteBean populateNoteBean() {
NoteBean nnb = new NoteBean();
return nnb;
}
With the method populateNoteBean() the model attribute is "WHAT". But, the name that I use is "note". So when I run the code, the NoteBean is correctly saved to the data base. My question is HOW?? It seems that the name "WHAT" should be "note" or that the model attribute is saving it as no name.
Thank for your time.
With your current code you will have two instances of your notebean in the model!
First spring invokes all modelattribute annotated methods in your controller and places the results in the model. Second it evaluates the ones from your requestmapping method.
The point of a modelattribute annotated method is that you can choose how to create your bean. Load it for example from a database.
We use this approach like that:
modelattr method (name="note")
Loads beans from db
requestmapping method with modelattr param (name="note")
Merges the note bean created by the first method with the request paramters from a submit for example and you habe directly access to the modifed one.
One nice effect:
We do not want to put hidden input fields for all attributes in a form just to be able to merge the entity with the entitymanager. This way you can have a form with only one attribute (plus one for the id to be able to fetch the entity)
Or another one:
If your note bean is an abstract class spring has no possibility to instanciate the bean because it does not know what to instanciate. You can for example add a requestparam parameter in the modelattr annotated method and decide what to do yourself.
This is very well described in the documentation. Either the reference or in the api of either controller, reqestmapping or modelattribute i believe.
I have a small doubt with SpringMVC's command object. So the problem is, I have couple of forms which I am going to use in multiple pages (Around 17). I decided to make these two forms as JSP's and include them in the parent JSP's. The problem I am facing is that the textfields and dropdown's aren't populating with the data which is passed on from the server using Command object.
Lets call the Parent JSP as parent.jsp and than two included JPS's(which have the forms) as child1.jsp and child2.jsp. The controller for parent.jsp sets a ModelAttribute with name previousSales and returns the view as abc/parent where abc is the folder. (WEB-INF/jsp/abc/parent). My question is how do I make the model attribute available to the included JSP's?
The Command object should be part of your handler method calls, as follows:
#RequestMapping("/somepath/foo/do")
public String someHandlerMethod(
#ModelAttribute("commandObject") CommandObject commandObject,
Model model,
BindingResult result) {
...processing...
return("some.jsp");
}
On your JSP, use the Spring Forms TLD for the form fields, and the Command object will be bound to the form fields.
#RequestMapping("/somepath/foo/do")
public String someHandlerMethod(
#ModelAttribute("commandObject") CommandObject commandObject,
Model model,
BindingResult result) {
...processing...
return("some.jsp");
}
I'm having an issue with using #Valid on a parameter to a handler method on my #Controller. My code looks like this:
#RequestMapping(value=BIBBLE_BOBBLE_URI_PATTERN + "/widgets", method=RequestMethod.POST)
#ResponseBody
#ResponseStatus(HttpStatus.CREATED)
public Widget saveNewWidget(
#PathVariable final String username,
#PathVariable final String bibbleBobbleName,
#Valid #RequestBody final Widget widget,
final BindingResult results,
final HttpServletRequest request,
final HttpServletResponse response)
where Widget is the class for one of my domain objects. I'm using the #RequestBody annotation to indicate that the payload of the request maps to widget (in my tests, the requests are JSON, though Jackson is on my classpath so I could also use XML).
As you can see, the BindingResult parameter follows directly after the Widget parameter, but I get the following error:
java.lang.IllegalStateException: Errors/BindingResult argument declared without preceding model attribute. Check your handler method signature!
How do I apply the #Valid annotation to a #RequestBody parameter and then get the results?
P.S. I'm using annotation-driven to handle wiring up the controllers, do content-negotiation, etc.
Are you using Spring 3.1? It is a newly added feature in Spring version 3.1. Please see Validation For #RequestBody Method Arguments
This is an issue in spring 3.0 and it is fixed in 3.1 M2.
https://jira.springsource.org/browse/SPR-6709
If you are using spring 3.0, based on some threads and extensive reading, here is the best approach for this problem. An aspect oriented approach so that we can back out when you upgrade it to the version of spring which fixes this issue.
An aspect which intercepts calls to method which uses #RequestMapping annotation and for each parameter which has #Valid annotation on it, call the corresponding validator in the aspect.