Spring Validator for duplicate record in database - spring

In my page jsp, i have a form where i can add a user to my database, and i use a validator to show errors when fields are empty, but what i want to do is, when i insert a duplicate entry of the primary key of my table, the validator show me a message that this login for example is already taken instead having an error by Apache!
this is my User POJO :
package gestion.delegation.domaine;
import java.io.Serializable;
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
int id;
String nom;
String prenom;
String login;
String password;
String role;
boolean enable;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getPrenom() {
return prenom;
}
public void setPrenom(String prenom) {
this.prenom = prenom;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean getEnable() {
return this.enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public User(int id, String nom, String prenom, String login,
String password, String role, boolean enable) {
super();
this.id = id;
this.nom = nom;
this.prenom = prenom;
this.login = login;
this.password = password;
this.role = role;
this.enable = enable;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public User() {
super();
}
}
and this is my validator :
package gestion.delegation.validator;
import gestion.delegation.domaine.User;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
public class AddUserValidator implements Validator{
#Override
public boolean supports(Class<?> clazz) {
return User.class.isAssignableFrom(clazz);
}
#Override
public void validate(Object obj, Errors err) {
ValidationUtils.rejectIfEmptyOrWhitespace(err, "nom", "name.required","Choisissez un nom");
ValidationUtils.rejectIfEmptyOrWhitespace(err, "prenom", "prenom.required", "Choisissez un prenom");
ValidationUtils.rejectIfEmptyOrWhitespace(err, "login", "login.required", "Choisissez un login");
ValidationUtils.rejectIfEmptyOrWhitespace(err, "password", "password.required", "Choisissez un password");
ValidationUtils.rejectIfEmpty(err, "role", "role.required", "Choisissez un role");
}
}
the form :
<c:if test="${not empty msg_success}">
<div class="success">Vous avez ajouter un utilisateur avec
succès !</div>
</c:if>
<form:form name="ajf"
action="${pageContext.request.contextPath}/ajouter_user"
method="post" commandName="user">
<table id="tabmenu">
<tr>
<td id="idtab">Nom :</td>
<td><form:input type="text" path="nom"
class="round default-width-input" name="name_" /></td>
<td><form:errors path="nom" Class="errorbox" /></td>
</tr>
<tr>
<td id="idtab">Prénom :</td>
<td><form:input type="text" path="prenom" name="prenom_"
class="round default-width-input" /></td>
<td><form:errors path="prenom" cssClass="errorbox" />
</tr>
<tr>
<td id="idtab">Login :</td>
<td><form:input type="text" path="login" name="login_"
cssClass="round default-width-input" /></td>
<td><form:errors path="login" cssClass="errorbox" /></td>
</tr>
<tr>
<td id="idtab">Password :</td>
<td><form:input type="password" path="password" name="pass_"
class="round default-width-input" /></td>
<td><form:errors path="password" cssClass="errorbox" /></td>
</tr>
<tr>
<td id="idtab">Séléctionner un rôle :</td>
<td><form:select path="role">
<form:option value="" label="" />
<form:option value="ROLE_ADMIN">Administrateur</form:option>
<form:option value="ROLE_USER">Simple utilisateur</form:option>
</form:select></td>
<td><form:errors path="role" cssClass="errorbox" /></td>
</tr>
<tr>
<td id="idtab">Activé :</td>
<td><form:input type="checkbox" value="true" path="enable" />
Oui</td>
</tr>
<tr></tr>
<tr></tr>
<tr>
<td><input
class="button round blue image-right ic-right-arrow"
type="submit" value="Créer" /></td>
<td><input
class="button round blue image-right ic-right-arrow"
type="reset" value="Initialiser" /></td>
</tr>
</table>
</form:form>
Any Idea?

I'm afraid that a Validator will not be sufficient in this case. Although you could extend your AddUserValidator class to check whether the given user name is free, it will not
work in a situation in which two users simultaneously try to register using the same user name - the validation will pass, however one of the users will get an error from the database.
To protect yourself against such situations I would place the registration logic in a try catch block and in case of an error display a proper message to the user. This would be kind of an application-level validation.

Spring validator simply checks your object in accordance with the prescribed rules before you bring it into the database. It does not know anything about the database. To display the error that occurred while working with a database, you need to catch the exception manually.

In your Controller Just Check the duplication by querying from Model Repository.
#Model Entity
#Table(name = "people")
public class People {
#Column(name = "nic")
#NotEmpty(message = "*Please provide your nic")
private String nic;
#Repository
public interface PeopleRepository extends JpaRepository<People, Integer>{
People findByNic(String nic);
}
#Controller
#RequestMapping(value = "/welcome", method = RequestMethod.POST)
public ModelAndView createNewPeople(Model model,, BindingResult bindingResult) {
ModelAndView modelAndView = new ModelAndView();
People peopleExistsEmail = peopleService.findUserByNic(people.getNic());
if (peopleExistsEmail != null) {
bindingResult
.rejectValue("nic", "error.people",
"There is already a person registered with the nic provided");
}
if (bindingResult.hasErrors()) {
modelAndView.setViewName("welcome");
} else {
peopleService.savePeople(people);
modelAndView.addObject("successMessage", "People has been registered successfully");
modelAndView.addObject("people", new People());
} catch (Exception e) {
e.printStackTrace();
}
}
return modelAndView;
}

So this is the Right Answer :
The method in DAO class implementation is like that :
public boolean AddUser(User user) {
boolean t=true;
final String User_INSERT1 = "insert into utilisateurs (login, password, nom, prenom,enable) "
+ "values (?,?,?,?,?)";
final String User_INSERT2="insert into roles (login,role) values(?,?)";
/*
* On récupère et on utilisera directement le jdbcTemplate
*/
MessageDigestPasswordEncoder encoder = new MessageDigestPasswordEncoder("SHA");
String hash = encoder.encodePassword(user.getPassword(), "");
final String check ="select count(*) from utilisateurs where login = ?";
int result= getJdbcTemplate().queryForInt(check, new Object[]{String.valueOf(user.getLogin())});
if (result==0) {
getJdbcTemplate()
.update(User_INSERT1,
new Object[] {user.getLogin(),
hash, user.getNom(),
user.getPrenom(), user.getEnable(),
});
getJdbcTemplate().update(User_INSERT2, new Object[]{user.getLogin(),user.getRole()});
return t;
}
else { t = false ; return t;}
}
The controller :
#RequestMapping(value ="/ajouter_user", method = RequestMethod.POST)
public String add(#ModelAttribute User us,BindingResult result,ModelMap model) {
AddUserValidator uservalid=new AddUserValidator();
uservalid.validate(us, result);
if (result.hasErrors()) {
model.addAttribute("usersystem", userservice.getAllUsers());
return "gestionUser";
}else {
boolean e = userservice.AddUser(us);
if (e==false){
model.addAttribute("msg_failed","true");
}
else {
model.addAttribute("msg_success","true");}
model.addAttribute("usersystem", userservice.getAllUsers()); /*verifier*/
return "gestionUser";
}
}
And for showing the error in the jsp file :
<c:if test="${not empty msg_failed}">
<div class="errorblock">Il existe déjà un utilisateur avec cet login </div>
</c:if>

The method in DAO class implementation is like that :
public final long insert(final User user) throws MyException {
String sql = "INSERT INTO users ....";
String chkSql = "SELECT count(*) FROM users WHERE username=:username";
Map namedParams = new HashMap();
namedParams.put("username", user.getUsername());
long newId = namedTemplate.queryForInt(chkSql, namedParams);
if (newId > 0) {
try {
throw new MyException(-1);
} catch (MyException e) {
throw e;
}
}
newId = ...;// could be generated if not inc field or triggered...
namedParams.put("username", user.getUserName());
...
...
namedParams.put("id", newId);
namedTemplate.update(sql, namedParams);
return newId;
}
MyException like that:
public class MyException extends Exception{
private static final long serialVersionUID = 1L;
int a;
public MyException(int b) {
a=b;
}
}
Controller:
#RequestMapping(value = "/user", method = RequestMethod.POST)
public final ModelAndView actionUser(
final ModelMap model,
#ModelAttribute("myitemuser") #Valid final User user,
final BindingResult bindResult,
...);
...
try {
userService.addUser(user); // or dao... ;)
} catch (Exception e) {
UserValidator userValidator = new UserValidator();
userValidator.custError(bindResult);
}
UserValidator like that:
...
#Override
public final void validate(final Object object, final Errors errors) {
User user = (User) object;
...
if (user.getPassword().isEmpty()) {
errors.rejectValue("password", "error.users.emptypass");
}
}
public final void custError(final Errors errors){
errors.rejectValue("username"/* or login */, "error.users.uniqname");
}
...
Ну как то так))))

Related

Spring JPA - Dropdown list (Filled with data from another table)

I've a problem to insert data to table from my form.
So, I have a two table with relation ManyToOne.
TORDER and TSYSTEM.
I want to insert data to TORDER table via form in my .jsp page. Data for one field is from TSYSTEM table - System Name.
I was able to fill the dropdown list with data from the mentioned table but I have an error message when submitting the form and trying to insert data to TORDER Table.
Do you have any idea why could be wrong here?
My Order model class:
#Entity
#Table(name="TORDER")
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="ORDER_ID")
private int orderId;
#ManyToOne(cascade = CascadeType.ALL, targetEntity=System.class)
#JoinColumn(name = "SYSTEM_ID", referencedColumnName = "SYSTEM_ID")
private int sysId;
#ManyToOne(cascade = CascadeType.ALL, targetEntity=System.class)
#JoinColumn(name = "SYSTEM_NAME", referencedColumnName = "SYSTEM_NAME")
private String systemName;
#Column(name="ORDER_DATE")
private String orderDate;
#Column(name="STATUS")
private String status;
#Column(name="COMMENT")
private String comment;
#Column(name="APPROVED_BY_MANAGER")
private String managerApproval;
#Column(name="APPROVED_BY_ADMIN")
private String adminApproval;
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public int getSystemId() {
return sysId;
}
public void setSystemId(int sysId) {
this.sysId = sysId;
}
public String getSystemName() {
return systemName;
}
public void setSystemName(String systemName) {
this.systemName = systemName;
}
public String getOrderDate() {
return orderDate;
}
public void setOrderDate(String orderDate) {
this.orderDate = orderDate;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getManagerApproval() {
return managerApproval;
}
public void setManagerApproval(String managerApproval) {
this.managerApproval = managerApproval;
}
public String getAdminApproval() {
return adminApproval;
}
public void setAdminApproval(String adminApproval) {
this.adminApproval = adminApproval;
}
}
System model:
#Entity
#Table(name="TSYSTEM")
public class System implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="SYSTEM_ID")
private int sysId;
#Column(name="SYSTEM_NAME")
private String systemName;
#Column(name="DESCRIPTION")
private String description;
#Column(name="GROUP_NAME")
private String groupName;
public int getSysId() {
return sysId;
}
public void setSysId(int sysId) {
this.sysId = sysId;
}
public String getSystemName() {
return systemName;
}
public void setSystemName(String systemName) {
this.systemName = systemName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
}
Controller methods:
#RequestMapping(value="/addOrder", method=RequestMethod.GET)
public ModelAndView addOrder() {
ModelAndView model = new ModelAndView();
Order order = new Order();
model.addObject("orderForm", order);
List<System> systemList = systemService.getAllSystemsName();
model.addObject("systemList", systemList);
model.setViewName("order_form");
return model;
}
#RequestMapping(value="/saveOrder", method=RequestMethod.POST)
public ModelAndView save(#ModelAttribute("orderForm") Order order) {
orderService.saveOrUpdate(order);
return new ModelAndView("redirect:/employee/orderList");
}
Repository methods to get all system names from TSYSTEM Table:
public interface SystemRepository extends CrudRepository<System, Integer> {
#Query("select a.systemName from System a")
public List<System> getAllSystemsName();
}
and finally my .jsp form:
<form:form modelAttribute="orderForm" method="post" action="${saveURL }" cssClass="form" >
<form:hidden path="orderId"/>
<table>
<tr>
<td>System Name</td>
<td><form:select path="systemName">
<form:option value="NONE" label="--- Select ---" />
<form:options items="${systemList}" />
</form:select>
</td>
<td><form:errors path="systemName" cssClass="error" /></td>
</tr>
<tr>
<td><label>Komentarz</label></td>
<td><form:textarea path="comment" cssClass="form-control" id="comment"
title="Dodaj komentarz do zamówienia" /></td>
</tr>
<tr>
<td><label>Data zamówienia</label></td>
<td><form:input type="text" path="orderDate" cssClass="form-control"
id="orderDate" pattern="{2,}" title="Data zamówienia" required="required"/>
</td>
</tr>
<tr>
<td><button type="reset" class="btn btn-primary">Wyczyść dane</button>
</td>
<td><button type="submit" class="btn btn-primary">Zamów dostęp</button>
</td>
</tr>
</table>
</form:form>
and after form submit action i received and error:
2018-11-13 17:32:32.846 ERROR 7416 --- [nio-8090-exec-9] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: Error accessing field [private int com.project.model.System.sysId] by reflection for persistent property [com.project.model.System#sysId] : 0; nested exception is org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private int com.project.model.System.sysId] by reflection for persistent property [com.project.model.System#sysId] : 0] with root cause
java.lang.IllegalArgumentException: Can not set int field com.project.model.System.sysId to java.lang.Integer
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) ~[na:1.8.0_161]
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) ~[na:1.8.0_161]
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58) ~[na:1.8.0_161]
at sun.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56) ~[na:1.8.0_161]
at java.lang.reflect.Field.getInt(Field.java:574) ~[na:1.8.0_161]
at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:62) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
Please post SYSTEM model. I think you need change System model with field sysId to Integer type. Because you set repository with model sysId is Integer.

Spring + thymeleaf Validanting integer error Neither BindingResult nor plain target object for bean name available as request attribute

I'm in the process of learning spring and thymeleaf and working on a timekeeping project.
For this I need to validate the number of hours an employee clocks in one day.
I used the tutorial in the spring documentation for this however i keep getting the following error
Neither BindingResult nor plain target object for bean name 'timetable' available as request attribute
Any ideas what I might be doing wrong?
Controller class
#RequestMapping(value="Timetable/AddToTimetable", method = RequestMethod.GET)
public String newUser(Model md) {
md.addAttribute("assignments", serv.findAll());
return "AddToTimetable";
}
#RequestMapping(value = "/createEntry", method = RequestMethod.POST)
public String create(#RequestParam("assignmentId") int assignmentId,
#RequestParam("date") #DateTimeFormat(pattern = "yyyy-MM-dd") Date date,
#RequestParam("hoursWorked") int hoursWorked,
#Valid Timetable timetable, BindingResult bindingResult,
Model md) {
timetable = new Timetable();
timetable.setAssignmentId(assignmentId);
timetable.setDate(date);
timetable.setHoursWorked(hoursWorked);
md.addAttribute("timetables", service.timetableAdd(timetable));
if (bindingResult.hasErrors()) {
return "AddToTimetable";
}
return "redirect:/Timetable";
}
Service class
public BigInteger timetableAdd(Timetable timetable){
KeyHolder keyHolder = new GeneratedKeyHolder();
String sql = "INSERT INTO timetables ( assignmentId, date, hoursWorked) VALUES ( ?, ?, ?)";
template.update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement pst = con.prepareStatement(sql, new String[] {"id"});
pst.setInt(1, timetable.getAssignmentId());
pst.setDate(2, new java.sql.Date(timetable.getDate().getTime()));
pst.setInt(3, timetable.getHoursWorked());
return pst;
}
}, keyHolder);
return (BigInteger) keyHolder.getKey();
}
}
Model class
package ro.database.jdbcPontaj.model;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;
public class Timetable {
private int timetableId;
private int assignmentId;
private Date date;
private String project;
#NotNull
#Min(0)
#Max(12)
private int hoursWorked;
public int getTimetableId() {
return timetableId;
}
public void setTimetableId(int timetableId) {
this.timetableId = timetableId;
}
public int getAssignmentId() {
return assignmentId;
}
public void setAssignmentId(int assignmentId) {
this.assignmentId = assignmentId;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getHoursWorked() {
return hoursWorked;
}
public void setHoursWorked(int hoursWorked) {
this.hoursWorked = hoursWorked;
}
public String getProject() {
return project;
}
public void setProject(String project) {
this.project = project;
}
public Timetable() {
}
public Timetable(int timetableId, String project, Date date, int hoursWorked) {
this.timetableId = timetableId;
this.project=project;
this.date = date;
this.hoursWorked = hoursWorked;
}
public Timetable(int timetableId, int assignmentId, Date date, int hoursWorked) {
this.timetableId = timetableId;
this.assignmentId = assignmentId;
this.date = date;
this.hoursWorked = hoursWorked;
}
}
Html
<form method="post" name="comment_form" id="comment_form" th:action="#{/createEntry}" th:object="${timetable}" role="form">
<p> Project</p><br>
<select name="assignmentId">
<option value="" th:each="assignment: ${assignments}" th:value="${assignment.assignmentId}" th:text="${assignment.assignmentId}"></option>
</select>
<p>Date</p> <br>
<input class="datepicker" type="text" name="date"><br>
<p>Number of hours</p>
<input type="text" name="hoursWorked" th:field="*{hoursWorked}"><br>
<p th:if="${#fields.hasErrors('hoursWorked')}" th:errors="*{hoursWorked}">Age Error</p>
<button type="submit" id="submit" class="btn btn-primary">Submit</button>
</form>
UPDATE:
Timetable (skipping bootstrap divs)
<div class="row">
<div class="col-md-10 title">
<h2>Timetable</h2>
</div>
<div class="col-md-2">
</div>
<div class="col-md-12">
<table class="table table-bordered">
<thead>
<tr>
<th>id</th>
<th>assignment</th>
<th>date</th>
<th>number of hours</th>
</tr>
</thead>
<tbody>
<tr th:each = "timetable: ${timetables}">
<td th:text="${timetable.timetableId}">45</td>
<td th:text="${timetable.project}">vasi</td>
<td th:text="${timetable.date}">1 ian</td>
<td th:text="${timetable.hoursWorked}">3000</td>
</tr>
</tbody>
</table>
Service method for Timetable
#Autowired
JdbcTemplate template;
public List<Timetable> findAll(String loginname) {
String sql = " SELECT timetables.timetableId, timetables.assignmentId, timetables.date, " +
"timetables.hoursWorked, users.username, projects.projectName AS project " +
"FROM timetables INNER join assignments on timetables.assignmentId = assignments.assignmentId " +
"INNER JOIN projects on assignments.projectId = projects.projectId " +
"INNER JOIN users on users.userId = assignments.userId where username= ?";
RowMapper<Timetable> rm = new RowMapper<Timetable>() {
#Override
public Timetable mapRow(ResultSet resultSet, int i) throws SQLException {
Timetable timetable = new Timetable(resultSet.getInt("timetableId"),
resultSet.getString("project"),
resultSet.getDate("date"),
resultSet.getInt("hoursWorked"));
return timetable;
}
};
return template.query(sql, rm, loginname);
}
The controller method for Timetable
#RequestMapping(value = {"/Timetable"}, method = RequestMethod.GET)
public String index(Model md){
org.springframework.security.core.Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String loginname = auth.getName();
md.addAttribute("timetables", service.findAll(loginname));
return "Timetable";
}
If I understand correctly you have two html pages one that shows all the assignments and one that you enter the new entry.I think that get the error when there is a validation error in the new entry page.
Substitute these lines
if (bindingResult.hasErrors()) {
return "AddToTimetable";
}
with these ones
if (bindingResult.hasErrors()) {
return "newEntry";//replace the newentry with the html page that you enter the new entry
}
When there is an error, you should go to the page that you tried to enter the new entry and not in the page that has all the assignments.

How to avoid special characters in Spring MVC

Hi am doing sever side validation for form fields see am getting all the error messages properly but How to avoid special characters like % # $ ^ & * for each input fields and how to make input box border gets red when i get error messages
To avoid special characters i have to use ESAPI.validator().getValidInput
How to use below try catch code In validator class to avoid special characters
try
{
ESAPI.validator().getValidInput("Validationofmobilenumber", mobilenumber, "Onlynumber", 200, false);
ESAPI.validator().getValidInput("Validationofinput", Studentname, "Onlycharacters", 200, false);
}
catch (ValidationException e) {
ESAPI.log().error(Logger.EVENT_FAILURE, e.getMessage());
System.out.println("in validation");
addActionError("Do not enter special character like % # $ ^ & *...... ");
} catch (IntrusionException ie) {
ESAPI.log().error(Logger.EVENT_FAILURE, ie.getMessage());
addActionError("Do not enter special character like % # $ ^ & *...... ");
} catch (Exception e) {
System.out.println(e);
}
Controller
#Controller
public class RegistrationController {
#Autowired
CustomerValidator customerValidator;
#RequestMapping(value = "/register", method = RequestMethod.GET)
public String viewRegistrationPage(Model model) {
Customer customer = new Customer();
model.addAttribute("customer", customer);
return "register";
}
#RequestMapping(value = "/doRegister", method = RequestMethod.POST)
public String doLogin(#Valid Customer customer, BindingResult result,Model model) {
model.addAttribute("customer",customer);
customerValidator.validate(customer, result);
if(result.hasErrors()){
return "register";
}
return "home";
}
public CustomerValidator getCustomerValidator() {
return customerValidator;
}
public void setCustomerValidator(CustomerValidator customerValidator) {
this.customerValidator = customerValidator;
}
}
Model
public class Customer {
#NotEmpty
#Email
private String emailId;
#Size(min=8,max=15)
private String password;
#Size(min=8,max=15)
private String confPassword;
private int age;
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getConfPassword() {
return confPassword;
}
public void setConfPassword(String confPassword) {
this.confPassword = confPassword;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Validator
#Component
public class CustomerValidator implements Validator {
public boolean supports(Class<?> clazz) {
return Customer.class.isAssignableFrom(clazz);
}
public void validate(Object target, Errors errors) {
Customer customer = (Customer)target;
int age = customer.getAge();
String password = customer.getPassword();
String confPassword = customer.getConfPassword();
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "age", "customer.age.empty");
//Business validation
if(!password.equals(confPassword)){
errors.rejectValue("password","customer.password.missMatch");
}
if(age < 18 || age > 60){
errors.rejectValue("age", "customer.age.range.invalid");
}
}
}
Jsp
<tr>
<td>Enter your E-mail:</td>
<td><form:input path="emailId" /></td>
<td><form:errors path="emailId" cssStyle="color: #ff0000;" /></td>
</tr>
<tr>
<td>Enter your Age:</td>
<td><form:input path="age"/></td>
<td><form:errors path="age" cssStyle="color: #ff0000;"/></td>
</tr>
<tr>
<td>Enter your password:</td>
<td><form:password path="password" showPassword="true"/></td>
<td><form:errors path="password" cssStyle="color: #ff0000;"/></td>
</tr>
<tr>
<td>Confirm your password:</td>
<td><form:password path="confPassword" showPassword="true"/></td>
<td><form:errors path="confPassword" cssStyle="color: #ff0000;"/></td>
</tr>
<tr>
<td><input type="submit" name="submit" value="Click here to Register"></td>
</tr>
</table>
</form:form>
Properties
NotEmpty.customer.emailId=Email Id is required.
Email.customer.emailId=valid email id is required.
Size.customer.password=Password should be minimum of 8 and maximum of 15 characters.
Size.customer.confPassword=Password should be minimum of 8 and maximum of 15 characters.
customer.age.empty = Age is required
customer.age.range.invalid = Age should be between 18 to 60
customer.password.missMatch = password and confirm password do not match
For validation use #Pattern annotation like this:
#Pattern(regexp = "^[a-zA-Z0-9.\\-\\/+=#_ ]*$")
#NotEmpty
#Email
private String emailId;
And for error field red border, add a css class for errors and put css style for that class and put that in head block of jsp or in the css file that you have.
<tr>
<td>Enter your E-mail:</td>
<td><form:input path="emailId" /></td>
<td><form:errors path="emailId" cssClass="error" /></td>
</tr>
<style>
.error {
color: red;
border: 1px solid red;
}
</style>
If you want to use ESAPI validator, add this rule in your ESAPI.properties
Validator.ValidInput=^[a-zA-Z0-9.\\-\\/+=#_ ]*$
And then add following for each of your input in Validator class, i'm giving only one for example.
try {
if (!ESAPI.validator().isValidInput("ValidationOfPassword", password, "ValidInput", 200, false)) {
errors.rejectValue("password","customer.password.missMatch");//replace your msg property in second param
}
} catch (Exception e) {
//something gone wrong
e.printStackTrace();
errors.rejectValue("password","customer.password.missMatch");//replace your msg property in second param
}
On your field, you can use javax.validation.constraints.Pattern annotation and then use something like "[\w]*" that means only alphanumeric characters.

Error with NullPointerExcetion Native Method Accessor, Can give me a solution

i browse "http://localhost:8080/subject/form" for fill information in Subjectform.jsp, after will direct "http://localhost:8080/subject/add" for insert subject object in table subject. But it not insert subject object and encouter following error:
null<br/>
edu.java.spring.controller.SubjectController.addSubject(SubjectController.java:5
0)<br/>
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<br/>
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)<br
/>
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav
a:43)<br/>
java.lang.reflect.Method.invoke(Method.java:497)<br/>
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHa
ndlerMethod.java:215)<br/>
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(I
nvocableHandlerMethod.java:132)<br/>
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMet
hod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)<br/>
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapt
er.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)<br/>
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapt
er.handleInternal(RequestMappingHandlerAdapter.java:689)<br/>
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(A
bstractHandlerMethodAdapter.java:83)<br/>
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.j
ava:938)<br/>
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.ja
va:870)<br/>
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet
.java:961)<br/>
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:86
3)<br/>
javax.servlet.http.HttpServlet.service(HttpServlet.java:707)<br/>
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:8
37)<br/>
javax.servlet.http.HttpServlet.service(HttpServlet.java:790)<br/>
org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:801)<br/>
org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:587)<br/>
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)<br
/>
org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)<br/>
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223
)<br/>
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:112
6)<br/>
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)<br/>
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
<br/>
org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1060
)<br/>
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)<br
/>
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerC
ollection.java:215)<br/>
org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java
:110)<br/>
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:113)<
br/>
org.eclipse.jetty.server.Server.handle(Server.java:509)<br/>
org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:288)<br/>
org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:240)<br/>
org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:539)<br/>
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:620)
<br/>
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:540)<
br/>
java.lang.Thread.run(Thread.java:745)<br/>
Here file SubjectController.class
#Controller
public class SubjectController {
#Autowired
public StudentDAO studentDao;
public SubjectDao subjectDao;
#RequestMapping(value = "subject/form",method = RequestMethod.GET)
public ModelAndView subjectForm (){
ModelAndView model = new ModelAndView("SubjectForm", "subject", new Subject());
List<Student> students = studentDao.listStudents();
Map<Integer,String> map = new HashMap<Integer,String>();
for(int i=0;i<students.size();i++){
map.put(students.get(i).getId(), students.get(i).getName());
}
model.getModelMap().put("studentList",map);
return model;
}
#RequestMapping(value="subject/add",method = RequestMethod.POST)
public void addSubject(#Valid #ModelAttribute("subject")Subject subject){
// ModelAndView model = new ModelAndView("redirect:/subject/list");
subjectDao.insert(subject);
// return model;
}
Here file SubjectHibernateDaoImpl.class
public class SubjectHibernateDaoImpl implements SubjectDao {
#Autowired
public LocalSessionFactoryBean sessionFactory;
#Override
public void insert(Subject subject){
Session session = sessionFactory.getObject().openSession();
try {
session.save(subject);
session.flush();
} finally {
// TODO: handle finally clause
session.close();
}
}
public List<Subject> listSubject() {
// TODO Auto-generated method stub
Session session = sessionFactory.getObject().openSession();
Query query = session.createQuery("from Subject");
try {
return query.list();
} finally {
// TODO: handle finally clause
session.close();
}
}
Here file Subject.class
#Entity
#Table(name = "subject",uniqueConstraints={#UniqueConstraint(columnNames="id")})
public class Subject {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column(name = "title", nullable = false, length = 200)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Column(name = "student", nullable = false)
public int getStudent() {
return student;
}
public void setStudent(int student) {
this.student = student;
}
#Column(name = "score", nullable = false)
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int id;
public String title;
public int student;
public int score;
}
Here file Subject.jsp
<html>
<head>
<title>Add New Subject Information</title>
</head>
<body>
<h2>Please Input Subject Information</h2>
<form:form method="POST" modelAttribute="subject" action="add">
<table>
<tr>
<td><form:label path="student">Student</form:label></td>
<td><form:input path="student" type = "number"/></td>
</tr>
<tr>
<td><form:label path="title">Title</form:label></td>
<td><form:input path="title"/></td>
</tr>
<tr>
<td><form:label path="score">Score</form:label></td>
<td><form:input path="score" type = "number"/></td>
</tr>
<tr>
<td colspan="3"><input type="submit" value="Submit"/></td>
</table>
</form:form>
</body>
</html>
Looks like you forgot to add the #Autowired annotation. It's present for the studentDao but not for the subjectDao, resulting in that object not being initialized.

Spring and Hibernate form binding

Ok I am having an issue and have been stuck for a few hours. I am running the current version of spring with Hibernate and need to take data from a form and save it do the database, that's all but it is giving me tons of trouble and have no idea how to go about it. Below is the controller, JSP, Model, and Dao.
Controller
private final String addNewView = "addAward";
#RequestMapping(value = "/addAwardType", method = RequestMethod.GET)
public String addAwardType() {
LOG.debug("Display form to add a new contact.");
return addNewView;
}
#RequestMapping(value = "/addAwardType", method = RequestMethod.POST)
public ModelAndView addAwardType(
#ModelAttribute("AwardTypeModel") AwardType awardType,
BindingResult result) {
return new ModelAndView(addNewView, "AwardType", new AwardTypeModel(awardType));
}
}
JSP
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h2>Add AwardType</h2>
<form:form method="POST" commandName="addAwardType">
<table>
<tr>
<td><form:label path="AwardType.name">Award Name</form:label></td>
<td><form:input path="AwardType.name" /></td>
</tr>
<tr>
<td><form:label path="AwardType.description">Last Name</form:label></td>
<td><form:input path="AwardType.description" /></td>
</tr>
<tr>
<td> <form:checkbox path="AwardType.isActive" value="Active"/></td>
</tr>
<tr>
<td><form:label path="AwardType.created"></form:label></td>
<td><form:input path="AwardType.created" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Add Award"/>
</td>
</tr>
</table>
</form:form>
</body>
</html>
Model
public class AwardTypeModel extends BaseModel {
private int id;
private String name;
private String description;
private boolean active;
private Date created;
private Date modified;
/**
* Construct from persistence object
* A similar constructor will be needed in each model
* #param dbo - the Persistence Object (data base object)
*/
public AwardTypeModel(AwardType dbo){
this.id = dbo.getAwardTypeId();
this.name = dbo.getAwardName();
this.description = dbo.getDescription();
this.active = dbo.isActive();
this.created = dbo.getCreated();
this.modified = dbo.getModified();
}
/* (non-Javadoc)
* #see com.eaglecrk.recognition.model.BaseModel#convertToDb()
*/
#Override
public BasePersistence convertToDb() {
AwardType dbo = new AwardType();
dbo.setAwardTypeId(this.id);
dbo.setAwardName(this.name);
dbo.setDescription(this.description);
dbo.setActive(this.active);
dbo.setCreated(this.created);
dbo.setModified(this.modified);
return dbo;
}
public int getId() {
return id;
}
public void setId(int 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 boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getModified() {
return modified;
}
public void setModified(Date modified) {
this.modified = modified;
}
}

Resources