Spring form ID field not populated on POST - java

In the below Spring form, my object's ID field is populated, but when I receive the submission in the controller method, all of the form's fields are populated except for the ID field. I've quintuple-checked that the field type and getter/setter types are all the same non-primitive, as I've seen many of the other questions on SO similar to this and that seems to be the common issue. The controller doesn't have any method-level #ModelAttributes, so it isn't being populated otherwise.
Here's the declaration of the POST method, as I debugged it on the first containing line and found that the form's id field is empty:
#RequestMapping(value="/{orgId}", method=RequestMethod.POST)
public String editOrganizationPost(#PathVariable int orgId,
#Valid #ModelAttribute(ORG_FORM) OrganizationForm orgForm,
BindingResult result, RedirectAttributes att,
HttpServletRequest request) {
Here's the form object:
public class OrganizationForm {
private Integer id;
#NotBlank
private String name;
#NotBlank
private String description;
private Set<User> users;
int moveToOrganizationId = 0;
String moveToOrganizationName;
int[] moveFromOrganizationUserSelect = null; // List of selected users
// to be moved to a new
// organization
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public int getMoveToOrganizationId() {
return this.moveToOrganizationId;
}
public void setMoveToOrganizationId(int moveToOrganizationId) {
this.moveToOrganizationId = moveToOrganizationId;
}
public String getMoveToOrganizationName() {
return this.moveToOrganizationName;
}
public void setMoveToOrganizationName(String moveToOrganizationName) {
this.moveToOrganizationName = moveToOrganizationName;
}
public int[] getMoveFromOrganizationUserSelect() {
return this.moveFromOrganizationUserSelect;
}
public void setMoveFromOrganizationUserSelect(
int[] moveFromOrganizationUserSelect) {
this.moveFromOrganizationUserSelect = moveFromOrganizationUserSelect;
}
public boolean isNew() {
return this.id == null || this.id == 0;
}
}
Here is the markup from the JSP file:
<form:form method="post" action="${submitUrl}" commandName="organizationForm">
<form:errors path="*" />
<form:hidden path="id" />
<table class="adminTable editContent">
<tr class="bg_lgtGrey">
<td><fmt:message
key="manageOrganizations.organizationForm.name" />:</td>
<td><form:input path="name" cssClass="inputbox"
tabindex="4" /></td>
</tr>
<tr class="bg_lgtGrey">
<td><fmt:message
key="manageOrganizations.organizationForm.description" />:</td>
<td><form:textarea path="description"
cssClass="inputbox" tabindex="4" /></td>
</tr>
<tr>
<td colspan="2" align="right"><c:choose>
<c:when test="${!organizationForm.new}">
<input type="submit" class="btn btn-primary"
id="submit_button" value="Update" />
</c:when>
<c:otherwise>
<input type="submit" class="btn btn-primary"
id="submit_button" value="Create" />
</c:otherwise>
</c:choose></td>
</tr>
</table>
</form:form>
And here is the generated HTML:
<form id="organizationForm" action="/admin/organizations/1" method="post">
<input id="id" name="id" type="hidden" value="1">
<table class="adminTable editContent">
<tbody><tr class="bg_lgtGrey">
<td>Organization Name:</td>
<td><input id="name" name="name" class="inputbox" tabindex="4" type="text" value="Organization1"></td>
</tr>
<tr class="bg_lgtGrey">
<td>Organization Description:</td>
<td><textarea id="description" name="description" class="inputbox" tabindex="4"></textarea></td>
</tr>
<tr>
<td colspan="2" align="right">
<input type="submit" class="btn btn-primary" id="submit_button" value="Update">
</td>
</tr>
</tbody></table>
</form>
I used Chrome devtools to catch the POST data and here it is:
id=1&name=Organization1&description=
...yet at the breakpoint at the first line of the editOrganizationPost method, the form.id field is set to 0.
I have spent forever trying to figure out why it will bind the name and description but not the ID when sent. I could obviously just inject the ID from the path variable but I am dumbfounded as to why it wouldn't just populate the field naturally.

I had the same problem.. the id field would always be set to 0. Changing the id field to something else didn't work either. After more hit and trail, removing
disabled="true"
from
<form:input path"id" disabled="true"/>
fixed the issue.
I assumed
<form:hidden path="id">
would give the same error but it didn't.

Related

Attempting to make a button in thymeleaf that increments a user's balance

Attempting to make have options for the user that they can press a few buttons to increase the current "balance" of the "buyer". As of now, my buttons do nothing and I'm sure there is extremely stupid I'm doing on a rather easy thing. Thanks for any help in advance.
Entity:
#Entity
#Table(schema = "toner_buyer")
public class Buyer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "BUYER_ID")
private Long buyerId;
#Column(name = "FIRST_NAME")
private String firstName;
#Column(name = "LAST_NAME")
private String lastName;
#Column(name = "BUYER_ADDRESS")
private String buyerAddress;
#Column(name = "BUYER_BALANCE")
private int balance;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "buyer")
private Set<Toner> toners;
public Buyer(){}
public Buyer(String firstName, String lastName, String buyerAddress, int balance) {
this.firstName = firstName;
this.lastName = lastName;
this.buyerAddress = buyerAddress;
this.balance = balance;
}
public Buyer(String firstName, String lastName, String buyerAddress, int balance, Set<Toner> toners) {
this.firstName = firstName;
this.lastName = lastName;
this.buyerAddress = buyerAddress;
this.balance = balance;
this.toners = toners;
}
public Set<Toner> getToners() {
return toners;
}
public void setToners(Set<Toner> toners) {
this.toners = toners;
}
public Long getBuyerId() {
return buyerId;
}
public void setBuyerId(Long buyerId) {
this.buyerId = buyerId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getBuyerAddress() {
return buyerAddress;
}
public void setBuyerAddress(String buyerAddress) {
this.buyerAddress = buyerAddress;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
}
Controller:
#Controller
public class BuyerController {
private BuyerService buyerService;
#Autowired
private TonerService tonerService;
#Autowired
public void setBuyerService(BuyerService buyerService){
this.buyerService = buyerService;
}
#RequestMapping("/add-buyer")
public String showBuyerPager(Model model){
//List
List<Buyer> buyers = buyerService.findAllBuyers();
List<Toner> toners = tonerService.findAllToners();
//sending list to view
model.addAttribute("buyers", buyers);
model.addAttribute("toners", toners);
//creating objects in view
model.addAttribute("buyer", new Buyer());
model.addAttribute("toner", new Toner());
return "add-buyer";
}
#GetMapping("/showBuyerForm")
public String addBuyerForm(Model model){
model.addAttribute("buyer", new Buyer());
model.addAttribute("toner", new Toner());
model.addAttribute("buyerId", new Buyer().getBuyerId());
return "add-buyer";
}
#PostMapping("/addBuyer")
public String postBuyerForm(#ModelAttribute("buyer") Buyer buyer, Model model){
buyerService.saveBuyer(buyer);
model.addAttribute("buyer", new Buyer());
return "redirect:/";
}
#PostMapping("/deleteBuyer/{id}")
public String deleteBuyer(#PathVariable Long id){
buyerService.deleteBuyer(id);
return "redirect:/";
}
#PostMapping("/addToBuyerBal/{id}")
public String addToBuyerBalance(Model model, #PathVariable Long id, #ModelAttribute("add") int add){
Buyer mBuyer = buyerService.findOne(id);
mBuyer.setBalance(mBuyer.getBalance() + add);
return "redirect:/";
}
#PostMapping("/purcahseToner/{toner}")
public String buyToner(#PathVariable Toner toner){
Buyer buyer = new Buyer();
return "redirect:/";
}
#PostMapping("/saleToner/{toner}")
public String saleToner(){
return "redirect:/";
}
}
Thymeleaf view:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Title</title>
<link href="styles.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<header> Welcome to Toner Stock </header>
<h1>Add Buyer</h1>
<div id="mynav" align="center">
<ul>
<li>Home</li>
<li>Add Buyer</li>
<li>Add Manager</li>
<li>Current Stock</li>
<li>Transactions</li>
</ul>
</div>
<div id="display-table" align="center">
<form th:action="#{/addBuyer}" th:object="${buyer}" style="width:100%" method="post">
<table>
<td><label>First Name: </label></td>
<td><input type="text" th:field="*{firstName}"/></td>
<td><label>Last Name: </label></td>
<td><input type="text" th:field="*{lastName}"/></td>
<td><label>Enter Address: </label></td>
<td><input type="text" th:field="*{buyerAddress}"/></td>
<td><input type="submit" value="save"/></td>
</table>
</form>
</div>
<div>
<div>
<table id="info-table" align="center" border="1">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Address</th>
<th>Select Toner</th>
<th>Current Balance</th>
<th>Add to Balance</th>
<th>Delete Buyer</th>
<th>Purchase Item</th>
<th>Sale Item</th>
</tr>
<tr th:each="buyer : ${buyers}">
<td th:text="${buyer.firstName}"></td>
<td th:text="${buyer.lastName}"></td>
<td th:text="${buyer.buyerAddress}"></td>
<td>
<select>
<option th:each="toner : ${toners}"
th:text="${toner.tonerName}"
th:value="${toner.id}">
</option>
</select>
</td>
<td th:text="${buyer.balance}"></td>
<td>
<form th:action="#{/addToBuyerBal/{id}(id=${buyer.buyerId})}" th:object="${buyer}" method="post">
<button type="submit" value="25" onclick="return confirm('Are you sure you want to pay $25?')">$25</button>
<button type="submit" value="50" onclick="return confirm('Are you sure you want to pay $50?')">$50</button>
<button type="submit" value="100" onclick="return confirm('Are you sure you want to pay $100?')">$100</button>
</form>
</td>
<td>
<form th:action="#{/deleteBuyer/{id}(id=${buyer.buyerId})}" th:object="${buyer}" method="post">
<input type="hidden" th:field="${buyer}">Delete</input>
<button type="submit" onClick="return confirm('Are you sure you want to delete a Manager?')"/>
</form>
</td>
<td>
<form th:action="#{/purcahseToner/{toner}(toner=${buyer.toners})}" th:object="${buyer}" method="post">
<input type="hidden" th:field="*{toners}">Purchase</input>
<button type="submit" onclick="return confirm('Are you sure you want to make this purchase?')"/>
</form>
</td>
<td>
<form th:action="#{/saleToner/{toner}(toner=${buyer.toners})}" th:object="${buyer}" method="post">
<input type="hidden" th:field="*{toners}">Sale</input>
<button type="submit" onclick="return confirm('Are you sure you want to sale this?')"/>
</form>
</td>
</tr>
</table>
</div>
</div>
</body>
</html>

CRUD in controller is not deleting row correctly

I was able to create values and store into my db, which displays a view of the list of values stored and additional values that is written into a input will automatically show in the table.
Controller
#Controller
public class AppPortController {
private ApServerService apServerService;
#Autowired
public void setApServerService(ApServerService apServerService) {
this.apServerService = apServerService;
}
#RequestMapping(value = "/editApServer", method = RequestMethod.GET)
public String list(Model model) {
model.addAttribute("apList", apServerService.listAllApServerModels());
return "editApServer";
}
#RequestMapping("editApServer/update/{id}")
public String update(#PathVariable String id, Model model) {
model.addAttribute("apList", apServerService.getApServerModelById(id));
return "editApServer";
}
#RequestMapping("editApServer/new")
public String newServer(Model model){
model.addAttribute("apServer", new ApServerModel());
return "editApServer";
}
#RequestMapping(value = "/addServer", method = RequestMethod.POST)
public String addServer(#ModelAttribute ApServerModel apServerModel) {
apServerService.saveApServerModel(apServerModel);
return "redirect:editApServer";
}
#RequestMapping("editApServer/delete")
public String delete(#PathVariable String host){
apServerService.deleteApServerModel(host);
return "redirect:editApServer";
}
Repository
public interface AppPortRepository extends CrudRepository<ApServerModel, String> {}
POJO
#Document(collection = "apDBServer")
public class ApServerModel {
#Id
private String id;
private String host;
private String port;
//getters and setters
HTML SNIPPET
<table>
<thead>
<tr>
<th> Host Name </th>
<th> Port Name</th>
<th>Id</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr th:each="ApServerModel : ${apList}">
<td th:text ="${ApServerModel.host}"></td>
<td th:text ="${ApServerModel.port}"></td>
<td th:text ="${ApServerModel.id}"></td>
<td><a th:href="${'editApServer/update/' + ApServerModel.id}">Edit</a></td>
<td><a th:href="${'editApServer/delete'}">Delete</a></td>
</tr>
</tbody>
</table>
<br />
<h2>Add AppPortServer</h2>
<form action="/addServer" method="POST">
Host <input type="text" id="host" name="host" /><br />
Port <input type="text" id="port" name="port" /><br />
<input type="submit" />
</form>
Problem
In my controller the delete would not execute(it is not doing what I want it to do). but line below it redirects me back to the same page.
What am I doing wrong? I have been savaging through the internet trying to find the crud functions for mongodb using springboot. Logically speaking why wouldn't my delete work if I follow the logic of the create?
I followed Tutorial, for posting to a table. Then I followed
Tutorial 2 That implements my delete and update. But It does not delete the values.

Property 'id' not found on type com.spring.schoolmanagement.model.Subject

I'm trying to put two objects in my JSP view but while getting the value by getter is working fine and while referring the value by property of the object throws error.
JSP Code Snipet is:
<div class="row">
<div class="box">
<div class="col-lg-12">
<hr><h2 class="intro-text text-center">Manage Subject</h2><hr>
</div>
<div class="col-md-12">
<c:url var="addAction" value="/data-entry/subject/add" ></c:url>
<form:form action="${addAction}" commandName="subject">
<table>
<c:if test="${!empty subject.name}">
<tr>
<td>
<form:label path="id">
<spring:message text="ID"/>
</form:label>
</td>
<td>
<form:input path="id" readonly="true" size="8" disabled="true" />
<form:hidden path="id" />
</td>
</tr>
</c:if>
<tr>
<td>
<form:label path="name">
<spring:message text="Name"/>
</form:label>
</td>
<td>
<form:input path="name" />
</td>
</tr>
<tr>
<td>
<form:label path="description">
<spring:message text="Description"/>
</form:label>
</td>
<td>
<form:input path="description" />
</td>
</tr>
<tr>
<td colspan="2">
<c:if test="${!empty subject.name}">
<input type="submit"
value="<spring:message text="Edit Subject"/>" />
</c:if>
<c:if test="${empty subject.name}">
<input type="submit"
value="<spring:message text="Add Subject"/>" />
</c:if>
</td>
</tr>
</table>
</form:form>
<br>
<h3>Subject List</h3>
<c:if test="${!empty subjectlist}">
<table class="tg">
<tr>
<th>ID</th>
<th>Name</th>
<th>Description</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<c:forEach items="${subjectlist}" var="subject">
<tr>
<td>${subject.getID()}</td>
<td>${subject.getName()}</td>
<td>${subject.getDescription()}</td>
<td><a href="<c:url value='/admin/subject/edit/${subject.getID()}' />" >Edit</a></td>
<td><a href="<c:url value='/admin/subject/remove/${subject.getID()}' />" >Delete</a></td>
</tr>
</c:forEach>
</table>
</c:if>
</div>
</div>
</div>
Model Class:
package com.spring.schoolmanagement.model;
public class Subject {
private int id;
private String name;
private String description;
public void setID(int id) {
this.id = id;
}
public int getID() {
return this.id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setDescription( String description ) {
this.description = description;
}
public String getDescription() {
return this.description;
}
#Override
public String toString(){
return "{ID=" + id + ",Name=" + name + ",Description=" + description + "}";
}
}
Controller Class:
package com.spring.schoolmangement;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.spring.schoolmanagement.dao.SubjectDAOImpl;
import com.spring.schoolmanagement.model.Subject;
/**
* Handles requests for admin specific pages.
*/
#Controller
public class AdminController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
#Autowired
private SubjectDAOImpl subjectService;
/**
* Simply selects the home view to render by returning its name.
*/
#RequestMapping(value = {"/admin/", "/admin"}, method = RequestMethod.GET)
public String home(Locale locale, Model model) {
return "admin-dash-board";
}
#RequestMapping(value = "/admin/student")
public String student(Model model) {
return "admin-student";
}
#RequestMapping(value = "/admin/subject")
public String displaySubjects(Model model) {
model.addAttribute("subject", new Subject());
model.addAttribute("subjectlist", this.subjectService.getAll());
return "manage-subject";
}
#RequestMapping(value = "/admin/subject/edit/{id}")
public String course(#PathVariable("id") int id, Model model) {
model.addAttribute("subject", this.subjectService.getById(id));
model.addAttribute("subjectlist", this.subjectService.getAll());
return "manage-subject";
}
}
Please suggest where I'm making the mistake.
Change your getter/setter method from:
public void setID(int id) {
this.id = id;
}
public int getID() {
return this.id;
}
To
public void setId(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
Your Bean is missing naming convention and should follow JavaBean (read pdf section 8.8) naming convention.

Binding form data to a list of objects with Java Play 2

I have a table in a form that I want to bind each row to an object and then add that object to a list on the server side, but when I do form.bindFromRequest(), I get null values and I can't figure out the binding. The following is my HTML/form.
<tr>
<td><input type="hidden" value="#domains(i).id" name="domains[#i].domainId" readonly></td>
<td><input type="text" value="#domains(i).domain" name="domains[#i].domain"></td>
<td><input type="text" class="no-default-datepicker" value="#domains(i).date.format("yyyy-MM-dd")" name="domains[#i].date" /></td>
<td><input type="hidden" value="#domains(i).cycle" name="domains[#i].cycle">#domains(i).cycle</td>
<td>#defining(if (domains(i).blacklist == true) "checked" else "") { checked =>
<input name="domains[#i].blacklist" type="checkbox" #checked />}
<input type="hidden" name="domains[#i].blacklist" value="false"></td>
<td><input type="text" value="#domains(i).source" name="domains[#i].source"></td>
#for( x <- domains(i).results.indices){
<td><input type="text" value="#domains(i).harvestResults(x).results" name="domains[#i].results[#x].results"></td>
}
</tr>
Edit: Server-side code, but it's wrong and doesn't work. I can't get the harvestResults subclass to bind when I get the form.
public static Result update(){
Form<EditClass> form = form(EditClass.class).bindFromRequest();
EditClass ec = form.get(); //problem starts here, the harvestResults won't work.
return redirect("/search");
}
Data model:
public class Domain {
public static class HarvestInformation{
#JsonProperty("_id")
public String id;
public String name;
public String results;
}
#JsonProperty("_id")
public String id;
public String domain;
public Boolean bl;
public String source;
public Date date;
public Integer cycle;
public List<HarvestInformation> harvestResults;
}

Implementing a java bean into a jsp servlet

I am trying to connect my JSP servlets to a posgress database and I am currently using a java bean class which is playing the role of the middle man. I am experiencing some difficulties with making the registration form successfully store user information into the database. I would really appreciate if you would kindly help me out.
Thanks a lot in advance.
JSP servlet:
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Register here</title>
</head>
<body>
<form method="post" action="registration.jsp">
<center>
<table border="1" width="30%" cellpadding="5">
<thead>
<tr>
<th colspan="2">Enter Information Here</th>
</tr>
</thead>
<tbody>
<tr>
<td>First Name</td>
<td><input type="text" name="fname" value="" /></td>
</tr>
<tr>
<td>Last Name</td>
<td><input type="text" name="lname" value="" /></td>
</tr>
<tr>
<td>Email</td>
<td><input type="text" name="email" value="" /></td>
</tr>
<tr>
<td>User Name</td>
<td><input type="text" name="uname" value="" /></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="pass" value="" /></td>
</tr>
<tr>
<td>Current Country</td>
<td><input type="text" name="country" value="" /></td>
</tr>
<tr>
<td>Current City</td>
<td><input type="text" name="city" value="" /></td>
</tr>
<tr>
<td><input type="submit" value="Submit" /></td>
<td><input type="reset" value="Reset" /></td>
</tr>
<tr>
<td colspan="2">Already have an account? Login Here</td>
</tr>
</tbody>
</table>
</center>
</form>
</body>
The Java Bean that I use :
public class UserBean {
private int id;
private String username;
private String password;
private String email;
private String firstName;
private String lastName;
private String endDate;
private boolean validated;
public UserBean() {
// Empty constructor
}
public int getId() {
return id;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getEmail() {
return email;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEndDate() {
return endDate;
}
public boolean isValidated() {
return validated;
}
public void setId(int id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setEmail(String email) {
this.email = email;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public void setValidated(boolean validated) {
this.validated = validated;
}
}
Your POJO JavaBean won't magically get populated with the data. It has no connection to the database and no way to get or save data.
You need a controller that fetches data from the DB, creates model objects, and populates them with the data. The controller is also responsible for saving beans
You could write this yourself but it's generally better to use existing ORM frameworks like JPA2, a custom persistence provider API like Hibernate, or something like MyBatis. If you really want, you can hand-roll your controller with direct JDBC calls, injecting the connection from the environment, but that tends to produce a lot of boilerplate code for little benefit even with things like Spring JDBC to help smooth things over.
Some IDEs, like NetBeans and Eclipse, can even auto-generate models and controllers for you, though I've never been very happy with the results (particularly the failure to use a parent-class and generic methods and the lack of any sort of useful error handling).

Categories