I am using Spring MVC and I am trying to pass both HashMap and ArrayList values to my view file. But I can't find a way to achive this.
Could you please help me?
My Controller Mehtod
#RequestMapping(value="/do_register", method= RequestMethod.GET)
public ModelAndView RegistrationForm(#ModelAttribute Subscriber subscriber, BindingResult result)
{
HashMap<Integer, String> interest = new HashMap<Integer, String>();
interest.put(1,"Java");
interest.put(2,"PHP");
interest.put(3, "Both");
List<City> myCities = subService.getCity();
// I want to pass both "myCities" and "interest" to my view File
return new ModelAndView("regForm", "records", " ");
}
Form
<c:url var="action" value="/register" ></c:url>
<form:form action="${action}" modelAttribute="subscriber" method="POST" >
<div>
<label>City</label>
<form:select path="city">
<c:forEach items="${records}" var="city">
<option value="${city.cityId}">${city.cityName}</option>
</c:forEach>
</form:select>
</div>
<div>
<label>Interests</label>
<form:checkboxes path="interest" items="${records.interests}"/>
</div>
<input type="submit" value="Submit">
</form:form>
A ModelAndView contains a Model which is a kind of Map. It can contain as many objects as you need. Simply modify your code like :
#RequestMapping(value="/do_register", method= RequestMethod.GET)
public ModelAndView RegistrationForm(#ModelAttribute Subscriber subscriber, BindingResult result)
{
...
// I want to pass both "myCities" and "interest" to my view File
ModelAndView mav = ModelAndView("regForm");
mav.addAttribute("interests", interest);
mav.addAttribute("records", myCities);
return mav;
}
And you find your objects in the JSP with ${records} and ${interests}
Not sure about surrounding logic in your code base but one way to do that is create Envelop object contain both items or use subscriber object to handle both item and iterate on view.
For more reference here its similar type of question link
How to pass multiple model objects from controller and how to pass all as command objects into the form:form in spring mvc?
Hope this helps
Related
I'm a trainee java-dev and this is my first question here so please, don't judge me!
I have a Controller class which works with jsp files. The first jsp (userinput.jsp) has 3 text fields (lat, lon, radius) and 2 buttons (submit, apply default values). The second jsp is just an HTML table filled with data (depends on user input), and a reset button which should return you to the starter page (userinput.jsp) and delete all existing data. How should I do this?
Bonus question: If I try to refresh the page at the second state (html table), the browser generates a warning that says I'll lose all data and I shouldn't refresh. How can I get rid of this?
#Controller
#EnableAutoConfiguration
class SpringBootController implements InitLogger {
#GetMapping(value="/geohash")
public String getUserInput(ModelMap model) {
model.put("command", new Tuple());
return "UserInput";
}
#PostMapping(value="/geohash", params="SubmitWithDefault")
public String defaultUserInput(ModelMap model) {
model.put("command", tupleFill (48.104564, 20.800041, 6) );
return "UserInput";
}
#PostMapping(value = "/geohash", params="Submit")
public String printHash(#ModelAttribute("user")Tuple tuple,ModelMap model) {
GetData.setLat1(tuple.getFirstCoordinate());
GetData.setLon1(tuple.getSecondCoordinate());
GetData.setRad1(tuple.getRadius());
LocationExecute.calculate();
model.addAttribute("geoItemList", LocationExecute.getTupleList());
model.addAttribute("listSize", LocationExecute.getTupleList().size());
return "Geohash";
}
#PostMapping(value = "/geohash", params="reset", method = RequestMethod.GET)
public ModelAndView method() {
return new ModelAndView("redirect:geohash");
}
}
userinput.jsp - buttons
<input type="submit" name="Submit" value="Submit" style="height:25px; width:100px"/>
<input type="submit" name="SubmitWithDefault" value="Default Values" style="height:25px; width:100px">
geohash.jsp - (html table) reset button
<input type="reset" name="reset" value="Reset" style="height:30px; width:100px">
You need to implement PRG(Post -Redirect-Get) design pattern in MVC to solve the issue.
Please go through the below for more information
http://www.c-sharpcorner.com/UploadFile/dacca2/implement-prg-pattern-in-mvc-architecture/
So instead of returning view name redirect it so your problem will be solved, if you want some data to be sent to redirect method then use flashAttributes of spring
Solved it this way:
geohash.jsp
(added form:form tags)
<form:form action="/geohash">
<th> <input type="submit" name="reset" value="Reset" style="height:30px; width:100px"> </th>
</form:form>
Controller
(changed method to post)
#RequestMapping(value = "/geohash", params="reset", method = RequestMethod.POST)
public ModelAndView method() {
return new ModelAndView("redirect:geohash");
}
Currently I am struggling with the problem as below:
I have a program that will hold information on the electricity meters and their readings.
I wanted to create a form in which I can insert all the readings for all registered meters at once.
I am currently stuck at this point:
Here is my controller:
#RequestMapping("/registerEnergyReading")
public ModelAndView registerEnergyReading(#ModelAttribute("reading") Reading reading, BindingResult result) {
List<ElectricityMeter> meters= meterService.getMeterList();
Map<String, Object> model = new HashMap<String, Object>();
model.put("meters", meters);
System.out.println("Register Form");
return new ModelAndView("RegisterEnergyReading", "model", model);}
Now the jsp file would create a table dynamically based on how many meters are there.
That would be done by < c:forEach items="${meters}" var="meters" >
But the tricky part for me is how to pass these multiple entries for the next controller to be saved? What form should be used here?
#RequestMapping("/saveReadings")
public ModelAndView saveReadings(
#ModelAttribute("reading") List<Reading> reading, BindingResult result) {
for(Reading i:reading) {
readingService.saveReading(i);
}
return new ModelAndView("redirect:/najemcaLista.html");
}
Am I going the right direction here?
Appreciate your help,
Maciej
I got a bit further but got stuck.
My controller looks now:
#RequestMapping("/registerEnergyReading")
public ModelAndView registerEnergyReading(
#ModelAttribute("listReadingModel") ListReadingModel listReadingModel, BindingResult result) {
List<EnergyMeter> energyMetersList= meterService.getMeters();
List<EnergyReading> readings= new ArrayList<EnergyReading>();
for (int i = 0; i < energyList.size(); i++) {
EnergyReading reading= new EnergyReading ();
reading.setMeter(energyList.get(i));
readings.add(reading);
}
listReadingModel.setEnergyReadings(readings);
Map<String, Object> model = new HashMap<String, Object>();
model.put("energyMetersList", energyMetersList);
model.put("readings", readings);
return new ModelAndView("registerEnergyReading", "model", model);
}
#RequestMapping("/saveEnergyReading")
public ModelAndView saveEnergyReading(
#ModelAttribute("listReadingModel") ListReadingModel listReadingModel, BindingResult result) {
List<EnergyMeter> energyMetersList=listReadingModel.getEnergyReadings()
for (EnergyReading i : reading) {
readingService.saveReading(i);
}
return new ModelAndView("redirect:/energyReadingsList.html");
}
here is my view file:
<c:url var="listReadingModel" value="listReadingModel.html" />
<form:form id="listReadingModel" modelAttribute="listReadingModel" method="post" action="${listReadingModel}">
<table width="400px" height="150px">
<c:forEach items="${model.readings}" var="readings">
<tr>
<td>${readings.meter.description}</td>
<td><form:label path="${readingValue}">Reading Value</form:label></td>
<td><form:input path="${readingValue}" /></td>
<td><form:label path="${readingDate}">date</form:label></td>
<td><form:input type="date" path="${readingDate}" /></td>
</tr>
</c:forEach>
<tr>
<td colspan="6"><input type="submit" value="Save" /></td>
</table>
</form:form>
'
When I open the page in browser it all looks ok (there are as many fields as there should be) but when I press "save" I get java.lang.NullPointerException. It seems the form doesn't pass listReadingModel to controller. Any ideas how to solve it? Appologies for any typos. The code is in different language so I translated it on the go.
Regards, Maciej
If I understand you right, I think what you need is to create a wrapper class as
public class ListReadingModel {
private List<Reading> readings;
// Getter, setter
}
And then under your registerEnergyReading method, add this ListReadingModel to your Model.
ListReadingModel listReadingModel = new ListReadingModel ();
model.put("listReadingModel", listReadingModel);
You can bind your ListReadingModel to your form element in the jsp file.
<form:form method="POST" commandName="listReadingModel">
// add meters and readings here
When submitted your jsp you can call your controller like that:
#RequestMapping("/saveReadings")
public ModelAndView saveReadings(
#ModelAttribute("listReadingModel") ListReadingModel listReadingModel , BindingResult result) {
List<Reading> reading = listReadingModel.getReadings();
for(Reading i:reading) {
readingService.saveReading(i);
}
return new ModelAndView("redirect:/najemcaLista.html");
}
This can work but I did not try it. You can search named wrapper class on google to find more information.
I was being tasked to create my controllers without passing any parameters at the method signature.
I am quite baffled as this is quite challenge and I haven't really seen any examples at the net.
For example: from my jsp page.
<form:form method="POST" action="/project/searchResults" id="productSearchResultsForm">
<input name="productRecord" id="productRecord" />
<input name="resultEntity" id="resultEntity" type="hidden" />
<input name="resultCode" id="resultCode" type="hidden" />
<button type="submit" class="btn btn-primary btn-lg">Submit</button>
</form:form>
I wanted to pass these three inputs to my controller without using #RequestParameter and #ModelAttribute at the method signature. As of now this is the only way I know how to do this.
#RequestMapping(value = "/productSearch", method = RequestMethod.GET)
public ModelAndView init(#ModelAttribute ("showroomCode") String showroomCode, HttpServletRequest request) {
logger.info("<<<< initial page <<<<<<");
logger.info("Showroom Code : " + showroomCode);
HttpSession session = request.getSession();
ModelAndView model = new ModelAndView("productSearch", "command",
String.class);
ShowroomUser user = new ShowroomUser();
user.setUserId(1);
session.setAttribute("usersession", user);
session.setAttribute("showroomCode", showroomCode);
logger.info(">>>>> initial page >>>>> ");
return model;
}
I know that in Struts 2, you can just declare global variables in the Action class so you can automatically use them in the method without literally putting them in the method signature. Is there are way to remove this?
Thanks.
Update
I am asked not to use HttpServlet Request and Model Attributes at all anywhere in the code. :(
Please help!
1) Create a form POJO with your attribute productRecord, resultEntity, resultCode. Ex MyForm.java
2) Set this form in the model (in your init method) Ex : model.addAttribute("myForm", new MyForm())
3) In your jsp form declaration set :
<form:form commandName="myForm" >
4) In your controller (to retrieve result)
#RequestMapping(value = "/productSearch", method = RequestMethod.POST)
public ModelAndView postForm(MyForm myForm, HttpServletRequest request) {...}
Then you can access values using myForm.getProductRecord() for example.
I don't know why you'd ever want to do this..
But, Spring exposes the request as a ThreadLocal. You can access it on the current thread but you can't on any spawned threads without passing it.
Here's what you do:
#RequestMapping("/whatever")
public ModelAndView controllerMethod() {
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
// Do as you want with the request without having to pass it in
}
I have developed part of a application with Spring MVC.
In here i am loading some values from database to this jsp.
<div class="row">
<div class="col-sm-4">
<label class="input-label">Answer</label>
</div>
<div class="col-sm-8">
<div class="input-group">
<form:input class="form-control required" type="text" id="securityQuestionAnswer1" path="userSecurityQuestionList[0].securityQuestionAnswer"/>
</div>
</div>
</div>
This Jsp have one form and two submit buttons. I have added two different names and call the controller via those names.
and catch it with
#RequestMapping(method = RequestMethod.POST, params = {"next"})
#RequestMapping(method = RequestMethod.POST, params = {"update"})
after changing first loaded values in jsp (Security answer) when i submit the form it comes to correct controller. but it dont catch changed data in that text inputs. it catches old data what loaded when jsp loads. I have gone many debug tests. but same result.
my controller method is like this
#RequestMapping(method = RequestMethod.POST, params = {"update"})
public String updateSecurityQuections(#Valid #ModelAttribute(value = "userForm")ForogtPasswordForm forogtPasswordForm, BindingResult result,
ModelMap model, final RedirectAttributes redirectAttributes) throws AccountAlreadyRegisteredException,
AccountNotFoundException {
I want to know how to correctly catch(initialize) all the correct input data to this form in controller class.
Thanks in advance
Try putting method parameters in following order. It worked for me, sounds like yours is similar case.
RequestMapping(method = RequestMethod.POST, params = {"update"})
public String updateSecurityQuections(ModelMap model,#Valid #ModelAttribute(value = "userForm")ForogtPasswordForm forogtPasswordForm,
BindingResult result,
final RedirectAttributes redirectAttributes) throws AccountAlreadyRegisteredException,
AccountNotFoundException {
I am teaching myself Spring Form tags, and have run into what is probably a simple error that I haven't been able to solve. I get the following error when I launch this app in a browser:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'index' available as request attribute
I've tried most of the fixes that came up in a Google search to no avail. Can someone spot where I went wrong? Below are the relevant components. Thanks very much.
Controller:
#Controller
#RequestMapping("/registration")
public class LoginController {
#RequestMapping(method = RequestMethod.GET)
public String setupForm(ModelMap model) {
Registration registration = new Registration();
model.addAttribute("registration", registration);
return "index";
}
#RequestMapping(method = RequestMethod.POST)
public String onSubmit(#ModelAttribute("registration") Registration registration, Map model) {
return "success";
}
}
JSP (/index.jsp):
<form:form commandName="index">
<table border="0" cellspacing="12">
<tr>
<td>
<form:input path="email"/>
</td>
</tr>
<tr>
<td>
<form:password path="password"/>
</td>
</tr>
<tr>
<td>
<input type="submit" value="Submit"/>
</td>
</tr>
</table>
</form:form>
Command Object (Registration.java) :
public class Registration {
private String password;
private String email;
// getters,setters
Facing same issue few days back, What i understood from hit and trail is, Index page is a static page and no processing happens before the same is rendered. In case i want to use a form model binding in index page i should have a controller's handler method which will create a Registration object and place the same in ModelAndView before index.jsp is rendered
add a method in your controller like the below and try
#RequestMapping(method = RequestMethod.GET, value="/")
public ModelAndView initiate(){
ModelAndView objModView = new ModelAndView("/index.jsp");
objModView.addObject("registration",new Registration());
return objModView;
}
In your index page correct the following and try
<form:form commandName="index"> to <form:form commandName="registration">
You can also do it like this if the above does not work
<form:form modelAttribute="registration" commandName="registration">
Thanks
The error which is seen is because when you submit the form you have to have a Binding Result associated with the #ModelAttribute annotation.
Try changing you code to this :
#RequestMapping(method = RequestMethod.POST)
public String onSubmit(#ModelAttribute("registration") Registration registration, BindingResult result, Map model){
return "success";
}
Also note that the Binding Result object should be followed immediately after the Model Attribute.
And if you are using two #ModelAttributes then each one should have its own binding result object which follows it.
Please refer the spring source guide for all the related documentation
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html