<form:checkbox> hidden value messing my form? - spring

i have a field in a form and its bound to an user class, in the form its this field
<tr>
<td>AcceptTerms:</td>
<td><form:checkbox path="acceptTerms"/><td>
</tr>
but at the moment of submitting the form an error arises
The request sent by the client was syntactically incorrect.
i inspected it with firebug and got this
Parameters application/x-www-form-urlencoded
_acceptTerms on
email ZX
password ZXZX
rol 2
username ZxZ
Fuente
username=ZxZ&password=ZXZX&email=ZX&rol=2&_acceptTerms=on
the _acceptTerms its a hidden value for the checkbox that as i assume it a default of spring tag <form:checkbox>.
this arises 3 questions for me:
does this field (_acceptTerms) mess with my form submit?
why is _acceptTerms always set to on?
if this field does indeed mess up my form how can i get rid of it or how should i process it? add to the user model?
thanks in advance
Edit
package com.carloscortina.paidosSimple.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.carloscortina.paidosSimple.model.Categoria;
import com.carloscortina.paidosSimple.model.Personal;
import com.carloscortina.paidosSimple.model.Usuario;
import com.carloscortina.paidosSimple.service.CategoriaService;
import com.carloscortina.paidosSimple.service.PersonalService;
import com.carloscortina.paidosSimple.service.UsuarioService;
#Controller
public class PersonalController {
private static final Logger logger = LoggerFactory.getLogger(PersonalController.class);
#Autowired
private PersonalService personalService;
#Autowired
private UsuarioService usuarioService;
#Autowired
private CategoriaService categoriaService;
#RequestMapping(value="/usuario/add")
public ModelAndView addUsuarioPage(){
ModelAndView modelAndView = new ModelAndView("add-usuario-form");
modelAndView.addObject("categorias",categorias());
modelAndView.addObject("user", new Usuario());
return modelAndView;
}
#RequestMapping(value="/usuario/add/process",method=RequestMethod.POST)
public ModelAndView addingUsuario(#ModelAttribute Usuario user){
ModelAndView modelAndView = new ModelAndView("add-personal-form");
usuarioService.addUsuario(user);
logger.info(modelAndView.toString());
String message= "Usuario Agregado Correctamente.";
modelAndView.addObject("message",message);
modelAndView.addObject("staff",new Personal());
return modelAndView;
}
#RequestMapping(value="/personal/list")
public ModelAndView listOfPersonal(){
ModelAndView modelAndView = new ModelAndView("list-of-personal");
List<Personal> staffMembers = personalService.getAllPersonal();
logger.info(staffMembers.get(0).getpNombre());
modelAndView.addObject("staffMembers",staffMembers);
return modelAndView;
}
#RequestMapping(value="/personal/edit/{id}",method=RequestMethod.GET)
public ModelAndView editPersonalPage(#PathVariable int id){
ModelAndView modelAndView = new ModelAndView("edit-personal-form");
Personal staff = personalService.getPersonal(id);
logger.info(staff.getpNombre());
modelAndView.addObject("staff",staff);
return modelAndView;
}
#RequestMapping(value="/personal/edit/{id}", method=RequestMethod.POST)
public ModelAndView edditingPersonal(#ModelAttribute Personal staff, #PathVariable int id) {
ModelAndView modelAndView = new ModelAndView("home");
personalService.updatePersonal(staff);
String message = "Personal was successfully edited.";
modelAndView.addObject("message", message);
return modelAndView;
}
#RequestMapping(value="/personal/delete/{id}", method=RequestMethod.GET)
public ModelAndView deletePersonal(#PathVariable int id) {
ModelAndView modelAndView = new ModelAndView("home");
personalService.deletePersonal(id);
String message = "Personal was successfully deleted.";
modelAndView.addObject("message", message);
return modelAndView;
}
private Map<String,String> categorias(){
List<Categoria> lista = categoriaService.getCategorias();
Map<String,String> categorias = new HashMap<String, String>();
for (Categoria categoria : lista) {
categorias.put(Integer.toString(categoria.getId()), categoria.getCategoria());
}
return categorias;
}
Form.jsp
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<head>
<title>Add personal page</title>
</head>
<body>
<p>${message}<br>
<h1>Add User Page</h1>
<p>Here you can add a new staff member.</p>
<form:form method="POST" commandName="user" action="${pageContext.request.contextPath}/usuario/add/process" >
<table>
<tbody>
<tr>
<td>Nombre de Usuario:</td>
<td><form:input path="username"/><td>
</tr>
<tr>
<td>Contraseña:</td>
<td><form:password path="password"/><td>
</tr>
<tr>
<td>Email:</td>
<td><form:input path="email"/><td>
</tr>
<tr>
<td>Categoria:</td>
<td><form:select path="rol">
<form:options items="${categorias}" />
</form:select><td>
</tr>
<tr>
<td>AcceptTerms:</td>
<td><form:checkbox path="acceptTerms"/><td>
</tr>
<tr>
<td><input type="submit" value="Registrar"><td>
</tr>
</tbody>
</table>
</form:form>
<p>Home Page</p>
</body>
Log
DEBUG: org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'appServlet' processing POST request for [/paidosSimple/usuario/add/process]
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /usuario/add/process
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Returning handler method [public org.springframework.web.servlet.ModelAndView com.carloscortina.paidosSimple.controller.PersonalController.addingUsuario(com.carloscortina.paidosSimple.model.Usuario)]
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'personalController'
DEBUG: org.springframework.beans.BeanUtils - No property editor [com.carloscortina.paidosSimple.model.CategoriaEditor] found for type com.carloscortina.paidosSimple.model.Categoria according to 'Editor' suffix convention
DEBUG: org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Resolving exception from handler [public org.springframework.web.servlet.ModelAndView com.carloscortina.paidosSimple.controller.PersonalController.addingUsuario(com.carloscortina.paidosSimple.model.Usuario)]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'usuario' on field 'rol': rejected value [2]; codes [typeMismatch.usuario.rol,typeMismatch.rol,typeMismatch.com.carloscortina.paidosSimple.model.Categoria,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [usuario.rol,rol]; arguments []; default message [rol]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.carloscortina.paidosSimple.model.Categoria' for property 'rol'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.carloscortina.paidosSimple.model.Categoria] for property 'rol': no matching editors or conversion strategy found]
DEBUG: org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver - Resolving exception from handler [public org.springframework.web.servlet.ModelAndView com.carloscortina.paidosSimple.controller.PersonalController.addingUsuario(com.carloscortina.paidosSimple.model.Usuario)]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'usuario' on field 'rol': rejected value [2]; codes [typeMismatch.usuario.rol,typeMismatch.rol,typeMismatch.com.carloscortina.paidosSimple.model.Categoria,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [usuario.rol,rol]; arguments []; default message [rol]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.carloscortina.paidosSimple.model.Categoria' for property 'rol'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.carloscortina.paidosSimple.model.Categoria] for property 'rol': no matching editors or conversion strategy found]
DEBUG: org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Resolving exception from handler [public org.springframework.web.servlet.ModelAndView com.carloscortina.paidosSimple.controller.PersonalController.addingUsuario(com.carloscortina.paidosSimple.model.Usuario)]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'usuario' on field 'rol': rejected value [2]; codes [typeMismatch.usuario.rol,typeMismatch.rol,typeMismatch.com.carloscortina.paidosSimple.model.Categoria,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [usuario.rol,rol]; arguments []; default message [rol]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.carloscortina.paidosSimple.model.Categoria' for property 'rol'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.carloscortina.paidosSimple.model.Categoria] for property 'rol': no matching editors or conversion strategy found]
DEBUG: org.springframework.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'appServlet': assuming HandlerAdapter completed request handling
DEBUG: org.springframework.web.servlet.DispatcherServlet - Successfully completed request
Usuario.java
package com.carloscortina.paidosSimple.model;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name="Usuario")
public class Usuario {
private Integer id;
private String username,password,email;
boolean acceptTerms = false,active=true;
private Categoria rol;
/**
* #return the id
*/
#Id
#GeneratedValue
#Column(name="id")
public Integer getId() {
return id;
}
/**
* #return the rol
*/
#OneToOne(cascade=CascadeType.ALL)
#JoinTable(name="usuario_rol",
joinColumns={#JoinColumn(name="Usuario",referencedColumnName="id")},
inverseJoinColumns={#JoinColumn(name="Rol",referencedColumnName="id")})
public Categoria getRol() {
return rol;
}
/**
* #param rol the rol to set
*/
public void setRol(Categoria rol) {
this.rol = rol;
}
/**
* #param id the id to set
*/
public void setId(Integer id) {
this.id = id;
}
/**
* #return the username
*/
#Column(name="Username")
public String getUsername() {
return username;
}
/**
* #param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* #return the password
*/
#Column(name="Password")
public String getPassword() {
return password;
}
/**
* #param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
/**
* #return the email
*/
#Column(name="Email")
public String getEmail() {
return email;
}
/**
* #param email the email to set
*/
public void setEmail(String email) {
this.email = email;
}
/**
* #return the acceptTerms
*/
#Column(name="acceptTerms")
public boolean isAcceptTerms() {
return acceptTerms;
}
/**
* #param acceptTerms the acceptTerms to set
*/
public void setAcceptTerms(boolean acceptTerms) {
this.acceptTerms = acceptTerms;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return "Usuario [id=" + id + ", username=" + username + ", password="
+ password + ", email=" + email + ", acceptTerms="
+ acceptTerms + "]";
}
}
Categoria.java
package com.carloscortina.paidosSimple.model;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name="Categoria")
public class Categoria {
private int id;
private String categoria,descripcion;
private Set<Usuario> UserRoles;
/**
* #return the userRoles
*/
#OneToMany(cascade=CascadeType.ALL)
#JoinTable(name="usuario_rol",
joinColumns={#JoinColumn(name="Categoria",referencedColumnName="id")},
inverseJoinColumns={#JoinColumn(name="Usuario",referencedColumnName="id")})
public Set<Usuario> getUserRoles() {
return UserRoles;
}
/**
* #param userRoles the userRoles to set
*/
public void setUserRoles(Set<Usuario> userRoles) {
UserRoles = userRoles;
}
/**
* #return the id
*/
#Id
#GeneratedValue
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the categoria
*/
public String getCategoria() {
return categoria;
}
/**
* #param categoria the categoria to set
*/
public void setCategoria(String categoria) {
this.categoria = categoria;
}
/**
* #return the descripcion
*/
public String getDescripcion() {
return descripcion;
}
/**
* #param descripcion the descripcion to set
*/
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}

Have you checked if your form submission works if you remove form:checbox, to ensure that indeed this checkbox is causing the issue
can you share debug logs of server
Also share your controller method that is hadnling this form submission including #requestMapping value
you can add a custom binder to convert rol into category
Create a custom property editor
public class CategoryEditor extends PropertyEditorSupport {
#Override
public void setAsText(String text) {
Category cat = new Category ();
//set rol vlaue in cat
setValue(cat);
}
now use following method in your controller
#InitBinder
public void initBinderAll(WebDataBinder binder) {
binder.registerCustomEditor(Category .class, new CategoryEditor ()); }

Related

Repository returns empty list in Spring boot

I am trying to write a simple REST to pull records from a table that was shared with me. Since the table doesn't have a default ID column, I embedded a pk column to the entity object. Please find the code below for your review.
The issue I'm facing is that the repository.findByMediaType, where mediaType is one of the entity properties, returns empty list. I made sure the query param is not null and there are records in the table for the param passed. I tried findAll as well but didn't work. I can't seem to find what's wrong with the code. I am new to spring boot and would like to know the different ways I can debug this.
Service implementation class
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.hyb.enterprisedashboard.api.entity.Tenders;
import com.hyb.enterprisedashboard.api.repository.DashboardRepository;
#Service
public class DashboardServiceImpl implements DashboardService{
Logger logger = LoggerFactory.getLogger(DashboardServiceImpl.class);
#Autowired
DashboardRepository dashboardRepository;
#Override
public List<Tenders> getTenderByMediaType(String mediaType) {
List<Tenders> tenderList = dashboardRepository.findAll();
//findByMediaType(mediaType);
tenderList.stream().forEach(tender -> {
logger.info("Order {} paid via {}",tender.getId().getOrderNumber(), tender.getMediaType());
});
return tenderList;
}
}
Entity class
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
#Entity
#Table(name = "TENDERS")
public class Tenders {
/** The id. */
#EmbeddedId
private TendersPK id;
/** The dateTime. */
#Column(name="DATE_TIME")
private Date dateTime;
/** The tenderMedia. */
#Column(name="TENDERED_MEDIA")
private String tenderMedia;
/** The mediaType. */
#Column(name="MEDIA_TYPE")
private String mediaType;
/** The tenderAmount. */
#Column(name="TENDERED_AMOUNT")
private BigDecimal tenderAmount;
/**
* #return the id
*/
public TendersPK getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(TendersPK id) {
this.id = id;
}
/**
* #return the dateTime
*/
public Date getDateTime() {
return dateTime;
}
/**
* #param dateTime the dateTime to set
*/
public void setDateTime(Date dateTime) {
this.dateTime = dateTime;
}
/**
* #return the tenderMedia
*/
public String getTenderMedia() {
return tenderMedia;
}
/**
* #param tenderMedia the tenderMedia to set
*/
public void setTenderMedia(String tenderMedia) {
this.tenderMedia = tenderMedia;
}
/**
* #return the mediaType
*/
public String getMediaType() {
return mediaType;
}
/**
* #param mediaType the mediaType to set
*/
public void setMediaType(String mediaType) {
this.mediaType = mediaType;
}
/**
* #return the tenderAmount
*/
public BigDecimal getTenderAmount() {
return tenderAmount;
}
/**
* #param tenderAmount the tenderAmount to set
*/
public void setTenderAmount(BigDecimal tenderAmount) {
this.tenderAmount = tenderAmount;
}
#Override
public String toString() {
return "Tenders [id=" + id + ", dateTime=" + dateTime + ", tenderMedia=" + tenderMedia + ", mediaType="
+ mediaType + ", tenderAmount=" + tenderAmount + "]";
}
}
PK Embedded class
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;
#Embeddable
public class TendersPK implements Serializable{
/** The Constant serialVersionUID.*/
private static final long serialVersionUID = 1L;
/**
*
*/
public TendersPK() {
}
/**
* #param storeNumber
* #param orderNumber
*/
public TendersPK(long storeNumber, long orderNumber) {
super();
this.storeNumber = storeNumber;
this.orderNumber = orderNumber;
}
#Column(name = "STORE_NUMBER")
private long storeNumber;
#Column(name = "ORDER_NUMBER")
private long orderNumber;
/**
* #return the storeNumber
*/
public long getStoreNumber() {
return storeNumber;
}
/**
* #param storeNumber the storeNumber to set
*/
public void setStoreNumber(long storeNumber) {
this.storeNumber = storeNumber;
}
/**
* #return the orderNumber
*/
public long getOrderNumber() {
return orderNumber;
}
/**
* #param orderNumber the orderNumber to set
*/
public void setOrderNumber(long orderNumber) {
this.orderNumber = orderNumber;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (orderNumber ^ (orderNumber >>> 32));
result = prime * result + (int) (storeNumber ^ (storeNumber >>> 32));
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof TendersPK))
return false;
TendersPK other = (TendersPK) obj;
if (orderNumber != other.orderNumber)
return false;
if (storeNumber != other.storeNumber)
return false;
return true;
}
#Override
public String toString() {
return "TendersPK [storeNumber=" + storeNumber + ", orderNumber=" + orderNumber + "]";
}
}
Repository class
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.hyb.enterprisedashboard.api.entity.Tenders;
import com.hyb.enterprisedashboard.api.entity.TendersPK;
#Repository
public interface DashboardRepository extends JpaRepository<Tenders, TendersPK>{
#Query("select t from Tenders t where t.mediaType = ?1")
List<Tenders> findByMediaType(String mediaType);
}
And I see the below query passed in the console
Hibernate: select tenders0_.order_number as order_number1_0_, tenders0_.store_number as store_number2_0_, tenders0_.date_time as date_time3_0_, tenders0_.media_type as media_type4_0_, tenders0_.tendered_amount as tendered_amount5_0_, tenders0_.tendered_media as tendered_media6_0_ from tenders tenders0_
Could anyone please help to find the cause?
This was happening to me and it turns out my spring.datasource.* properties were not being set. I had them in the wrong file and the were not being read.
I would think that my repository query would error out if I had not provided datasource url, username, and password - instead I would simply just get an empty list returned.
I ended up figuring out that I was not pulling my datasource credentials by adding this in my RestController:
#Value("${spring.datasource.username}")
String username;
Then I just printed username to the system.out.println. When starting the application I would get an error that spring.datasource.username was undefined. Hence I knew I was not loading datasource information that I thought I was.

JSF 2 managed bean is being shared across mulitple users logged in different window

I am using JSF2, Spring 3 and Mybatis. On user login, I am doing authentication from ConfigAutomationLoginBean.java which has other beans as its Managed properties. The problem is that my beans are being shared across multiple users in different browser window. All my beans are SessionScoped and if I don't keep it that way, I may not get navigation screen after login. I guess JSF creates all managed bean with SessionScoped attribute by default singleton. Would it be good idean if I make the initial bean authentication bean ie. ConfigAutomationLoginBean and other beans autorwired to it using Spring 3 and remove the JSF for intial bean loading? Below is my login code:
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.telus.routerconfigurationtool.dto.UserProfileDTO;
import com.telus.routerconfigurationtool.service.UserManagementService;
import com.telus.routerconfigurationtool.util.CommonUtil;
#Component
#ManagedBean(name = "configAutomationLoginBean")
#SessionScoped
public class ConfigAutomationLoginBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(ConfigAutomationLoginBean.class);
private String id;
private String password;
private String role;
#ManagedProperty(value = "#{userManagementService}")
private UserManagementService userManagementService;
#ManagedProperty(value = "#{treeNavigationBean}")
private TreeNavigationBean treeNavigationBean;
#ManagedProperty(value = "#{breadCrumbBean}")
private BreadCrumbBean breadCrumbBean;
public String authenticateUser() {
/** Reset and Update BreadCrumb - Add Nodes for Create User **/
breadCrumbBean.resetBreadCrumbModel();
Boolean authenticUser = false;
//TODO logic to authenticate user. authenticUser set true if authentication
//TODO Temporary setting to true
authenticUser = true;
if (authenticUser) {
return authorizeUser();
} else {
CommonUtil.displayFacesMessage(this.getClass(), FacesContext.getCurrentInstance(),
FacesMessage.SEVERITY_ERROR, "ERR1", id);
return "index";
}
}
private String authorizeUser() {
UserProfileDTO userProfileDTO = new UserProfileDTO();
CommonUtil.copyProperties(userProfileDTO, this);
Boolean authorizedUser = false;
// logic to authorize user. authorizedUser set true if authorization is
// successful
authorizedUser = userManagementService.authorizeUser(userProfileDTO);
if (authorizedUser) {
// Set User Role fetched from Database
this.role = userProfileDTO.getRole();
treeNavigationBean.setLoggedInUserId(id);
treeNavigationBean.setLoggedInUserRole(role);
treeNavigationBean.createTreeByUserRole();
treeNavigationBean.setViewCenterContent(null);
return "treeNavigation";
} else {
// Display Error Message that user is not authorized.
CommonUtil.displayFacesMessage(this.getClass(), FacesContext.getCurrentInstance(),
FacesMessage.SEVERITY_ERROR, "ERR2", id);
return "index";
}
}
/**
* #return the id
*/
public String getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(String id) {
if (StringUtils.isBlank(id)) {
this.id = id;
} else {
this.id = id.toUpperCase();
}
}
/**
* #return the password
*/
public String getPassword() {
return password;
}
/**
* #param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
/**
* #return the role
*/
public String getRole() {
return role;
}
/**
* #param role the role to set
*/
public void setRole(String role) {
this.role = role;
}
/**
* #return the userManagementService
*/
public UserManagementService getUserManagementService() {
return userManagementService;
}
/**
* #param userManagementService the userManagementService to set
*/
public void setUserManagementService(UserManagementService userManagementService) {
this.userManagementService = userManagementService;
}
/**
* #return the treeNavigationBean
*/
public TreeNavigationBean getTreeNavigationBean() {
return treeNavigationBean;
}
/**
* #param treeNavigationBean the treeNavigationBean to set
*/
public void setTreeNavigationBean(TreeNavigationBean treeNavigationBean) {
this.treeNavigationBean = treeNavigationBean;
}
/**
* #return the breadCrumbBean
*/
public BreadCrumbBean getBreadCrumbBean() {
return breadCrumbBean;
}
/**
* #param breadCrumbBean the breadCrumbBean to set
*/
public void setBreadCrumbBean(BreadCrumbBean breadCrumbBean) {
this.breadCrumbBean = breadCrumbBean;
}
}
Note: Since TreeNavigation bean is sessionscoped and single instance is shared, loggedInUserName is changed everytime different user is logging in. If user1 and user 2 logged in, then user1 who logged in first will see the screen of user2.
#ManagedBean(name = "treeNavigationBean")
#SessionScoped
public class TreeNavigationBean implements Serializable {
private static final long serialVersionUID = 1892577430001834938L;
private static final Logger LOGGER = Logger.getLogger(TreeNavigationBean.class);
private TreeNode root;
private TreeNode selectedNode;
private String loggedInUserId;
private String loggedInUserRole;
private String loggedInUserName;
private String viewCenterContent;
private String userAction;
#ManagedProperty(value = "#{userProfileBean}")
private UserProfileBean userProfileBean;
#ManagedProperty(value = "#{createConfigurationBean}")
private CreateConfigurationBean createConfigurationBean;
#ManagedProperty(value = "#{placeholderBean}")
private CreateConfigPlaceholderBean placeholderBean;
#ManagedProperty(value = "#{ncParamMappingBean}")
private NCParamMappingBean ncParamMappingBean;
#ManagedProperty(value = "#{breadCrumbBean}")
private BreadCrumbBean breadCrumbBean;
#ManagedProperty(value = "#{createTemplateBean}")
private CreateTemplateBean createTemplateBean;
#ManagedProperty(value = "#{configurationManagementBean}")
private ConfigurationManagementBean configurationManagementBean;
public void createTreeByUserRole() {
root = new DefaultTreeNode("Root", null);
if (TreeNodesEnum.SUPER_USER.equals(loggedInUserRole)) {
addCreateConfigurationNodes();
addTemplateAdministrationNodes();
addUserAdministrationNodes();
} else if (TreeNodesEnum.ADMIN_USER.equals(loggedInUserRole)) {
addCreateConfigurationNodes();
addTemplateAdministrationNodes();
} else if (TreeNodesEnum.NORMAL_USER.equals(loggedInUserRole)) {
addCreateConfigurationNodes();
}
}
.....................
With #Component you are using spring mvc beans instead of JSF beans. You can either switch to JSF beans or use Spring scopes, for example #Scope("session").

Spring MVC - Hibernate mapped object partially filled when using POST request method

Since I've decided to use same JSP for adding and editing posts, I just pass an attribute "saveUrl" which defines the action for my form in the JSP. Adding a new post works fine, but when editing a post, the object returned to the controller is missing all attributes except for the description.
What am I missing or doing wrong here?
Thanks for help!
My controller:
#Controller
public class BlogController {
private static final Logger logger = LoggerFactory.getLogger(BlogController.class);
#Autowired
private BlogPostManager bpManager;
#Autowired
private UserManager usrManager;
.....
#RequestMapping(value = "addPost", method = RequestMethod.GET)
public String addPost(Locale locale, Model model, Principal principal) {
model.addAttribute("post", new BlogPostEntity());
/** some more code here **/
return "addEditPost";
}
#RequestMapping(value = "addPostProcess", method = RequestMethod.POST)
public String addPostProcess(Locale locale, Model model, Principal principal, #ModelAttribute("post") BlogPostEntity blogPost) {
blogPost.setDate(new Date());
blogPost.setAuthor(usrManager.getUser(principal.getName()));
bpManager.addBlogPost(blogPost);
return "redirect:/latest";
}
#RequestMapping(value = "editPost/{id}", method = RequestMethod.GET)
public String editPost(Locale locale, Model model, Principal principal, #PathVariable Integer id) {
model.addAttribute("post", bpManager.getBlogPost(id));
model.addAttribute("username", getUsername(principal));
model.addAttribute("saveUrl", "");
return "addEditPost";
}
#RequestMapping(value = "editPost/{id}", method = RequestMethod.POST)
public String editPostProcess(Locale locale, Model model, Principal principal, #ModelAttribute("post") BlogPostEntity blogPost) {
bpManager.updateBlogPost(blogPost);
return "redirect:/latest";
}
/** some private methods **/
}
addEditPost.jsp
NOTE: this jsp is acting as a body of Apache tiles.
<h2>Create new post:</h2>
<form:form modelAttribute="post" action="${saveUrl}" method='POST'>
<table>
<tr>
<td><form:label path="title">Title:</form:label></td>
<td><form:input path="title"></form:input></td>
</tr>
<tr>
<td><form:label path="description">Description:</form:label></td>
<td><form:input path="description"></form:input></td>
</tr>
<tr>
<td><form:label path="text">Text:</form:label></td>
<td><form:input path="text"></form:input></td>
</tr>
<tr>
<td><input value="Save" type="submit"></td>
<td></td>
</tr>
</table>
</form:form>
The mapped BlogPost class:
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "BLOGPOST")
public class BlogPostEntity {
#Id
#GeneratedValue
#Column(name = "ID")
private int id;
#Column(name = "TITLE", nullable = false, length = 100)
private String title;
#Column(name = "DESCRIPTION", length = 500)
private String description;
#Column(name = "TEXT", length = 5000)
private String text;
#Column(name = "DATE")
private Date date;
#ManyToOne(targetEntity = UserEntity.class)
#JoinColumn(name = "authorid", referencedColumnName = "id")
private UserEntity author;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getId() {
return id;
}
public void setAuthor(UserEntity author) {
this.author = author;
}
public UserEntity getAuthor() {
return author;
}
}
DAO for blogpost:
import java.util.ArrayList;
import java.util.List;
import org.danizmax.simpleblog.entity.BlogPostEntity;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
#Repository("blogpostdao")
public class BlogPostDaoImpl implements BlogPostDao {
#Autowired
private SessionFactory sessionFactory;
#Override
public void addBlogPost(BlogPostEntity blogPost) {
getSession().persist(blogPost);
}
#Override
public void removeBlogPost(int id) {
BlogPostEntity entity = (BlogPostEntity) sessionFactory.getCurrentSession().load(BlogPostEntity.class, id);
if (entity != null) {
getSession().delete(entity);
}
}
#Override
#SuppressWarnings("unchecked")
public List<BlogPostEntity> latest() {
List<BlogPostEntity> result = new ArrayList<BlogPostEntity>();
try {
result = getSession().createQuery("FROM BlogPostEntity ORDER BY 'id' desc LIMIT 5;").list();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
#Override
#SuppressWarnings("unchecked")
public List<BlogPostEntity> listPosts(int userId) {
List<BlogPostEntity> result = new ArrayList<BlogPostEntity>();
try {
result = getSession().createQuery("FROM UserEntity").list();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
#Override
public void updateBlogPost(BlogPostEntity blogPost) {
blogPost = getBlogPost(blogPost.getId());
getSession().update(blogPost);
}
#Override
public BlogPostEntity getBlogPost(int id) {
return (BlogPostEntity) getSession().get(BlogPostEntity.class, id);
}
private Session getSession() {
return sessionFactory.getCurrentSession();
}
}
UPDATE: I've been experimenting a bit and tried method from HERE, but the object returned to the controler was still empty.
Then I changed the saveURL in JSP to (I read it might be important HERE):
<c:url var="addUrl" value="/secure/postProcess"/>
<form:form modelAttribute="post" action="${addUrl}" method='POST'>
and now the object is filled, only the id is still empty. So there is something probably wrong with the JSP.

Cross field bean validation - why you no work

I've got a little problem here with my application. I'd like to check if fields password and confirm password match together, so I tried to do it like in the first answer for this question: Cross field validation with Hibernate Validator (JSR 303)
The problem is that it actually doesn't work and I HAVE NO IDEA WHY. Please, help me! This is my first post here, so please don't be too harsh for me.
Here's my Annotation :
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package pl.lodz.p.zsk.ssbd2012.ssbd12.ValidationConstraints;
import java.lang.annotation.*;
import javax.validation.Constraint;
import javax.validation.Payload;
/**
*
* #author lukasz
*/
#Documented
#Constraint(validatedBy = FieldMatchValidator.class)
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface FieldMatch {
String message() default "{pl.lodz.p.zsk.ssbd2012.ssbd12.ValidationConstraints.FieldMatch}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String first();
String second();
}
Here's my ValidatorClass:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package pl.lodz.p.zsk.ssbd2012.ssbd12.ValidationConstraints;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.commons.beanutils.BeanUtils;
/**
*
* #author lukasz
*/
public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object> {
private String firstFieldName;
private String secondFieldName;
#Override
public void initialize(FieldMatch constraintAnnotation) {
firstFieldName = constraintAnnotation.first();
secondFieldName = constraintAnnotation.second();
}
#Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
try {
String sFirstField = BeanUtils.getProperty(value, firstFieldName);
String sSecondField = BeanUtils.getProperty(value, secondFieldName);
if(sFirstField.equals(sSecondField)){
return true;
}
} catch (IllegalAccessException ex) {
Logger.getLogger(FieldMatchValidator.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(FieldMatchValidator.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchMethodException ex) {
Logger.getLogger(FieldMatchValidator.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
}
And here's my bean:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package pl.lodz.p.zsk.ssbd2012.ssbd12.Beans;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import pl.lodz.p.zsk.ssbd2012.ssbd12.ValidationConstraints.CheckEmail;
import pl.lodz.p.zsk.ssbd2012.ssbd12.ValidationConstraints.FieldMatch;
import pl.lodz.p.zsk.ssbd2012.ssbd12.entities.Account;
import pl.lodz.p.zsk.ssbd2012.ssbd12.mok.endpoint.MokEndpointLocal;
/**
*
* #author krzys
* #author lukasz
*/
#ManagedBean
#RequestScoped
#FieldMatch(first = "password", second = "password2", message = "{pl.lodz.p.zsk.ssbd2012.ssbd12.ValidationConstraints.FieldMatch}")
public class RegisterBean {
/**
* Creates a new instance of RegisterBean
*/
#EJB
MokEndpointLocal endpoint;
#Size(min = 3, max = 16, message = "{pl.lodz.p.zsk.ssbd2012.ssbd12.Beans.RegisterBean.login.size}")
#Pattern(regexp = "[a-zA-Z0-9]+", message = "{pl.lodz.p.zsk.ssbd2012.ssbd12.Beans.RegisterBean.login.invalid}")
private String login;
#Size(min = 6, max = 64, message = "{pl.lodz.p.zsk.ssbd2012.ssbd12.Beans.RegisterBean.password.size}")
#Pattern(regexp = "[a-zA-Z0-9]+", message = "{pl.lodz.p.zsk.ssbd2012.ssbd12.Beans.RegisterBean.password.invalid}")
private String password;
private String password2;
#Pattern(regexp = "[A-Ż][a-ż]+", message = "{pl.lodz.p.zsk.ssbd2012.ssbd12.Beans.RegisterBean.name.invalid}")
private String name;
#Pattern(regexp = "[A-Ż][a-ż]+", message = "{pl.lodz.p.zsk.ssbd2012.ssbd12.Beans.RegisterBean.surname.invalid}")
private String surname;
#CheckEmail
private String email = "";
/**
* #return the login
*/
public String getLogin() {
return login;
}
/**
* #param login the login to set
*/
public void setLogin(String login) {
this.login = login;
}
/**
* #return the password
*/
public String getPassword() {
return password;
}
/**
* #param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
public String getPassword2() {
return password2;
}
public void setPassword2(String password2) {
this.password2 = password2;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String register ()
{
// Account account = new Account();
// account.setLogin(login);
// account.setHaslo(password);
// account.setImie(name);
// account.setNazwisko(surname);
// account.setEmail(email);
// endpoint.register(account);
return "registerSucces";
}
/**
* #return the surname
*/
public String getSurname() {
return surname;
}
/**
* #param surname the surname to set
*/
public void setSurname(String surname) {
this.surname = surname;
}
}
And here's JSF:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<h:outputStylesheet name="menu.css" library="css" />
<title>#{messages.registration}</title>
</h:head>
<h:body>
<ui:composition template="./../resources/mainTemplate.xhtml">
<h4>#{messages.registration}</h4>
<ui:define name="content">
<h4>#{messages.registration}</h4>
<h1>#{messages.registrationInfo1}</h1>
#{messages.registrationInfo2}
<h:form>
<h2>
<h:outputText value="#{messages.loginForm}"/>
<h:inputText id="login" value="#{registerBean.login}" />
</h2>
<h2>
<h:outputText value="#{messages.passwordForm}" />
<h:inputSecret id="password" value="#{registerBean.password}" />
</h2>
<h2>
<h:outputText value="#{messages.repeatPasswordForm}"/>
<h:inputSecret id="confirm" value="#{registerBean.password2}" />
</h2>
<h2>
<h:outputText value="#{messages.nameForm}"/>
<h:inputText id="name" value="#{registerBean.name}" />
</h2>
<h2>
<h:outputText value="#{messages.surnameForm}"/>
<h:inputText id="surname" value="#{registerBean.surname}" />
</h2>
<h2>
<h:outputText value="#{messages.emailForm}"/>
<h:inputText id="email" value="#{registerBean.email}" />
</h2>
<h2>
<h:commandButton value="#{messages.send}" action="#{registerBean.register()}" />
</h2>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
Class-level constraints are not triggered automatically by JSF during validation phase. You can use only field-level constraints (moreover not all fields are valuated by JSF but only those that are in your facelet).
If you want to use bean validation you can perform validation manually:
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Test>> violations = validator.validate( this, Default.class );
You can do it in registration method of your bean or after update model phase (but I've never tried it).
Anyway you can use JSF validation instead of bean validation or check the passwords directly in the registration method:
public String registration() {
...
if ( !password.equals(password2) ) {
FacesContext.getCurrentInstance().addMessage( null, new FacesMessage( "Passwords do not match" ) );
return null;
}
...
}

Cross field validation with HibernateValidator displays no error messages

I'm validating two fields, "password" and "confirmPassword" on the form for equality using HibernateValidator as specified in this answer. The following is the constraint descriptor (validator interface).
package constraintdescriptor;
import constraintvalidator.FieldMatchValidator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
#Target({TYPE, ANNOTATION_TYPE})
#Retention(RUNTIME)
#Constraint(validatedBy = FieldMatchValidator.class)
#Documented
public #interface FieldMatch
{
String message() default "{constraintdescriptor.fieldmatch}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* #return The first field
*/
String first();
/**
* #return The second field
*/
String second();
/**
* Defines several <code>#FieldMatch</code> annotations on the same element
*
* #see FieldMatch
*/
#Target({TYPE, ANNOTATION_TYPE})
#Retention(RUNTIME)
#Documented
public #interface List{
FieldMatch[] value();
}
}
The following is the constraint validator (the implementing class).
package constraintvalidator;
import constraintdescriptor.FieldMatch;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.commons.beanutils.BeanUtils;
public final class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object>
{
private String firstFieldName;
private String secondFieldName;
public void initialize(final FieldMatch constraintAnnotation) {
firstFieldName = constraintAnnotation.first();
secondFieldName = constraintAnnotation.second();
//System.out.println("firstFieldName = "+firstFieldName+" secondFieldName = "+secondFieldName);
}
public boolean isValid(final Object value, final ConstraintValidatorContext cvc) {
try {
final Object firstObj = BeanUtils.getProperty(value, firstFieldName );
final Object secondObj = BeanUtils.getProperty(value, secondFieldName );
//System.out.println("firstObj = "+firstObj+" secondObj = "+secondObj);
return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
}
catch (final Exception e) {
System.out.println(e.toString());
}
return true;
}
}
The following is the validator bean which is mapped with the JSP page (as specified commandName="tempBean" with the <form:form></form:form> tag).
package validatorbeans;
import constraintdescriptor.FieldMatch;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
#FieldMatch.List({
#FieldMatch(first = "password", second = "confirmPassword", message = "The password fields must match", groups={TempBean.ValidationGroup.class})
})
public final class TempBean
{
#NotEmpty(groups={ValidationGroup.class}, message="Might not be left blank.")
private String password;
#NotEmpty(groups={ValidationGroup.class}, message="Might not be left blank.")
private String confirmPassword;
public interface ValidationGroup {};
//Getters and setters
}
UPDATE
It's all working correctly and does the validation intended. Just one thing remains is to display the specified error message above the TempBean class within #FieldMatch is not being displayed i.e only one question : how to display error messages on the JSP page when validation violation occurs?
(the annotation #NotEmpty on both of the fields password and confirmPassword in the TempBean class works and displays the specified messages on violation, the thing is not happening with #FieldMatch).
I'm using validation group based on this question as specified in this blog and it works well causing no interruption in displaying error messages (as it might seem to be).
On the JSP page these two fields are specified as follows.
<form:form id="mainForm" name="mainForm" method="post" action="Temp.htm" commandName="tempBean">
<form:password path="password"/>
<font style="color: red"><form:errors path="password"/></font><br/>
<form:password path="confirmPassword"/>
<font style="color: red"><form:errors path="confirmPassword"/></font><br/>
</form:form>
Could you try your isValid method to be like this? (this is certainly working for me in live project):
public boolean isValid(final Object value, final ConstraintValidatorContext cvc){
boolean toReturn = false;
try{
final Object firstObj = BeanUtils.getProperty(value, firstFieldName );
final Object secondObj = BeanUtils.getProperty(value, secondFieldName );
//System.out.println("firstObj = "+firstObj+" secondObj = "+secondObj);
toReturn = firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
}
catch (final Exception e){
System.out.println(e.toString());
}
//If the validation failed
if(!toReturn) {
cvc.disableDefaultConstraintViolation();
//In the initialiaze method you get the errorMessage: constraintAnnotation.message();
cvc.buildConstraintViolationWithTemplate(errorMessage).addNode(firstFieldName).addConstraintViolation();
}
return toReturn;
}
Also I see that you are implementing the ConstraintValidator interface with an Object, literally. It should be the backing object that you have from your form:
tempBean // the one that you specify in the commandName actually.
So you implementation should like this:
implements ConstraintValidator<FieldMatch, TempBean>
This is probably not the issue here, but as a future reference, this is how it should be.
UPDATE
Inside your FieldMatch interface/annotation you have two methods : first and second, add one more called errorMessage for example:
Class<? extends Payload>[] payload() default {};
/**
* #return The first field
*/
String first();
/**
* #return The second field
*/
String second();
/**
#return the Error Message
*/
String errorMessage
Look inside you method from the Validation class - you are getting the first and second field names there., so just add the errorMessage, like this for example:
private String firstFieldName;
private String secondFieldName;
//get the error message name
private String errorMessagename;
public void initialize(final FieldMatch constraintAnnotation)
{
firstFieldName = constraintAnnotation.first();
secondFieldName = constraintAnnotation.second();
errorMessageNAme = constraintAnnotation.errorMessage();
//System.out.println("firstFieldName = "+firstFieldName+" secondFieldName = "+secondFieldName);
}
Inside isValida get it, the same way you do for first and second field name and use it.

Resources