How to pass data to from view to controller in Spring-MVC? - java

I have a list of objects as JSON which is inside a workLists. I created a table by iterating using each on workLists and create a table in thymeleaf?
Now how can I pass work that is a single object back to the controller, what I tried is using th:object
I thought it would work but on the controller end null values are coming.
Thymeleaf section
<tr th:each="work , status : ${workLists}">
<td scope="row" th:text="${status.count}"></td>
<td>
<form th:action="#{/edit/work}" th:object="${work}" method="post">
<button type="submit" class="dropdown-item">Edit</button>
</form>
</td>
</tr>
Controller Section
#PostMapping("/edit/work")
public String editWork(#ModelAttribute("work") GetWorkkDto getWorkDto){
logger.debug(" Inside of edit work method");
return "listOfwork";
}

You need to give the contoller 2 attribues which are the workLists and a work. It will be something like:
#GetMapping("/edit/work")
public String editWork(Model model){
model.addAttribute("workLists", workLists);
model.addAttribute("workDTO", new Work());
return "listOfwork";
}
Then in your HTML page through hidden fields you give the values of the work selected:
<table>
<tr th:each="work, stat : ${workLists}">
<td>
<form action="#" th:action="#{/edit/work}" th:object="${workDTO}" method="post">
<input type="hidden" th:attr="name='id'" th:value="${work.id}" />
<input type="hidden" th:attr="name='name'" th:value="${work.name}" />
<input type="hidden" th:attr="name='description'" th:value="${work.description}" />
<p th:text="'Id : '+${work.id}"></p>
<p th:text="'Name : '+${work.name}"></p>
<p th:text="'Description : '+${work.description}"></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</td>
</tr>
</table>
You can see in the proposed code that I give the value of work.id to the workDTO.id through the name attribute (don't ask me why it is like this)
Finaly you retrieve the object in your controller (as you do already) with something like this:
#PostMapping("/edit/work")
public String editWork(#ModelAttribute Work workDTO, Model model){
System.out.println(workDTO.toString());
model.addAttribute("workLists", workLists);
model.addAttribute("workDTO", new Work());
return "listOfwork";
}

Related

why is my form not passing information in spring boot

Hello i am passing information in a form and everything runs fine but when i fill out the form it doesnt not pass the information and i am getting this error.
There was an unexpected error (type=Internal Server Error, status=500).
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
Caused by: java.sql.SQLIntegrityConstraintViolationException: Column 'movie_id' cannot be null
the code i am using is as folow:
#PostMapping("/save")
public String save(Movie movie) {
savedMovie.save(movie);
return "redirect:/LatestMovies";
}
And
<form th:action="#{/save}" method="post" >
<p><input type="text" id="movie_id" name="movie_id" value="" /></p>
<p><input type="text" id="movie_name" name="movie_name" value="" /></p>
<p><input type="submit" value="save" /></p>
</form>
i belive all other code is correct becuase if i try to render the db information i have no problem.
Update
This is the complete html code.
<div class="container">
<table class="table table-hover">
<tr>
<th>Id</th>
<th>Name</th>
</tr>
<tr th:each="LatestMovies : ${latestMovies}">
<td th:text="${LatestMovies.id}"></td>
<td th:text="${LatestMovies.movieName}"></td>
<td>
<form th:action="#{/save}" method="post" th:object="${newMovie}">
<p><input type="text" id="movie_id" th:field="*{movie_Id}"/></p>
<p><input type="text" id="movie_name" th:field="*{movie_Name}"/></p>
<p><input type="submit" value="save" /></p>
</form>
</td>
</tr>
</table>
Your controller is expecting a Movie object, but it is receiving something else, which then produces a null Movie object. You need to use th:object in your form in order to correctly send the respective class. First, let's add a new #ModelAttribute to your controller, so that your form can automatically map your Movie object in your form.
Controller
// In order to use th:object in a form, we must be able to map a new entity to that form.
// In this case we return a Movie entity.
#ModelAttribute(value = "newMovie")
public Movie newMovie() {return new Movie();}
Now, let's change your form, so that it actually sends a Movie object.
<form th:action="#{/save}" method="post" th:object="${newMovie}">
<p><input type="text" id="movie_id" th:field="*{movie_id}"/></p>
<p><input type="text" id="movie_name" th:field="*{movie_name}"/></p>
<p><input type="submit" value="save" /></p>
</form>
Note that I also changed the name attribute in your inputs, for th:field. Have in mind that in order for this to work, the name of each field must match exactly the names in your objects.
Update
In case you want to set a default value to your form, without using js and since you can't combine th:field with th:value, you could set the object's attribute in your controller.
#ModelAttribute(value = "newMovie")
public Movie newMovie() {
Movie movie = new Movie();
movie.setName("Test");
return movie;
}
Update 2
If what you want is to put the current iteration of a Thymeleaf list in your form, you can do the following.
<div class="container">
<table class="table table-hover">
<tr>
<th>Id</th>
<th>Name</th>
</tr>
<tr th:each="LatestMovies : ${latestMovies}">
<td th:text="${LatestMovies.id}"></td>
<td th:text="${LatestMovies.movieName}"></td>
<td>
<form th:action="#{/save}" th:object="${LatestMovies}" method="post">
<p><input type="hidden" th:value="*{id}"/></p>
<p><input type="hidden" th:value="*{movieName}"/></p>
<p><input type="submit" value="Submit"/></p>
</form>
</td>
</tr>
</table>
You forgot to mark method param with #RequestBody annotation.
This happens because the movie object you are trying to send from the form to the controller is not mapped properly. This has as a result the constraint of the movie_id you have in your movies table (PK not null I guess) to be violated by trying to insert a not null value into it. If you want the object formed in the frontend page form to be binded in a java object you could try this
front page form
<form:form action="save" modelAttribute="movie" method="POST">
<form:label path = "movie_id"> Movie id</form:label>
<form:input path="movie_id" name="movie_id">
<form:label path = "movie_name"> Movie name</form:label>
<form:input path="movie_name" name="movie_name">
<button type="submit">save</button>
</form:form>
(you should import on your page the springframework form taglib
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>)
Save controller code
#PostMapping("/save")
public String save(#ModelAttribute("movie") Movie movie) {
savedMovie.save(movie);
return "redirect:/LatestMovies";
}
Of course I am assuming that your object has a similar structure like shown below
Movie class
public class Movie{
private String movie_id; // or int or long
private String movie_name;
//getters setters constructors ommitted
}

Unable to bind list variable from thymleaf view in spring mvc

I am binding a list to field from thymleaf view, but getting null in the controller. Consider it is not null in view.
<form th:object="${obj}"
<input type="hidden" th:field="*{someList}" th:value="${obj.getSomeList()}">
POJO is like this:
public class Foo {
private int id;
private List<Some> someList;
//setter getter
}
If I bind the id in same way I am getting it in controller, pls help If I have take special care for List.
My controller:
#RequestMapping
public String bar(#ModelAttribute("obj") Foo foo)
Hi Anil after setting the values to a variable you need to iterate through the list using the each tag
Pls find the syntax
<form th:object="${obj}" th:action="#{/list}" action="void(0)" method="post">
<tr>
<td th:field="*{id}" th:text="${obj.id}" />
</tr>
<tr th:each="l , i : ${obj.someList}">
<input type="hidden" th:field="*{someList[__${i.index}__].something}" />
</tr>
<input type="submit" class="btn btn-success" />
</form>

How to get checked boxes in a Controller

I have got a html page (with Thymeleaf):
<form action="#" th:action="#{/changeme}">
<fieldset>
<table style="width: 500px">
<tr th:each="esfield : ${esfields}">
<td>
<div>
<div class="checkbox">
<input type="checkbox" name="optionsMulti"
th:text="${esfield}" />
</div>
</div>
</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td>
<button type="submit"
class="btn btn-xs btn-primary margin10-right paddingNew"
name="save">Calculate!</button>
</td>
<td></td>
</tr>
</table>
</fieldset>
</form>
When I click Calculate! it goes to my controller
#RequestMapping(value = "/changeme", params = { "save" })
public String save(final ModelMap m) {
m.addAttribute("centers", /*params*/);
return "clustering";
}
I would like to get information about checked boxes in my controller?
How can I do that?
Thank you in advance
You have basically two options :
either you use a different name for each checkbox
or you use spring tag <form:checkbox> instead of native <checkbox>
If you don't posted data will not allow you to know exactly what boxes were actually checked (excepted in cases all and none)
With the approach, you should use in your controller a #ModelAttribute annotated object containing a List<Boolean> and spring will automagically populate it with the values of your checkboxes.
#RequestMapping(value = "/changeme", params = { "save" })
public String save(#ModelAttribute BoxesForm form, final ModelMap m) {
// do what you need with form.getCheckboxes() ...
m.addAttribute("centers", /*params*/);
return "clustering";
}
public class BoxesForm {
List<Boolean> checkboxes;
// getter and setter omitted ...
}

Spring MVC getting value of element that is not an object property on the server

I have a jsp page which uses spring tag lib. I have elements on he page that is bind to properties of an object. I also have button values that are not bind to the POJO i am trying to get these values on the server. Under is the code
JSP
<body>
<form:form id="monitoringList" name="monitoringList" commandName="monitoring">
<h3>Monitoring For Criminals Victims/Wittiness</h3>
<h3>Crime Record - ${crimeRecNo}</h3>
<div id="victims">
<h3>Victims</h3>
<hr>
<input type="hidden" id="records" value="${records}"/>
<div id="citizen_row">
<label class="name"></label>
<form:input class="citizen" type="hidden" name="socialSecurityNumber" path="socialSecurityNumber"/>
<table border="1">
<tr>
<td><form:input type="hidden" path="crimeRecNo" name = "crimeRecNo"/>
<canvas id="photoCvs${citizen.socialSecurityNumber}" class="canvas" height="200" width="200"></canvas></td>
<td><label>Start Date : </label><form:input name= "monitoringStDate" path="monitoringStDate" id="monitoringStDate"/></td>
<td><label>End Date : </label><form:input name="monitoringEndDate" path="monitoringEndDate" id="monitoringEndDate"/></td>
<td>
<label>Monitoring Type : </label>
<form:select path="monitoringTypeId" name="monitoringTypeId" id="monitoringTypeId" title="Monitoring Type">
<form:options items="${monitoringType.monitoringTypeList}" itemValue="monitoringTypeId" itemLabel="monitoringTypeDesc" />
</form:select>
</td>
</tr>
</table>
<div><button id="action" onclick="submitPage('${pageContext.request.contextPath}/monitoringList.htm','POST');" type="button">Create Monitoring Records</button></div>
</div>
<!-- MySql first record starts at 0. So we need to send in the value 0 to get the first record. Create Record Navigation based on record count -->
<div id= "recordNavigation">
<c:forEach begin="0" end="${records - 1}" var="i">
<input type="submit" class="navigationbtns" id="page" onclick="submitPage('${pageContext.request.contextPath}/monitoringList.htm','POST');" value="${i}"/>
</c:forEach>
</div>
</div>
</form:form>
</body>
This is the controller and i am using request.getParameter to get the value of the button however the value id null when i click on the button which post me to the server
Controller
#RequestMapping(value = "monitoringList.htm", method = RequestMethod.POST)
public ModelAndView handleNextMonitoringPage(#ModelAttribute("crimeRecNo")Integer crimeRecNo, Model model,#ModelAttribute Monitoring monitoring, BindingResult result,ModelMap m,HttpServletRequest request,SessionStatus status, HttpSession session) throws Exception {
String p_page = request.getParameter("page");
logger.info("Page request was ::" + p_page);
//int page = 0;
myMonitoringTypeList.put("monitoringTypeList",this.monitoringTypeManager.getListOfMonitoringType());
model.addAttribute("monitoringType",myMonitoringTypeList);
Monitoring aMonitoringRecord = new Monitoring();
aMonitoringRecord = this.monitoringManager.getAMonitoringRecByCrimeRecNo(crimeRecNo, page);
int recordCount = this.monitoringManager.MonitoringRecords_RecordCount(crimeRecNo);
model.addAttribute("records",recordCount);
model.addAttribute("crimeRecNo", crimeRecNo);
model.addAttribute("monitoring", aMonitoringRecord);
return new ModelAndView(new RedirectView("monitoringList.htm"),"page",page);
}
you are missing the name attribute under which the value is being submitted
<button name="page" ....>
and
<input type="submit" name="page" ..../>

Binding objects to controls on JSP pages

I have the following class that I'm using in my Java with JSP applicaton.
//
public class QuestionBO implements Serializable{
private int questionId;
private int testID;
private String question;
private TutorBO infoAboutTutor;
private SubjectBO infoAboutSubject;
private TestBO infoAboutTest;
private List<AnswerBO> answers;
public QuestionBO() {
}
public QuestionBO(String question) {
this.question = question;
}
getter & setter....
The JSP page has a form where each Question (its String representation) has a checkbox next to it. A user marks some of the questions and submits the form to the server for processing by a servlet.
What is the conventional way of binding the Question objects with the checkboxes so that I could find out what Questions have been selected?
Currently I'm using the following approach for constructing the form:
//
<c:if test="${not empty questionsForSubject}">
<form action="/TutorWebApp/controller" method="POST" name="addQuestionForm">
<input type="hidden" name="command" value="add_question_list" />
<input type="hidden" name="testName" value="${testName}"/>
<table border ="1">
<tbody>
<c:forEach items="${questionsForSubject}" var="question">
<tr>
<td>
<input type="checkbox" name ="choosen_question"
value="${question.getQuestion()}">
${question.getQuestion()}
<br />
</td>
</tr>
</c:forEach>
</tbody>
</table>
<input type="submit" value="Add questions "/>
</form>
And I shouldn't use frameworks.
Thanks
And I have last question
<c:if test="${not empty questionsForSubject}">
<form action="/TutorWebApp/controller" method="POST" name="addQuestionForm">
<input type="hidden" name="command" value="add_question_list" />
<input type="hidden" name="testName" value="${testName}"/>
<input type="hidden" name="questionsForSubject" value="${questionsForSubject}"/>
<table border ="1">
<tbody>
<c:forEach items="${questionsForSubject.keySet()}" var="questionID">
<tr>
<td>
<input type="checkbox" name ="choosen_question" value="${questionID}">
${questionsForSubject.get(questionID).getQuestion()}
<br />
</td>
</tr>
</c:forEach>
</tbody>
</table>
<input type="submit" value="Добавить вопросы"/>
</form>
How I can get map from this page on servlet?
Give each checkbox an unique value. For example, the unique question identifier:
<c:forEach items="${questionsForSubject}" var="question">
<tr>
<td>
<input type="checkbox" name="chosen_question" value="${question.questionId}" />
${question.question}
<br />
</td>
</tr>
</c:forEach>
This way you'll be able to grab all checked values by just the following call in the servlet:
String[] chosenQuestions = request.getParameterValues("chosen_question");
Generate an unique name for each checkbox as follows:
<input type="checkbox" name="${question.questionId}" />
or:
<input type="checkbox" name="choosen_question_${question.questionId}" />
After that, you're already able to identify each checkbox in your servlet

Categories