<form:form modelAttribute .. using two beans in JSP - spring

This is a spring based application. My form definition in JSP is as below,
<form:form modelAttribute="article" enctype="multipart/form-data" method="POST"
action="${sendEmailUrl}" name="postAd" id="postAd">
I want to display some data from 'article' bean on my form so I've defined modelAttribute='article'. Till here it is all fine. But on submit of the form, I want to collect data in different bean than article. Since I can define modelAttribute only once in the form, can someone please advise how can I use two beans in JSP?
P.S. In case I am not clear, let me give more details. On submit of form, data entered by user will be collected in bean 'X' and email will be sent using java email. But bean 'Y' (article in this case) is holding some values which needs to be displayed on the form.
Hope I am clear.

You could create a FormBean class, containing the two beans you said. Use this new class as a modelAttribute in your form and you will be able to access to both object's properties.
public class FormBean {
public Article article;
public YourOtherObject yourOtherObject;
}

Related

How to avoid some fields to be bound on form submit?

I have a simple form that edits my profile on the web. 'Person' bean, that describes user, contains many internal fields that cannot be changed by the form. Therefore I have just a subset of fields available for editing on the form. So far so good. Now what if some advanced user opens developer tools in Chrome browser and adds some other fields on the form or rename some existing fields ... so when submitted those fields will be bound back to the 'Person' bean and stored into database. Such way the user can spoof my form easily and chnage values for not allowed fields. Is there a way how to define (server side) which fields (bean properties) can be bound during the form submit?
Here is how the controller method signature looks like to get an idea:
#RequestMapping(path = "/profile/edit", method = RequestMethod.POST)
public String editProfile(#ModelAttribute("profile") Person doc, BindingResult result, Model m){
... saving doc to database ...
}
I'm using SpringBoot 1.3.5 with Thymeleaf ...
Turned out that solution is quite simple. I just added #InitBinder annotated method to controller and used WebDataBinder provided object to specify list of fields allowed. To do this I can use binder.setAllowedFields(...) method. Field names support "xxx*", "*xxx" and "xxx" patterns so its easy to specify set of fields when named properly in the bean. Now when post request variables are bound to my bean, these allowed fields are preserved and the others are rejected and not bound.
Code example:
#InitBinder // or #InitBinder("profile") with ModelAttribute name information
public void initBinder(WebDataBinder binder) {
binder.setAllowedFields("settings*");
}
See DataBinder docs for detailed info.

Java Spring #ModelAttribute method model name

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.

Displaying Data Table And Submiting Form In One Page Struts

I'm new in Struts, currently I'm using struts 1.3 to build simple Contact application
I want to display data table contains contact list from the database, in the same page I want to create a form for creating new contact and then insert it to database.
I'm using Spring bean and hibernate to do database operation and logic. So here is my flow, my action class will call spring bean, and the spring bean will call dao classes for database operation do some logic, then my action class will put the list into request object named contactList, then in jsp file I'm iterate it using logicLiterate tag.
Displaying the table and submiting all works fine, but when I do validating in ActionForm, and I want to display the error message, I have an error 500. This is because the jsp cannot find attribute named contactList in the request object, because if there is an error in ActionForm classes, Struts not calling the method at my Action class that will read the database and put it into the request object. I can try calling the spring bean in my ActionForm, but I'm afraid it not appropriate, because if there is no error then I will call the spring bean twice for the same work. What do you suggest me to do?
My bad not to read the doc carefully, now i understand that action tag in struts-config.xml have "input" attribute, this attribute specifies the physical page to which the request has to be forwarded if there is an error.
In my case, i just have to specified the input attribute to current path (eg. /contacts.do, etc) so the Action class can do its Action method.
Please note that, this request is forward requuest, not redirect.

Spring MVC Front End Validations

I wanted to validate user inputs in my jsp which were binded to Springformdata objects using <spring:bind> without hitting the controller.
Is there any other way I can achive this in spring MVC without using javascrpit.
See below code
<tr><td>
<spring:bind path="applyDmlFormData.file">
Select DML File : <input type="file" name="file"/>
</spring:bind>
</td></tr>
Here I am asking user to browse/select the input file and then attaching that to applyDmlFormData objects' file property.
If user don't selects any file and submits the form I wanted to validate that in the forntend itself without hitting the controller and display a error message saying file must me choosen. Basically I wanted to achieve the same functionality which is available in struts validation framework.
One more thing to add is I dont want to use validator which will be invoked by controller
#RequestMapping(value="/applyDml.htm", method = RequestMethod.POST)
public String process(#ModelAttribute("applyDmlFormData") ApplyDmlFormData applyDmlFormData, BindingResult result, SessionStatus status, HttpServletRequest request)
{
String mav = applyDmls;
validator.validate(applyDmlFormData, result);
if(!result.hasErrors())
{ //Business logic goes here
}
}
In the above code I am validating user inputs using validator.validate I dont want to do that.
The Struts Validator framework generates client-side JavaScript; AFAIK, Spring MVC doesn't offer a similar functionality. You need to roll your own client-side validation code. Even if you include Spring JS in your application, you still need to write your own validation code; here's an example.
Note that you don't need to use use a Validator object in your handler methods. You can also annotate your #ModelAttribute with #Valid and use JSR-303 annotations. See http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html#validation-beanvalidation-overview for details.
You can explore the Rhino library..find the spring integration api here

Access and modify attributes/objects which are not part of the form backing bean

I use Spring MVC (via Spring Roo) to build a small web application for administering persons. In the page for creating a person the bean Person is used as form backing object (key "person" in the model map).
<form:form action="${form_url}" method="POST" modelAttribute="person">
I would like to add some attributes to the model map which can be altered by the user in the creation form. Basically, I try to add a Boolean, so that I can control which page is displayed next after the user presses the submit button.
I try to modify the Boolean (key "myBoolean" in the model map) using a simple checkbox:
<form:checkbox id="_myboolean_id" path="myBoolean"/>
However, as I am new to Spring MVC I have some difficulties here. The Boolean object is not an attribute of the form backing object. So if I try to access it the following exception is thrown (of course):
Invalid property 'myBoolean' of bean
class [de.cm.model.Person]: Bean
property 'myBoolean' is not readable or
has an invalid getter method: Does the
return type of the getter match the
parameter type of the setter?
Is there are way to access a value of the model map directly? The only solution I can imagine right now is a kind of wrapper object around the class Person and my additional attributes which is used as a new form backing object. However, this is more work for a IMHO simple task. Do you have a better solution?
You may create custom form field:
<input type="checkbox" name="myBoolean"/>
And specify additional parameter in Controller post method:
public ModelAndView savePerson(#ModelAttribute("person") Person person, #RequestParameter ("myBoolean") Boolean myBoolean)

Resources