spring mvc-adding a object to the request - spring-mvc

I am new to spring-mvc and have a basic question.
I have a controller that reads the parameters that are sent in from a jsp and adds an object called userInfo to the ModelAndView and passes on to another jsp. The second jsp displays the vaious properites of the userInfo.
How do I send back the userInfo object to the controller?
<td><input type="hidden" name="userInfo" value="${requestScope.userInfo}"/></td>
I try to read the userInfo in the controller as follows:
request.getAttribute("userInfo")
However, this is null.
What is the best way for me to do this?
Thanks

HTML <form> <input> elements are sent as url-encoded parameters. You need to access them with HttpServletRequest#getParameter(String)
request.getParameter("userInfo");
Or use the #RequestParam annotation on a handler method parameter
#RequestMapping(...)
public String myHandler(#RequestParam("userInfo") String userInfo) {
...
}
Note however, that this won't send back the object, it will send back a String which is the toString() value of the object because that is what is given with ${requestScope.userInfo}.
Consider using session or flash attributes to have access to the same object in future requests.

Related

How to pass single parameter to contoller in Spring MVC?

I have some questions from a design point of view in Spring Web MVC.
Is it good practice to use Request Object in controller? If not, then what is alternative way to pass pass one text fields value to controller? Do I need to create one new from bean for this single fields?
It depends of the situation, in a few cases I used the HttpServletRequest; for example for writing a file to the output stream.
If you want to get the Request Parameters you can use the annotation #RequestParam, that it´s more easy to get the parameters from the request.
Depends that you want to handle, for example for a form you can use #ModelAttribute and this attribute can be in a session or in the request.
For example:
#Controller
public class YourController {
#RequestMapping(value = "someUrl", method = RequestMethod.GET)
public String someMethod(#RequestParam("someProperty") String myProperty)
{
// ... do some stuff
}
}
Check the documentation here:
#RequestParam
#ModelAttribute
#PathVariable

handle form post with a array of items in spring MVC

I'm trying to send some data from the client side to the server, and have it processed into a file download.
I'm using a simple HTML form because I want to initialize a file download (and not AJAX).
one of the form fields is an array of items. (the other two are name and description strings).
I'm serializing this field to a string (JSON.stringify) before submitting the form.
on the server side I tried a million techniques (#ModelAttribute vs. #RequestBody, different jackson mapping bean configurations) to either convert this to a single type or to three separate types (String + String + List/Array).
the examples I found were only for AJAX...
can anyone supply a working example or a description of one?
=======
Update:
I've implemented a workaround by JSON.stringify-ing the collection and passing it in one of the inputs,
and on the server side I have:
#RequestMapping(method = RequestMethod.POST, value = "exportSectionsToExcel")
public HttpEntity<byte[]> createExcelWorkBook(#ModelAttribute ExportSectionsListForm exportSectionsListForm) {
Section[] sectionObjects = gson.fromJson(exportSectionsListForm.getSections(), Section[].class);
...
with ExportSectionsListForm object containing strings only:
public class ExportSectionsListForm {
private String name;
private String url;
private String rssUrl;
private String sections;
...
(omitting ctor, getters and setters)
additionally, I found this promising link:
http://viralpatel.net/blogs/spring-mvc-multi-row-submit-java-list/
but didn't try it - seems like I'll need to dynamically generate input elements for this to work, but it might actually be the right solution. has anyone tried this?
The #ModelAttribute tag will try to build the object based on form postings. Since you are serializing your form values to JSON, this wont work. #RequestBody simply gives you a String representing the request body. So, you could get the String representing the JSON being passed in, then demarshal the JSON using Jackson of FlexJSON (or whatever JSON library you use). I am not sure this is the best approach, though.
I would question why you need to serialize the form to JSON to begin with. Spring handles forms with Lists/Maps just fine. Simply submit the form using the #ModelAttribute, making your "array" and List, or whatever you are expecting, on the Controller. So, if I am interpreting your example correctly, my ModelAttribute would look like:
public class ExportSectionsFormBean {
private String name;
private String url;
private String rssUrl;
private List<String> sections;
/* getters/setters */
}
Then my Controller method would look like:
#RequestMapping(method = RequestMethod.POST, value = "exportSectionsToExcel")
public HttpEntity<byte[]> createExcelWorkBook(#ModelAttribute ExportSectionsFormBean exportSectionsFormBean ) {
/* Do whatever with your */
}
On the form side, using the Spring JSTL tags, simply make your "sections" fields look like:
<form:input path="sections[0]" />
<form:input path="sections[1]" />
Or, if you'd rather use HTML, then
<input type="text" name="sections[0]" id="sections0" />
<input type="text" name="sections[1]" id="sections1" />
Which is what gets generated by the above JSTL tags. As long as the values for "sections" is put in the HTTP request as 'section[#]=value', you are all set.
I have been working on the same issue. And if i have several inputs witht eh same name such as:
<input name="somename"/>
<input name="somename"/>
<input name="somename"/>
and i have a form mapped to my method like this:
#ModelAttribute("ReturnsAndExchangesForm") ReturnsAndExchangesForm returnsAndExchangesForm
and in that form i have getters and setters for a property named:
String[] somename , spring is passing those values into that array nicely!

passing objects to action methods in mvc places properties in querystring

I am passing an object to an action method and that action method displays the view but it has all the proerties in the querystring and I do not want that (I have a long json string that cannot pass in url). How can I pass in a model object and not have it in the querystring? Also when you have a strong type view, Where does the object values for the Model store? Thanks for any help.
//This works fine when I am calling /controller/uploader
public ActionResult Uploader(Model model)
{
//logic
return View(model);
}
//But when I am on another method and want to call uploader it does pass the object but puts //all the data in a querystring
public void DoSomething(string val, string anotherval){
Model model = new Model();
Uploader(model);//This passes the object but when uploader page shows it has all the //model object properties in querystring and I do not want that.
return RedirectToAction("Uploader",model);//or this does the same thing
}
Try using the POST method on the html form:
<form action="/uploader" method="POST">
<!-- maybe some input elements? -->
<input type="submit" />
</form>
This will transfer the data as Form Encoded within the request body and keep the data out of the query string.

#ModelAttribute and #SessionAttribute in Spring

As Spring Specification said, #ModelAttribute will executed before the mapping handler and #SessionAttribute will keep the model attribute in session.
Consider below scenario: form bean is created after the controller is called and is set as session attribute as well. Next time MenuController is called, createForm() will be executed again and create another new form bean. My question is: will this latest created form bean be set as session attribute? and which form bean will be bind to the parameter in method bookList()?
Hope you guys can help. Thank you.
#Controller
#RequestMapping("/store")
#SessionAttribute("form")
public class MenuController {
#ModelAttribute("form")
public Form createForm() {
return new Form();
}
#RqeustMapping("/book")
public String bookList(#ModelAttribute("form") Form form){
//processing the form
}
}
When the bookList method is invoked for the first time in a given session, then method with #ModelAttribute('form) is invoked, the returned value (Form object) is stored in HttpSession and finally the bookList method is invoked with the same Form object passed as an argument (obtained from session).
For the subsequent requests within the same HttpSession, Spring retrieves the same Form object from the session and doesn't call the method with #ModelAttribute('form') again till the end of the session.
After each end of the bookList method invocation Spring stores updated version of Form object in HttpSession.
If you are using Spring Boot 2.x you can debug DefaultSessionAttributeStore#retrieveAttribute method to understand this behaviour.
Remember that your mapping is generalised. It will map both to a GET method and a POST method.
If your request mapping is a GET method,
The session attribute will hold the value of the #ModelAttribute("form") from the method createForm.
If an attribute form is returned from a POST request,
The session Attribute will override the #Model Attribute from the createForm method.
It is helpful to remember that the #ModelAttribute will execute before the mapping handler.
the sessionAttribute indicates that the "form" will be saved in the session. not meaning the "form" is retrieved from the session.

ASP.NET Web Service returns IndexOutOfRangeException with arguments

I have the following web service:
[ScriptService]
public class Handler : WebService {
[WebMethod]
public void method1() {
string json = "{ \"success\": true }";
System.Web.HttpContext.Current.Response.Write(json);
}
[WebMethod]
public object method2(Dictionary<string, object> d) {
Dictionary<string, object> response = new Dictionary<string, object>();
response.Add("success", true);
return response;
}
}
The first method accepts a traditional html form post and response writes a JSON string to the page. The second method accepts a JSON value posted via AJAX and returns a serialized object.
Both these methods work fine on their own but when put together in the same web service I get this error when calling method1:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
When I remove the arguments from method2 they work.
Can anyone suggest why this is happening?
Edit:
The problem spans from the argument type of method2. If I change it to a string or simple data type it works fine. As Joel suggests it's probably because Dictionaries can't be serialized. This doesn't seem to affect my requests sent by ajax and only breaks direct form posts to this handler. Therefore my workaround is to put the form post handlers in a separate file by themselves. Not ideal but works for my application.
Dictionaries are not serializable. Hiding it behind an object doesn't do anything for you. You must first convert your dictionary to an array or some other serializable object before sending it out.
Why isn't there an XML-serializable dictionary in .NET?
http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx
http://www.tanguay.info/web/index.php?pg=codeExamples&id=333

Resources