I am aware of ResultBinding when trying to validate a form (get request), i am also aware of #Valid when trying to validate a request body but i have no knowledge of validating a multipartForm Request parameter. I have a multipart form with a request parameter #RequestParam("model") String userJson of a json string representation of my User.class. when i convert the json to an object,
User user = new Gson().fromJson(userJson, User.class);
how can i check if the parameters in the user class meets requirements, such as (email having an '#' or first name not having numeral values) ?
This is my code, the controller :
#RequestMapping(value = "/signup", method = RequestMethod.POST)
public ResponseEntity<ResponseModel> SignUp(#RequestParam("file") MultipartFile file, #RequestParam("model") String userJson, RedirectAttributes redirectAttributes){
User tempSavedUser = new User();
try {
if (file.isEmpty()) {
redirectAttributes.addFlashAttribute("message", "Please select a file to upload");
responseModel.setIsSuccessful(false).setResponseMessage("Please select an image to upload");
return new ResponseEntity<>(responseModel, HttpStatus.CREATED); // return response to client.
}
User user = new Gson().fromJson(userJson, User.class);
tempSavedUser = this.defaultUserDAOService.saveUser(user);
responseModel.setIsSuccessful(true);
responseModel.setResponseMessage("Registration was successful, Please check your mail for an account activation link");
return new ResponseEntity<ResponseModel>(responseModel, HttpStatus.CREATED);
}
this is the user class to:
#Table(name = "Users")
public class User extends DefaultEntity {
#Column(name = "FirstName")
#NotNull(message = "Enter a FirstName")
private String firstName;
#Column(name = "LastName")
#NotBlank(message = "Enter a LastName")
private String lastName;
#Column(unique = true,name = "UserName")
#NotBlank(message = "Enter a UserName")
private String userName;
#Column(unique = true, name = "Email")
#NotBlank(message = "Please enter an Email address")
#Email(message = "Enter a valid Email")
private String email;
#Column(name = "Password")
#NotBlank(message = "Enter a Password")
private String password;
#Enumerated(EnumType.STRING)
#Column(name = "Gender")
private Gender gender;
#Column(name = "Address")
#NotBlank(message = "Please enter your Home Address")
private String address;
#Column(name = "Country")
#NotBlank(message = "Please enter your Country")
private String country;
#Column(name = "Picture")
private String picture;
#Column(unique = true, name = "PhoneNumber") //make this accept only numbers
private String phoneNumber;
#Column(name = "Bio")
private String bio;
#Enumerated(EnumType.STRING)
#Column(name = "OnlineStatus")
private OnlineStatus onlineStatus;
#Enumerated(EnumType.STRING)
#Column(name = "UserType")
private UserType userType;
#Column(name = "Money")
private double money;
//#MapsId()
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "playerstats")
private PlayerStats playerStats;
//columnDefinition = "tinyint default false"
#Column(name = "locked",columnDefinition = "BOOL default false")
private Boolean locked;
#Transient
private MultipartFile file;
public String getFirstName() {
return firstName;
}
public User setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
public String getLastName() {
return lastName;
}
public User setLastName(String lastName) {
this.lastName = lastName;
return this;
}
public String getUserName() {
return userName;
}
public User setUserName(String userName) {
this.userName = userName;
return this;
}
public String getEmail() {
return email;
}
public User setEmail(String email) {
this.email = email;
return this;
}
public String getPassword() {
return password;
}
public User setPassword(String password) {
this.password = password;
return this;
}
public Enum.Gender getGender() {
return gender;
}
public User setGender(Enum.Gender gender) {
this.gender = gender;
return this;
}
public String getAddress() {
return address;
}
public User setAddress(String address) {
this.address = address;
return this;
}
public String getCountry() {
return country;
}
public User setCountry(String country) {
this.country = country;
return this;
}
public String getPicture() {
return picture;
}
public User setPicture(String picture) {
this.picture = picture;
return this;
}
public String getBio() {
return bio;
}
public User setBio(String bio) {
this.bio = bio;
return this;
}
public Enum.OnlineStatus getOnlineStatus() {
return onlineStatus;
}
public User setOnlineStatus(Enum.OnlineStatus onlineStatus) {
this.onlineStatus = onlineStatus;
return this;
}
public Enum.UserType getUserType() {
return userType;
}
public User setUserType(Enum.UserType userType) {
this.userType = userType;
return this;
}
public double getMoney() {
return money;
}
public User setMoney(double money) {
this.money = money;
return this;
}
public String getPhoneNumber() {
return phoneNumber;
}
public User setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
return this;
}
public MultipartFile getFile() {
return file;
}
public User setFile(MultipartFile file) {
this.file = file;
return this;
}
public PlayerStats getPlayerStats() {
return playerStats;
}
public User setPlayerStats(PlayerStats playerStats) {
this.playerStats = playerStats;
return this;
}
public Boolean getLocked() {
return locked;
}
public void setLocked(Boolean locked) {
this.locked = locked;
}
}
Inorder to validate a multipart form with spring you can take take this approach :
1. Add Dependencies
include the commons-fileupload which is used to upload a MultipartFile.
include the validation-api to create a Validator.
As:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
2.Create a Web Config:
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = {
"com.test"
})
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource rb = new ResourceBundleMessageSource();
rb.setBasenames(new String[] {
"validation"
});
return rb;
}
#Bean(name = "multipartResolver")
public CommonsMultipartResolver getResolver() {
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
//set max upload size per file is 20mb
commonsMultipartResolver.setMaxUploadSizePerFile(20 * 1024 * 1024);
return commonsMultipartResolver;
}
}
3.Create WebInitializer Class which extends from AbstractAnnotationConfigDispatcherServletInitializer
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class << ? > [] getRootConfigClasses() {
return new Class[] {
WebConfig.class
};
}
#Override
protected Class << ? > [] getServletConfigClasses() {
// TODO Auto-generated method stub
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] {
"/"
};
}
}
4. Create Your Model
public class Model {
private User user;
private CommonsMultipartFile[] files;
//getter and setter
}
5.Create a Validator to validate you file
#Component
public class ModelValidator implements Validator {
public boolean supports(Class << ? > clazz) {
return Model.class.isAssignableFrom(clazz);
}
public void validate(Object target, Errors errors) {
Model model = (Model) target;
CommonsMultipartFile[] commonsMultipartFiles = model.getFiles();
for (CommonsMultipartFile multipartFile: commonsMultipartFiles) {
if (multipartFile.getSize() == 0) {
errors.rejectValue("files", "myapplication.missing.file");
}
}
}
}
6. Add validation error message in side application.properties under resources folder
myapplication.missing.file=No file choose
7. Develop a controller
#Controller
#RequestMapping(value = "/")
public class Controller {
#Autowired
ModelValidator modelValidator;
#RequestMapping(value = "/page", method = RequestMethod.GET)
public ModelAndView page() {
ModelAndView model = new ModelAndView("page");
model.addObject("model", new Model());
return model;
}
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public ModelAndView upload(#ModelAttribute("model") Model model, BindingResult result) throws IOException {
// :::: VALIDATION HAPPENS HERE ::::
fileValidator.validate(model, result);
if (result.hasErrors()) {
return new ModelAndView("page");
}
return new ModelAndView("success", "fileNames", processUpload(model));
}
private List < String > processUpload(Model model) throws IOException {
List < String > Models = new ArrayList < String > ();
CommonsMultipartFile[] commonsMultipartFiles = model.getFiles();
for (CommonsMultipartFile multipartFile: commonsMultipartFiles) {
FileCopyUtils.copy(multipartFile.getBytes(), new File("C:\\upload\\" + multipartFile.getOriginalFilename()));
fileNames.add(multipartFile.getOriginalFilename());
}
return fileNames;
}
}
More Information:
https://memorynotfound.com/spring-mvc-file-upload-example-validator/
http://websystique.com/springmvc/spring-mvc-4-fileupload-download-hibernate-example/
http://javainsimpleway.com/spring-mvc-file-upload-with-validation/
Related
I have a Spring Boot project, in which when i create new account successfully, the property of that account returns null in the database
Controller class
import javax.validation.Valid;
#Controller
#RequestMapping("/music/backend/user")
public class UserController {
#Autowired
UserService userService;
#GetMapping("list")// Phương thức Get: Lấy dữ liệu ==> load trang ra dự form có sẵn trước
// #ResponseBody// trả về dạng json
public String list(Model model,
#RequestParam(name = "name",
required = false) String name){
//model: chuyền biến từ java -> jsp
Object obj= null;
if(name==null){
obj=userService.findAll();
}else{
obj=userService.searchByEmail(name);
}
model.addAttribute("title", name);
model.addAttribute("list", obj);
return "/jsp/list.jsp";
}
#GetMapping("create")
public String create(Model model,
#RequestParam(name = "name",
required = false) String name){
//model: chuyền biến từ java -> jsp
// Object authors= userService.findAllAuthor();
model.addAttribute("title", "Tạo Mới User");
UserDto userDto= new UserDto();
model.addAttribute("userDto",userDto);
// model.addAttribute("authors", authors);
return "/jsp/signup.jsp";
}
// #GetMapping("edit/{id}")// Phương thức Get: Lấy dữ liệu
// public String create(Model model, #PathVariable Integer id){
//// Object authors = bookService.findAllAuthor();
// model.addAttribute("user", userService.getById(id));
// model.addAttribute("title", "Cập nhật tài khoản");
//// model.addAttribute("authors", authors);
// return "/jsp/user_edit.jsp";
// }
#GetMapping("delete/{id}")
public String delete(RedirectAttributes redirectAttributes, #PathVariable Integer id){
userService.deleteById(id);
redirectAttributes.addFlashAttribute("message", "Xóa thành công");
return "redirect:/music/backend/user/list";
}
#PostMapping(value = "save", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String save( UserDto userDto,
Model model, RedirectAttributes redirectAttributes) {
userService.save(userDto);
redirectAttributes.addFlashAttribute("message", "Tạo mới thành công");
return "redirect:/music/backend/user/list";
}
}
UserDto class
#Data
public class UserDto {
private int id;
private String username;
private String email;
private String password;
private String sex;
private Date dob;
}
UserEntity class
import javax.persistence.*;
import java.sql.Date;
import java.util.Objects;
#Entity
#Table(name = "user", schema = "ktpm", catalog = "")
public class UserEntity {
private Integer id;
private String username;
private String email;
private String password;
private String sex;
private Date dob;
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Basic
#Column(name = "user_name")
public String getUserName() {
return username;
}
public void setUserName(String username) {
this.username = username;
}
#Basic
#Column(name = "user_email")
public String getUserEmail() {
return email;
}
public void setUserEmail(String email) {
this.email = email;
}
#Basic
#Column(name = "user_password")
public String getUserPassword() {
return password;
}
public void setUserPassword(String password) {
this.password = password;
}
#Basic
#Column(name = "user_sex")
public String getUserSex() {
return sex;
}
public void setUserSex(String sex) {
this.sex = sex;
}
#Basic
#Column(name = "user_date")
public Date getUserDate() {
return dob;
}
public void setUserDate(Date dob) {
this.dob = dob;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserEntity that = (UserEntity) o;
return Objects.equals(id, that.id) &&
Objects.equals(username, that.username) &&
Objects.equals(email, that.email) &&
Objects.equals(password, that.password) &&
Objects.equals(sex, that.sex) &&
Objects.equals(dob, that.dob);
}
#Override
public int hashCode() {
return Objects.hash(id, username, email, password, sex, dob);
}
}
UserService class
#Service
public class UserService {
#Autowired
UserRepository userRepository;
public String save(UserDto userDto) {
UserEntity userEntity = new UserEntity();
BeanUtils.copyProperties(userDto, userEntity);
// lưu vào db
userRepository.save(userEntity);
return "tạo mới thành công ";
}
public List<UserEntity> findAll(){
return userRepository.findAll();
}
public UserEntity getById(Integer id){
return userRepository.findById(id).get(); // sự # giữa orm và jdbc
}
public String deleteById(Integer id){
userRepository.deleteById(id);
return "xóa thành công";
}
public List<UserEntity> searchByEmail(String email){
return userRepository.findAllByUserEmailContaining(email);
}
}
user_list.jsp
Danh sách book:
${title}
<br>
<h2 class="color-red" >${message}</h2>
<a class="color-red" href="/backend/user/create">Tạo mới</a>
<br>
<input id="search" value="${title}"/> <button onclick="searchClick()">Tìm kiếm</button>
<script>
function searchClick() {
var name = document.getElementById("search").value;
window.location.href = "/backend/user/list?name="+name;
}
</script>
<table>
<thead>
<th>Email</th>
<th>Họ và tên</th>
<th>Địa chỉ</th>
<th>Ngày sinh</th>
<th>Hành động</th>
</thead>
<tbody>
<c:forEach items="${list}" var="s">
<tr>
<td>${s.email}</td>
<td>${s.fullName}</td>
<td>${s.address}</td>
<td>${s.dateOfBirth}</td>
<td>Xóa</td>
</tr>
</c:forEach>
</tbody>
</table>
when i create new account successfully, the property of that account returns null in the database, how should i fix it
What dependency are you using for BeanUtils ?
org.apache.commons.beanutils
or
org.springframework.beans.
For the first one BeanUtils.copyProperties(Object res, Object src), for the second this is BeanUtils.copyProperties(Object src, Object res).
In the mysql database, the transaction table has successfully had the accountId field added via Java code. However, whenever I add a transaction on the React frontend, the account_id column value in the database is null. What could I be doing wrong?
Account entity:
#Entity
public class Account {
#Id
#GeneratedValue
public long id;
private String username;
private String accountName;
private Date asOfDate;
#OneToMany(mappedBy="account", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Transaction> transactions = new ArrayList<>();
protected Account() {
}
public Account(String username, String accountName, Date asOfDate) {
super();
this.username = username;
this.accountName = accountName;
this.asOfDate = asOfDate;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public Date getAsOfDate() {
return asOfDate;
}
public void setAsOfDate(Date asOfDate) {
this.asOfDate = asOfDate;
}
public List<Transaction> getTransactions() {
return transactions;
}
public void setTransactions(List<Transaction> transactions) {
this.transactions = transactions;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Account other = (Account) obj;
if (id != other.id)
return false;
return true;
}
}
Transaction entity:
#Entity
public class Transaction {
#Id
#GeneratedValue
private long id;
private String username;
private Date transactionDate;
private String transactionType;
private String depositCategory;
private String withdrawalCategory;
private double transactionAmount;
private String notes;
#ManyToOne
#JoinColumn(name="account_id")
private Account account;
protected Transaction() {
}
public Transaction(String username, Date transactionDate, String transactionType, String depositCategory,
String withdrawalCategory, double transactionAmount, String notes){
super();
this.username = username;
this.transactionDate = transactionDate;
this.transactionType = transactionType;
this.depositCategory = depositCategory;
this.withdrawalCategory = withdrawalCategory;
this.transactionAmount = transactionAmount;
this.notes = notes;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getTransactionDate() {
return transactionDate;
}
public void setTransactionDate(Date transactionDate) {
this.transactionDate = transactionDate;
}
public String getTransactionType() {
return transactionType;
}
public void setTransactionType(String transactionType) {
this.transactionType = transactionType;
}
public String getDepositCategory() {
return depositCategory;
}
public void setDepositCategory(String depositCategory) {
this.depositCategory = depositCategory;
}
public String getWithdrawalCategory() {
return withdrawalCategory;
}
public void setWithdrawalCategory(String withdrawalCategory) {
this.withdrawalCategory = withdrawalCategory;
}
public double getTransactionAmount() {
return transactionAmount;
}
public void setTransactionAmount(double transactionAmount) {
this.transactionAmount = transactionAmount;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Transaction other = (Transaction) obj;
if (id != other.id)
return false;
return true;
}
}
TransactionJpaResource:
#CrossOrigin(origins = "http://localhost:4200")
#RestController
public class TransactionJpaResource {
#Autowired
private TransactionService transactionService;
#Autowired
private TransactionJpaRepository transactionJpaRepository;
#GetMapping("/jpa/users/{username}/transactions")
public List<Transaction> getAllTransactions(#PathVariable String username) {
return transactionJpaRepository.findByUsername(username);
}
#GetMapping("/jpa/users/{username}/transactions/{id}")
public Transaction getTransaction(#PathVariable String username, #PathVariable long id) {
return transactionJpaRepository.findById(id).get();
}
// DELETE /users/{username}/transactions/{id}
#DeleteMapping("/jpa/users/{username}/transactions/{id}")
public ResponseEntity<Void> deleteTransaction(#PathVariable String username, #PathVariable long id) {
transactionJpaRepository.deleteById(id);
return ResponseEntity.noContent().build();
}
//Edit/Update a Transaction
//PUT /users/{username}/transactions/{id}
#PutMapping("/jpa/users/{username}/transactions/{id}")
public ResponseEntity<Transaction> updateTransaction(
#PathVariable String username,
#PathVariable long id, #RequestBody Transaction transaction){
transaction.setUsername(username);
Transaction transactionUpdated = transactionJpaRepository.save(transaction);
return new ResponseEntity<Transaction>(transaction, HttpStatus.OK);
}
#PostMapping("/jpa/users/{username}/transactions")
public ResponseEntity<Void> createTransaction (
#PathVariable String username, #RequestBody Transaction transaction){
transaction.setUsername(username);
Transaction createdTransaction = transactionJpaRepository.save(transaction);
URI uri = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}").buildAndExpand(createdTransaction.getId()).toUri();
return ResponseEntity.created(uri).build();
}
}
TransactionJpaRepository:
#Repository
public interface TransactionJpaRepository extends JpaRepository<Transaction, Long> {
List<Transaction> findByUsername(String username);
}
Relevant React code from the transactions form:
let username = AuthenticationService.getLoggedInUsername();
fetch(`http://localhost:8080/jpa/users/${username}/transactions`, {
method: "POST",
body: JSON.stringify({
accountId: this.state.accountId,
transactionDate: this.state.transactionDate,
transactionType: this.state.transactionType,
depositCategory: this.state.depositCategory,
withdrawalCategory: this.state.withdrawalCategory,
transactionAmount: this.state.transactionAmount,
notes: this.state.notes,
}),
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
})
.then((result) => result.text())
.then((data) => console.log(data));
};
...
handleAccountNameChange = (event) => {
this.setState({ accountId: event.target.value });
};
This is what I did to fix the issue:
In React, in the transactions form:
fetch(`http://localhost:8080/jpa/users/${username}/transactions`, {
method: "POST",
body: JSON.stringify({
username: this.state.username,
transactionDate: this.state.transactionDate,
transactionType: this.state.transactionType,
depositCategory: this.state.depositCategory,
withdrawalCategory: this.state.withdrawalCategory,
transactionAmount: this.state.transactionAmount,
notes: this.state.notes,
account: ({
id: this.state.accountId,
username: this.state.username,
accountName: this.state.accountName,
asOfDate: this.state.asOfDate
})
}),
In the Account entity:
#Entity
#Table(name = "account")
public class Account {
#Id
#GeneratedValue
public long id;
private String username;
private String accountName;
private Date asOfDate;
#OneToMany(mappedBy = "account", cascade = { CascadeType.PERSIST, CascadeType.ALL, CascadeType.MERGE })
#JsonIgnore
private List<Transaction> transactions = new ArrayList<>();
In the Transaction entity:
#Entity
#Table(name = "transaction")
public class Transaction {
In TransactionJpaResource:
#PostMapping("/jpa/users/{username}/transactions")
public ResponseEntity<String> createTransaction(#PathVariable String username,
#RequestBody Transaction transaction) {
transaction.setUsername(username);
Transaction createdTransaction = transactionJpaRepository.save(transaction);
URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
.buildAndExpand(createdTransaction.getId()).toUri();
ResponseEntity<Object> build = ResponseEntity.created(uri).build();
int statusCodeValue = build.getStatusCodeValue();
if (build.getStatusCodeValue() == 201) {
return new ResponseEntity<String>("Data has been Inserted Successfully", HttpStatus.OK);
} else {
return new ResponseEntity<String>("Something went wrong", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
I'm trying to login with users from database, but I have this error. I think the problem appears in class "UserDetailsServiceImpl". What I have to do to fix this error? I will be grateful for any hint or idea...........................................................................
2018-03-16 11:13:40.389 ERROR 6520 --- [nio-8080-exec-5]
w.a.UsernamePasswordAuthenticationFilter : An internal error occurred while trying to authenticate the user.org.springframework.security.authentication.InternalAuthenticationServiceException: failed to lazily initialize a collection of role: com.continental.qtools.fingerprints.models.User.roles, could not initialize proxy - no Session
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:126) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:144) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
This is entity "User"
#Entity
#Table(name = "users")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "user_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int userId;
#Column(name = "username")
#NotEmpty(message = "*Please provide your username")
private String username;
#Column(name = "password")
#Length(min = 5, message = "*Your password must have at least 5 characters")
#NotEmpty(message = "*Please provide your password")
private String password;
#Column(name = "email")
#Email(message = "*Please provide a valid Email")
#NotEmpty(message = "*Please provide an email")
private String email;
#Transient
private String passwordConfirm;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "users_roles", joinColumns = #JoinColumn(name = "user_id"), inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "users_projects", joinColumns = #JoinColumn)
private List<Project> projects;
public User(String username, String password, String email, String passwordConfirm, Set<Role> roles,
List<Project> projects) {
super();
this.username = username;
this.password = password;
this.email = email;
this.passwordConfirm = passwordConfirm;
this.roles = roles;
this.projects = projects;
}
public User() {
// TODO Auto-generated constructor stub
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getUserId() {
return userId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPasswordConfirm() {
return passwordConfirm;
}
public void setPasswordConfirm(String passwordConfirm) {
this.passwordConfirm = passwordConfirm;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Project> getProjects() {
return projects;
}
public void setProjects(List<Project> projects) {
this.projects = projects;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
#Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", email=" + email + ", passwordConfirm="
+ passwordConfirm + ", roles=" + roles + ", projects=" + projects + "]";
}
}
This is entity "Role"
#Entity
#Table(name = "roles")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "role_id")
private int id;
#Column(name = "role")
private String role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
UserDetailsServiceImp
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
System.out.println("User: " + user.getUsername());
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
for (Role role : user.getRoles()) {
grantedAuthorities.add(new SimpleGrantedAuthority(role.getRole()));
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
grantedAuthorities);
}
}
Try adding a FetchType.EAGER to the roles property on the user object.
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "users_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id")
)
private Set<Role> roles;
Update: Alternative refactor with Privileges included
Authority Class instead of Role Class
#Entity
#Table(name = "authority")
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Authority implements GrantedAuthority {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
#ManyToMany
#JoinTable(
name = "authorities_privileges",
joinColumns = #JoinColumn(
name = "authority_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(
name = "privilege_id", referencedColumnName = "id"))
private Collection<Privilege> privileges;
public Authority() {
super();
}
public Authority(final String name) {
super();
this.name = name;
}
public Authority(String name,
Collection<Privilege> privileges) {
this.name = name;
this.privileges = privileges;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Collection<Privilege> getPrivileges() {
return privileges;
}
public void setPrivileges(Collection<Privilege> privileges) {
this.privileges = privileges;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (obj.toString().equals(this.name)) {
return true;
}
if (getClass() != obj.getClass()) {
return false;
}
final Authority auth = (Authority) obj;
if (this.name != null && this.name.equals(auth.name)) {
return true;
}
return false;
}
#Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("Role [name=").append(name).append("]").append("[id=").append(id).append("]");
return builder.toString();
}
#Override
#JsonIgnore
public String getAuthority() {
return name;
}
}
Privilege Class (Optional)
#Entity
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Privilege {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
private String name;
public Privilege() {
super();
}
public Privilege(final String name) {
super();
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
User Class
#Entity
#Table(name = "user_account")
public class User implements UserDetails {
#Id
#Column(unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "username")
private String username;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "email")
private String email;
#JsonIgnore
#Column(name = "password", length = 60)
private String password;
#Column(name = "enabled")
private boolean enabled;
#Column(name = "last_password_reset_date")
private Timestamp lastPasswordResetDate;
#Column(name = "is_using_2FA")
private boolean isUsing2FA;
#JsonIgnore
#Column(name = "secret", length = 60)
private String secret;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "user_authority",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "authority_id", referencedColumnName = "id"))
private Collection<Authority> authorities;
public User() {
this.secret = UUID.randomUUID().toString();
this.enabled = false;
}
public User(Long id,
String username, String firstName, String lastName,
String email, String password,
boolean enabled, Timestamp lastPasswordResetDate,
boolean isUsing2FA, String secret,
Collection<Authority> authorities) {
this.id = id;
this.username = username;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
this.enabled = enabled;
this.lastPasswordResetDate = lastPasswordResetDate;
this.isUsing2FA = isUsing2FA;
this.secret = secret;
this.authorities = authorities;
}
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(final String username) {
this.email = username;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
Date date = new Date();
this.lastPasswordResetDate = new Timestamp(date.getTime());
this.password = password;
}
#Override
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public boolean isUsing2FA() {
return isUsing2FA;
}
public void setUsing2FA(boolean isUsing2FA) {
this.isUsing2FA = isUsing2FA;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.authorities;
}
#Override
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Timestamp getLastPasswordResetDate() {
return lastPasswordResetDate;
}
public void setLastPasswordResetDate(Timestamp lastPasswordResetDate) {
this.lastPasswordResetDate = lastPasswordResetDate;
}
#JsonIgnore
#Override
public boolean isAccountNonExpired() {
return true;
}
#JsonIgnore
#Override
public boolean isAccountNonLocked() {
return true;
}
#JsonIgnore
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + ((username == null) ? 0 : username.hashCode());
return result;
}
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final User user = (User) obj;
if (!username.equals(user.username)) {
return false;
}
return true;
}
#Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("User [id=").append(id).append(", firstName=").append(firstName).append(", lastName=").append(lastName).append(", email=").append(email).append(", password=").append(password).append(", enabled=").append(enabled).append(", isUsing2FA=")
.append(isUsing2FA).append(", secret=").append(secret).append(", roles=").append(authorities).append("]");
return builder.toString();
}
}
UserBuilder Class
public class UserBuilder {
private Long bId;
private String bUsername;
private String bFirstName;
private String bLastName;
private String bEmail;
private String bPassword;
private boolean bEnabled;
private Timestamp bLastPasswordResetDate;
private boolean bIsUsing2FA;
private String bSecret;
private Collection<Authority> bAuthorities;
public UserBuilder() {
}
public UserBuilder(Long bId,
String bUsername, String bFirstName, String bLastName,
String bEmail, String bPassword, boolean bEnabled,
Timestamp bLastPasswordResetDate, boolean bIsUsing2FA, String bSecret,
Collection<Authority> authorities) {
this.bId = bId;
this.bUsername = bUsername;
this.bFirstName = bFirstName;
this.bLastName = bLastName;
this.bEmail = bEmail;
this.bPassword = bPassword;
this.bEnabled = bEnabled;
this.bLastPasswordResetDate = bLastPasswordResetDate;
this.bIsUsing2FA = bIsUsing2FA;
this.bSecret = bSecret;
this.bAuthorities = bAuthorities;
}
public UserBuilder(User user) {
this.bId = user.getId();
this.bUsername = user.getUsername();
this.bFirstName = user.getFirstName();
this.bLastName = user.getLastName();
this.bEmail = user.getEmail();
this.bPassword = user.getPassword();
this.bEnabled = user.isEnabled();
this.bLastPasswordResetDate = user.getLastPasswordResetDate();
this.bIsUsing2FA = user.isUsing2FA();
this.bSecret = user.getSecret();
}
public User createUser() {
return new User(bId,
bUsername,
bFirstName,
bLastName,
bEmail,
bPassword,
bEnabled,
bLastPasswordResetDate,
bIsUsing2FA,
bSecret,
bAuthorities
);
}
public UserBuilder bId(Long bId) {
this.bId = bId;
return this;
}
public UserBuilder bUsername(String bUsername) {
this.bUsername = bUsername;
return this;
}
public UserBuilder bFirstName(String bFirstName) {
this.bFirstName = bFirstName;
return this;
}
public UserBuilder bLastName(String bLastName) {
this.bLastName = bLastName;
return this;
}
public UserBuilder bEmail(String bEmail) {
this.bEmail = bEmail;
return this;
}
public UserBuilder bPassword(String bPassword) {
Date date = new Date();
this.bLastPasswordResetDate = new Timestamp(date.getTime());
this.bPassword = bPassword;
return this;
}
public UserBuilder bEnabled(boolean bEnabled) {
this.bEnabled = bEnabled;
return this;
}
public UserBuilder bLastPasswordResetDate(Timestamp bLastPasswordResetDate) {
this.bLastPasswordResetDate = bLastPasswordResetDate;
return this;
}
public UserBuilder bIsUsing2FA(boolean bIsUsing2FA) {
this.bIsUsing2FA = bIsUsing2FA;
return this;
}
public UserBuilder bSecret(String bSecret) {
this.bSecret = bSecret;
return this;
}
public UserBuilder bAuthorities(Collection<Authority> bAuthorities) {
this.bAuthorities = bAuthorities;
return this;
}
}
CustomUserDetailsService Class
#Service("userDetailsService")
#Transactional
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#SuppressWarnings("unchecked")
#Override
public UserDetails loadUserByUsername(final String identity) throws UsernameNotFoundException {
try {
final User user = Optional.ofNullable(userRepository.findByEmail(identity)).orElseGet(() -> userRepository.findByUsername(identity));
if (user == null) {
throw new UsernameNotFoundException("No user found with username: " + identity);
}
//Collection<Authority> authorities = getAuthorities((Collection<Authority>) user.getAuthorities());
Collection<Authority> authorities = getAuthorities((Collection<Authority>) user.getAuthorities());
return new UserBuilder(user).bAuthorities(authorities).createUser();
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
private final Collection<Authority> getAuthorities(final Collection<Authority> authorityList) {
return getGrantedAuthorities(getAuthorityList(authorityList));
}
private final List<String> getAuthorityList(final Collection<Authority> authorityList) {
final List<String> authorities = new ArrayList<String>();
for (final Authority authority : authorityList) {
authorities.add(authority.getName());
if (authority.getPrivileges() == null || authority.getPrivileges().isEmpty()) continue;
// Add all Privileges as Authorities
for (final Privilege item : authority.getPrivileges()) {
authorities.add(item.getName());
}
}
return authorities;
}
private final Collection<Authority> getGrantedAuthorities(final List<String> authorityList) {
final List<Authority> grantedAuthorities = new ArrayList<Authority>();
for (final String authority : authorityList) {
grantedAuthorities.add(new Authority(authority));
}
return grantedAuthorities;
}
}
Repos
public interface PrivilegeRepository extends JpaRepository<Privilege, Long> {
Privilege findByName(String name);
#Override
void delete(Privilege privilege);
}
public interface RoleRepository extends JpaRepository<Authority, Long> {
Authority findByName(String name);
#Override
void delete(Authority role);
}
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
User findByUsername(String username);
#Override
void delete(User user);
}
SetupDataLoader Class (Optional)
#Component
public class SetupDataLoader implements ApplicationListener<ContextRefreshedEvent> {
private boolean alreadySetup = false;
#Autowired
private UserRepository userRepository;
#Autowired
private RoleRepository roleRepository;
#Autowired
private PrivilegeRepository privilegeRepository;
#Autowired
private PasswordEncoder passwordEncoder;
#Autowired
BeerRepository beerRepository;
#Override
#Transactional
public void onApplicationEvent(final ContextRefreshedEvent event) {
if (alreadySetup) {
return;
}
// == create initial privileges
final Privilege userReadPrivilege = createPrivilegeIfNotFound("USER_READ_PRIVILEGE");
final Privilege userWritePrivilege = createPrivilegeIfNotFound("USER_WRITE_PRIVILEGE");
final Privilege beerReadPrivilege = createPrivilegeIfNotFound("BEER_READ_PRIVILEGE");
final Privilege beerWritePrivilege = createPrivilegeIfNotFound("BEER_WRITE_PRIVILEGE");
final Privilege passwordPrivilege = createPrivilegeIfNotFound("CHANGE_PASSWORD_PRIVILEGE");
// == create initial roles
final List<Privilege> adminPrivileges = new ArrayList<Privilege>(Arrays.asList(beerReadPrivilege, beerWritePrivilege, userReadPrivilege, userWritePrivilege, passwordPrivilege));
final List<Privilege> userPrivileges = new ArrayList<Privilege>(Arrays.asList(beerReadPrivilege, beerWritePrivilege));
final Authority adminAuthority = createRoleIfNotFound("ROLE_ADMIN", adminPrivileges);
createRoleIfNotFound("ROLE_USER", userPrivileges);
// == create initial user
createUserIfNotFound("rdurden",
"rdurden#example.com",
"Rupert",
"Durden",
"ILikeBeer2!",
new ArrayList<Authority>(Arrays.asList(adminAuthority)));
alreadySetup = true;
}
#Transactional
Privilege createPrivilegeIfNotFound(final String name) {
Privilege privilege = privilegeRepository.findByName(name);
if (privilege == null) {
privilege = new Privilege(name);
privilege = privilegeRepository.save(privilege);
}
return privilege;
}
#Transactional
Authority createRoleIfNotFound(final String name, final Collection<Privilege> privileges) {
Authority authority = roleRepository.findByName(name);
if (authority == null) {
authority = new Authority(name);
}
authority.setPrivileges(privileges);
authority = roleRepository.save(authority);
return authority;
}
#Transactional
User createUserIfNotFound(final String username, final String email, final String firstName, final String lastName, final String password, final Collection<Authority> authorities) {
User user = Optional.ofNullable(userRepository.findByEmail(email)).orElseGet(() -> userRepository.findByUsername(username));
if (user != null) return user;
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, -1);
Date lastMonthDate = cal.getTime();
Timestamp lastMonthTimestamp = new Timestamp(lastMonthDate.getTime());
user = new UserBuilder()
.bAuthorities(authorities)
.bUsername(username)
.bFirstName(firstName)
.bLastName(lastName)
.bEmail(email)
.bPassword(passwordEncoder.encode(password))
.bIsUsing2FA(false)
.bEnabled(true)
.bLastPasswordResetDate(lastMonthTimestamp)
.createUser();
user = userRepository.save(user);
return user;
}
}
Try adding #Transactional to method loadUserByUsername.
I have a problem with Hibernate. Im struggling with this since yesterday, it seems very easy but I have no idea why it is not working...
I have entity Login.java:
package offersmanager.model.entity;
import org.json.JSONObject;
import javax.persistence.*;
#Entity
public class Login {
#Id
#GeneratedValue
private Integer id;
#Column(nullable = false, unique = true)
String username;
#Column(nullable = false)
String password;
public Login(){
}
public Login(String username, String password){
this.username = username;
this.password = password;
}
public Login(JSONObject jsonObject) {
this.id = (Integer) jsonObject.get("id");
this.username = (String) jsonObject.get("username");
this.password = (String) jsonObject.get("password");
}
public JSONObject toJsonObject() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", this.id);
jsonObject.put("username", this.username);
jsonObject.put("password", this.password);
return jsonObject;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
And entity TourOffice.java:
package offersmanager.model.entity;
import org.json.JSONObject;
import javax.persistence.*;
#Entity
public class TourOffice {
#Id
#GeneratedValue
private Integer id;
#Column(nullable = false)
String officeName;
#Column(nullable = false)
String eMail;
#Column(nullable = false)
String phoneNumber;
#Column(nullable = false)
String city;
#Column(nullable = false)
String zipCode;
#Column(nullable = false)
String address;
#OneToOne(cascade = {CascadeType.ALL})
#JoinColumn(name = "login_id")
Login login;
public TourOffice(){
}
public TourOffice(String officeName, String eMail, String phoneNumber, String city, String zipCode, String address) {
this.officeName = officeName;
this.eMail = eMail;
this.phoneNumber = phoneNumber;
this.city = city;
this.zipCode = zipCode;
this.address = address;
}
public TourOffice(JSONObject jsonObject) {
this.id = (Integer) jsonObject.get("id");
this.officeName = (String) jsonObject.get("officeName");
this.eMail = (String) jsonObject.get("eMail");
this.phoneNumber = (String) jsonObject.get("phoneNumber");
this.city = (String) jsonObject.get("city");
this.zipCode = (String) jsonObject.get("zipCode");
this.address = (String) jsonObject.get("address");
this.login = (new Login((JSONObject) jsonObject.get("login")));
}
public JSONObject toJsonObject() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", this.id);
jsonObject.put("officeName", this.officeName);
jsonObject.put("eMail", this.eMail);
jsonObject.put("phoneNumber", this.phoneNumber);
jsonObject.put("city", this.city);
jsonObject.put("zipCode", this.zipCode);
jsonObject.put("address", this.address);
jsonObject.put("login", this.login == null? null : login.toJsonObject());
return jsonObject;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getOfficeName() {
return officeName;
}
public void setOfficeName(String officeName) {
this.officeName = officeName;
}
public String geteMail() {
return eMail;
}
public void seteMail(String eMail) {
this.eMail = eMail;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Login getLogin() {
return login;
}
public void setLogin(Login login) {
this.login = login;
}
}
These entities are connected with #OneToOne relation.
What I'm trying to do is to find the name of my office (officeName) with field of Login class (username).
This is my function in TourOfficeDAO.java:
public TourOffice findOfficeNameByLogin(String username) {
Criteria name = createCriteria();
name.add(Restrictions.eq("login.username", username));
return (TourOffice) name.uniqueResult();
}
It goes through TourOfficeService to my rest controller where this method is invoked. But it doesn't matter cause exeception is thrown in DAO:
could not resolve property: login.username of:
offersmanager.model.entity.TourOffice; nested exception is
org.hibernate.QueryException: could not resolve property:
login.username of: offersmanager.model.entity.TourOffice
It can't find "login.username" and have no idea why... everything seems good.
I looked for similiar topics but I haven't still managed to make this works. Any help would be appreciated.
EDIT 1:
This is my abstract class DAO.java where is the function createCriteria()
public abstract class DAO<MODEL> implements Serializable {
public abstract Class<MODEL> getEntityClass();
#Autowired
protected SessionFactory sessionFactory;
protected Session getSession(){
return sessionFactory.getCurrentSession();
}
protected Query createQuery(String query){
return getSession().createQuery(query);
}
protected SQLQuery createSQLQuery(String query){
return getSession().createSQLQuery(query);
}
protected Criteria createCriteria(){
return getSession().createCriteria(getEntityClass());
}
#SuppressWarnings("unchecked")
public MODEL findById(Integer id) {
return (MODEL) getSession().get(getEntityClass(), id);
}
public void save(MODEL entity) {
getSession().save(entity);
getSession().flush();
}
public void update(MODEL entity) {
getSession().update(entity);
getSession().flush();
}
public void saveOrUpdate(MODEL entity) {
getSession().saveOrUpdate(entity);
getSession().flush();
}
public void delete(MODEL entity) {
getSession().delete(entity);
getSession().flush();
}
public List<MODEL> list(){
Criteria criteria = createCriteria();
#SuppressWarnings("unchecked")
List<MODEL> list = criteria.list();
return list;
}
}
I think you need first to create an alias like that:
public TourOffice findOfficeNameByLogin(String username) {
Criteria name = createCriteria();
name.createAlias("login", "login");
name.add(Restrictions.eq("login.username", username));
return (TourOffice) name.uniqueResult();
}
I have custom implementation of the Picketlink IDM JPA authentication model. I got it by coping an example from there https://github.com/jboss-developer/jboss-picketlink-quickstarts/tree/master/picketlink-idm-custom-identity-model to package org.picketlink.idm.jpa.model.custom.simple. Then I have implemented this example https://github.com/pedroigor/picketlink-quickstarts/tree/master/picketlink-deltaspike-authorization .
I changed User class and UserTypeEntity in picketlink-idm-custom-identity-model example like this:
#IdentityStereotype(USER)
public class User extends AbstractIdentityType implements Account {
public static final QueryParameter USER_NAME = QUERY_ATTRIBUTE.byName("userName");
#StereotypeProperty(IDENTITY_USER_NAME)
#AttributeProperty
#Unique
private String userName;
#AttributeProperty
private String firstName;
#AttributeProperty
private String lastName;
#AttributeProperty
private String email;
#AttributeProperty
private String middleName;
#AttributeProperty
private String telephone;
#AttributeProperty
private String address;
#AttributeProperty
private int postIndex;
#AttributeProperty
private Date registerDate;
#AttributeProperty
private Date lastVisitDate;
#AttributeProperty
private boolean isOrganizer;
#AttributeProperty
private boolean isAdmin;
#Embedded
private Organizer organizer;
#Embedded
private Customer customer;
// getters and setters
}
class UserTypeEntity
#IdentityManaged(User.class)
#Entity
public class UserTypeEntity extends AbstractIdentityTypeEntity {
#AttributeValue
private String userName;
#OwnerReference
#ManyToOne(fetch = FetchType.LAZY)
private RealmTypeEntity realm;
#AttributeProperty
private String firstName;
#AttributeProperty
private String lastName;
#AttributeProperty
private String email;
#AttributeProperty
#Column(length = 255)
private String middleName;
#AttributeProperty
#Size(max = 12)
#Column(length = 12)
private String telephone;
#AttributeProperty
#Column(length = 5000)
#Size(max = 5000)
private String address;
#AttributeProperty
private int postIndex;
#AttributeProperty
private Date registerDate;
#AttributeProperty
private Date lastVisitDate;
#AttributeProperty
private boolean isOrganizer;
#AttributeProperty
private boolean isAdmin;
#Embedded
private Organizer organizer;
#Embedded
private Customer customer;
// getters and setters
}
Then I implemented Login controller:
#Named
#Stateless
public class LoginController {
#Inject
private Identity identity;
#Inject
private FacesContext facesContext;
public void login() {
AuthenticationResult result = identity.login();
if (AuthenticationResult.FAILED.equals(result)) {
facesContext.addMessage(
null,
new FacesMessage("Invalid user name or password"));
}
}
}
And Registration Controller:
#Named
#RequestScoped
public class RegistrationController {
private IdentityManager identityManager;
#Inject
private PartitionManager partitionManager;
#Inject
private FacesContext facesContext;
#Inject
private User user;
private String password;
private String passwordVerify;
private boolean isOrganizer;
public RegistrationController() {
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getPasswordVerify() {
return passwordVerify;
}
public void setPasswordVerify(String passwordVerify) {
this.passwordVerify = passwordVerify;
}
public boolean getIsOrganizer() {
return isOrganizer;
}
public void setIsOrganizer(boolean isOrganizer) {
this.isOrganizer = isOrganizer;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Transactional
public String register() throws Exception {
if (password.isEmpty()) {
String message = LocaleBean.loadErrorMessage(facesContext, LocaleBean.EX_RESOURCE_BUNDLE_NAME, "password.empty");
facesContext.addMessage("signup:registrationPassword", new FacesMessage(message));
return "returnToSignup";
}
if (!password.equals(passwordVerify)) {
String message = LocaleBean.loadErrorMessage(facesContext, LocaleBean.EX_RESOURCE_BUNDLE_NAME, "password.NotEqual");
facesContext.addMessage("signup:registrationPassword", new FacesMessage(message));
return "returnToSignup";
}
identityManager = partitionManager.createIdentityManager(partitionManager.getPartition(Realm.class,
Resources.REALM_ACME_NAME));
if (isOrganizer) {
user.setOrganizer(true);
user.setOrganizer(new Organizer());
try {
identityManager.add(user);
} catch (IdentityManagementException e) {
String message = LocaleBean.loadErrorMessage(facesContext, LocaleBean.EX_RESOURCE_BUNDLE_NAME, "login.Registered");
facesContext.addMessage(null, new FacesMessage(message));
return "returnToSignup";
}
Password password = new Password(this.password);
identityManager.updateCredential(user, password);
RelationshipManager relationshipManager = partitionManager.createRelationshipManager();
IdentityQuery<Group> query = identityManager.createIdentityQuery(Group.class);
// query all childs of sales unit
query.setParameter(Group.NAME, Resources.ORGANIZERS_GROUP_NAME);
List<Group> groups = query.getResultList();
Group organizersGroup = groups.get(0);
relationshipManager.add(new GroupMembership(user, organizersGroup));
} else {
}
return "signin";
}
}
After that I implemented Authorizer:
#ApplicationScoped
public class SPAuthorizer {
#Secures
#Admins
public boolean doAdminsCheck(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {
return hasGroup(identity, identityManager, relationshipManager, Resources.ADMINS_GROUP_NAME);
}
#Secures
#Organizers
public boolean doOrganizersCheck(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {
return hasGroup(identity, identityManager, relationshipManager, Resources.ORGANIZERS_GROUP_NAME);
}
#Secures
#Customers
public boolean doCustomersCheck(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {
return hasGroup(identity, identityManager, relationshipManager, Resources.CUSTOMERS_GROUP_NAME);
}
private boolean hasGroup(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager,
String groupName) {
IdentityQuery<Group> queryGroup = identityManager.createIdentityQuery(Group.class);
// query all childs of sales unit
queryGroup.setParameter(Group.NAME, groupName);
List<Group> groups = queryGroup.getResultList();
if (groups.size() == 1) {
Group group = groups.get(0);
Account user = identity.getAccount();
if (user == null) {
return false;
}
RelationshipQuery<GroupMembership> query = relationshipManager.createRelationshipQuery(GroupMembership.class);
query.setParameter(GroupMembership.GROUP, group);
query.setParameter(GroupMembership.MEMBER, user);
// user is assigned with two groups
List<GroupMembership> resultList = query.getResultList();
return resultList.size() > 0;
}
return false;
}
}
So I implemented authorization checker to check belonging user to a some group in JSF:
#Named
#Stateless
public class AuthorizationChecker {
#Inject
private Identity identity;
#Inject
private PartitionManager partitionManager;
public boolean hasGroup(String groupName) {
IdentityManager identityManager = partitionManager.createIdentityManager(partitionManager.getPartition(Realm.class,
Resources.REALM_ACME_NAME));
IdentityQuery<Group> queryGroup = identityManager.createIdentityQuery(Group.class);
// query all childs of sales unit
queryGroup.setParameter(Group.NAME, groupName);
List<Group> groups = queryGroup.getResultList();
if (groups.size() == 1) {
Group group = groups.get(0);
Account user = identity.getAccount();
RelationshipManager relationshipManager = partitionManager.createRelationshipManager();
RelationshipQuery<GroupMembership> query = relationshipManager.createRelationshipQuery(GroupMembership.class);
query.setParameter(GroupMembership.GROUP, group);
query.setParameter(GroupMembership.MEMBER, user);
// user is assigned with two groups
List<GroupMembership> resultList = query.getResultList();
return resultList.size() > 0;
}
return false;
}
}
But an instance of Identity in hasGroup of the SPAuthorizer doesn't corresponds to an instance that I have in AuthorizationChecker. I checked it in debugger. And when I do identity.getAccount(); it returns null although user was authenticated. Any idea what to do?
The problem was in missed annotation #Stateless in Controller.
There is workable example https://github.com/lynx-r/picketlink-deltaspike-authorization-and-idm-custom-identity-model.