Can not get the error message in the spring form - spring

I am woring on an Spring Web application with the CURD operation for the Entity Department, this is the handler for processing the submit of a new Department:
#RequestMapping(value = "/", method = RequestMethod.POST)
public String addSubmit(#Valid Department department, BindingResult result,SessionStatus status) {
if (result.hasErrors()) {
return "department/add";
} else {
departmentService.save(department);
status.setComplete();
return "redirect:/departments/" + department.getId();
}
}
Model:
#Entity
public class Department extends BaseNamedEntity {
#NotNull
#NotEmpty
private String description;
...
}
And the form:
<form:form method="post" action="${fmURL}" class="form-horizontal" commandName="department">
<form:hidden path="id"/>
<spring:bind path="name">
<div class="control-group ${status.error ? 'error' : ''}">
<label class="control-label">Name</label>
<div class="controls">
<form:input path="name"/>
<span class="help-inline">${status.errorMessage}</span>
</div>
</div>
</spring:bind>
<form:form>
However, once I submit the form with empty field, normally, the errorMessage should be displayed and the related div should be add a class with error, however I can not found the error message.
What's going on?
BTW, the example is derive from Spring-petclinic project.

Related

Show Springboot validation results in Thymeleaf template

I am getting started with Springboot and am unable to propagate validation results (errors) back to the thyme template. I have a typical setup: #Entity object, #Service, and #Repository. Here are the sections of my Controller and index template (and its form). UserVital, UserBlood, etc. are the data objects mapped to the DB tables using hibernate. Hope this information is enough for the members to point me in the right direction.
Data Object
#Entity
#Table(name = ".....")
public class UserVital {
#NotNull(message = "Height (Feet) cannot be null")
#Range(min = 0, max = 15, message = "Height (Feet) must be greater than 0")
#Column(name = "feet", nullable = false)
private int heightInFeet;
.............
}
Controller
#GetMapping("/")
public String getUsers(Model model) {
UserVital vital = new UserVital();
UserGrithMeasurements grith = new UserGrithMeasurements();
UserBloodChemistry blood = new UserBloodChemistry();
List<Category> categories = categoryService.getAllCategories();
model.addAttribute("categories", categories.get(0));
model.addAttribute("vital", vital);
model.addAttribute("grith", grith);
model.addAttribute("blood", blood);
return "index";
}
#PostMapping("/add")
public String addData(#Valid UserVital vital, BindingResult vitalValidationResult,
#Valid UserGrithMeasurements grith, BindingResult grithValidationResult, #Valid UserBloodChemistry blood,
BindingResult bloodValidationResult, Model model) {
if (vitalValidationResult.hasErrors() || grithValidationResult.hasErrors()
|| bloodValidationResult.hasErrors()) {
return "index";
} else {
model.addAttribute("successMsg", "Details saved successfully!!");
return "index";
}
}
Thyme Form
<form class="tab-content" method="POST" th:action="#{/add}">
<div class="form-group row">
<label for="height" class="col-sm-2 control-label" th:text="#{height}"></label>
<div class="col-sm-2">
<input type="number" class="form-control" id="feet" th:attr="placeholder=#{feet}"
th:field="${vital.heightInFeet}">
</div>
<div class="form-group col-sm-12">
<label for="neck" class="col-sm-2 control-label" th:text="#{neck}"></label>
<div class="col-sm-2">
<input type="number" class="form-control" id="systolic" th:attr="placeholder=#{inches}"
th:field="${grith.neck}">
<div class="col-sm-2">
<input type="number" class="form-control" id="ldl" th:field="${blood.ldl}">
.....
</form>
Question: As you can see I have multiple BindingResult objects. Each BindingResult object holding the validation results of the respective data object (vitalValidationResult holds validation result of UserVital object vital, etc.). Now, how do I write "th:if" statements in the template that will allow me to check if there are any errors in the fields.
Thanks.
I have solved the problem by encapsulating the required form fields in a div and then placing "th:object=${objectName}" in the div.
<form >
<div class="tab-pane active text-center" id="tab_1_1" th:object=${vital}>
<div class="tab-pane active text-center" id="tab_1_2" th:object=${grith}>
</form>

Insert jsp form to database using spring boot

I'm a beginner in spring boot I start with creating a contact form that send data to data base. this is the form:
<form:form method="POST" id="contactform" modelAttribute="message">
<div class="form">
<div class="six columns noleftmargin">
<label name="name">Name</label>
<form:input path="name" type="text" class="smoothborder" placeholder="Your name *"/>
</div>
<div class="six columns">
<label name="email">E-mail address</label>
<form:input path="email" type="text" class="smoothborder" placeholder="Your e-mail address *"/>
</div>
<label name="comment">Message</label>
<form:textarea path="comment" class="smoothborder ctextarea" rows="14" placeholder="Message, feedback, comments *"></form:textarea>
<input type="submit" id="submit" class="readmore" value="Submit"/>
</div>
</form:form>
And this is my conact controller:
#Autowired
private MessageRepository messageRepository ;
#RequestMapping(value= "/newmessage", method = RequestMethod.GET)
public String newMessage(ModelMap model) {
Message message = new Message();
model.addAttribute("message", message);
return ("/contact");
}
#RequestMapping(value="/newmessage",method=RequestMethod.POST)
public String saveMessage( Message message, BindingResult result, ModelMap model)
{
if (result.hasErrors()) {
return "/contact";
}
messageRepository.save(message);
model.addAttribute("success", "Message " + message.getName() + " "+ message.getEmail() + " "+ message.getComment()+ " registered successfully");
//return "success";
return "/homepage";
Folder Structure
You need to set the action of the form. If you want to hit /newmessage while submitting form, then you need to change as following :
<form:form method="POST" id="contactform" action="/newmessage" modelAttribute="message">
<!-- The elements of the form -->
</form:form>
Also, you need to add the modelAttribute to your controller method. And you should return only the name of the jsp page. If your page name is homepage.jsp then you should only return homepage from your controller method. Of course, homepage.jsp file needs to be in WEB-INF folder.
#RequestMapping(value="/newmessage",method=RequestMethod.POST)
public String saveMessage(#ModelAttribute("message") Message message, BindingResult result, ModelMap model) {
// Rest of the code
return "homepage";
}

Spring Boot ModelAndView - cannot update value to Model

I am trying to create a form with 3 fields within the class LoginForm: usuario, senha, msgLogin.
I receive the fields usuário and senha from the input boxes and then I try to redirect to the same page with the same fields plus the field MsgLogin. But I've not been able to update the msgLogin field and I don't understand why.
These are the code:
HTML:
<form id="frmLogin" class="form col-md-12" action="#" th:action="#{/login}" th:object="${loginForm}" method="post">
<div class="form-group">
<label for="usuario" class="col-md-1">Usuário: </label>
<input type="text" id="usuario" placeholder="Email" th:field="*{usuario}"/>
</div>
<div class="form-group">
<label for="senha" class="col-md-1">Senha: </label>
<input type="password" id="senha" placeholder="senha" th:field="*{senha}"/>
</div>
<div class="row">
<button id="entrar">Entrar</button>
</div>
<div class="row">
<div id="msgLogin"></div>
<p th:text="${loginForm.msgLogin}" />
</div>
</form>
The Controller:
#RequestMapping("/")
public String init(#ModelAttribute LoginForm loginForm) {
Logger.getAnonymousLogger().info("Tela Inicial.");
return "home";
}
#PostMapping("/login")
public ModelAndView entrar(LoginForm loginForm) throws IOException {
Logger.getAnonymousLogger().info("Entrando no Internet Banking.");
service.login(usuario, senha);
ModelMap model = new ModelMap();
loginForm.setMsgLogin("I want to update that value!");
model.addAttribute("loginForm", loginForm);
return new ModelAndView("redirect:/", model);
}
Class using Lombok:
#Getter
#Setter
public class LoginForm {
private String usuario;
private String senha;
private String msgLogin;
}
A redirect send a 302 HTTP status back to the browser to resubmit using a new url, so it resubmits the same two fields to the new url. There's no expectation of payload data in the 302 response.
In your Controller, change the last line in your entrar method to: return new ModelAndView("/login", model);

Spring/Hibernate not persisting all data submited from HTML Form

In my current spring pŕoject, I have a form like that:
<form role="form" class="form" id="form" method="post" action="/loja/pagina/insert" enctype="multipart/form-data">
<input class="form-control" type="hidden" name="id" />
<label>Title</label>
<input class="form-control" type="text" name="titulo" />
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">
pt-BR
</li>
<li role="presentation">
es-ES</li>
<li role="presentation">en-US</li>
</ul>
<div class="tab-content">
<div role="tabpane1" class="tab-pane active" id="pt-BR">
<input type="hidden" name="textos.idioma" value="pt-BR" />
<textarea class="summernote" name="textos.conteudo"></textarea>
</div>
<div role="tabpane1" class="tab-pane" id="es-ES">
<input type="hidden" name="textos.idioma" value="es-ES" />
<textarea class="summernote" name="textos.conteudo"></textarea>
</div>
<div role="tabpane1" class="tab-pane" id="en-US">
<input type="hidden" name="textos.idioma" value="en-US" />
<textarea class="summernote" name="textos.conteudo"></textarea>
</div>
</div>
</form>
When I submit this form to this methods:
controller
#RequestMapping(value = "/insert", method=RequestMethod.POST)
#ResponseBody
#PreAuthorize("hasPermission(#user, 'insert_'+#this.this.name)")
public void insert(#Valid E object, BindingResult result) {
serv.insert(object);
}
service
#Transactional
public void insert(E object) {
dao.insert(object);
}
dao
#Transactional
public void insert(E object) {
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.persist(object);
tx.commit();
} catch (Exception e) {
if(tx != null)
tx.rollback();
} finally {
session.close();
}
}
Only the field titulo is persisted. the field textos , which is represented by this entity class (getters and setter omitted):
#Entity
public class Texto extends Model {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column
private String idioma;
#Column
private String conteudo;
}
is not saved on the database. Anyone can tell what's the right way to implement the form to properly store this data? I check the browser's developer tools, and the data is being submitted, it's only not being persisted in the database.
I assume, that your model class Texto has a #OneToMany relation to class E, so that one E references multiple instances of Texto. If this is what your model expresses, you have to use a different syntax for your textarea names to Spring being able to parse your request payload.
In your case Spring would search for a property textos.conteudo on your class E. As I assume, that textos will be a collection, Spring will ignore this.
Assuming, that textos will be modeled as an indexed based collection like List, try to rename your textareas names to name="textos[0].conteudo" and so on to tell Spring that textos is a List and Spring will be able to parse the POST payload.
With the hint given to me by the user #AnsgarSchulte in this question, I change the html code in the form for name="textos[0] and change my PropertyEditorSupport class to handle this array and return a Texto object with the property idioma being the first element of the vector and the property conteudo being all the elements left (concatenating all of them in one string).

Spring MVC: #RequestParam validation

In my register form i'm using Bean Validator (JSR-303) for validate User object, and need to validate separately password confirmation, because it is not a member of User. I have a problem to assign error message for confirm field. How to do that ?
View:
<form:form modelAttribute="user" method="post" action="register.html">
<div class="fcell">
<div class="clabel"><spring:message code="label.password"/></div>
<div class="cdata"><form:password path="password"/></div>
<div class="cmsgs"><form:errors path="password" /></div>
</div>
<div class="fcell">
<div class="clabel"><spring:message code="label.confirm"/></div>
<div class="cdata"><input type="password" name="confirm"/></div>
<div class="cmsgs"></div>
</div>
</form:form>
Controller:
#RequestMapping("/register.html")
public String register(#RequestParam("confirm") String confirm, #ModelAttribute("user") #Valid User user, BindingResult result) {
if(!DigestUtils.sha256Hex(confirm).equals(user.getPassword())) {
/* Invalid property 'confirm' ... */
result.rejectValue("confirm", "text.passwords_not_equal");
}
return "register";
}
In this case confirmation can be considered a part of model object, like this:
public class RegistrationForm {
#Valid
private User user;
private String confirm;
...
}
...
public String register(#ModelAttribute("user") #Valid RegistrationForm user,
BindingResult result) { ... }
...
<div class="cdata">
<form:password path="confirm"/></div>
<div class="cmsgs"><form:errors path="confirm" />
</div>
...

Resources