Spring tool suite: not-null property references a null or transient value - spring

could you help me with this question?
I built a project on sts4. I am trying to let users register an account on Postman. The primary method I am testing is Put(PutMapping), which I wrote on sts4. I got the project initialized completely, but when I click send from Postman, I got errors like below.
not-null property references a null or transient value: com.appsdeveloperblog.app.ws.io.entity.UserEntity.firstName
The following is part of my project.
UserDetailsRequestModel, (for processing incoming requestbody)
public class UserDetailsRequestModel {
private String firstName;
private String lastName;
private String email;
private String password;
public String getFirstname() {
return firstName;
}
public void setFirstname(String firstname) {
this.firstName = firstname;
}
public String getLastname() {
return lastName;
}
public void setLastname(String lastname) {
this.lastName = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}```
2. UserRest, (Class, which will be returned back to Postman)
```package com.appsdeveloperblog.app.ws.ui.model.response;
public class UserRest {
// public id, not auto increment key from database
private String userId;
private String firstName;
private String lastName;
private String email;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}```
3. UserDTO
```package com.appsdeveloperblog.app.ws.shared.dto;
import java.io.Serializable;
public class UserDTO implements Serializable {
private static final long serialVersionUID = -5607842248454975055L;
// auto increment key from database
private long id;
// public user id, which could be returned back to application
private String userId;
private String firstName;
private String lastName;
private String email;
// clear text password
private String password;
// password which is encrypted, stored,
private String encryptedPassword;
private String emailVerificationToken;
private Boolean emailVerificationStatus = false;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEncryptedPassword() {
return encryptedPassword;
}
public void setEncryptedPassword(String encryptedPassword) {
this.encryptedPassword = encryptedPassword;
}
public String getEmailVerificationToken() {
return emailVerificationToken;
}
public void setEmailVerificationToken(String emailVerificationToken) {
this.emailVerificationToken = emailVerificationToken;
}
public Boolean getEmailVerificationStatus() {
return emailVerificationStatus;
}
public void setEmailVerificationStatus(Boolean emailVerificationStatus) {
this.emailVerificationStatus = emailVerificationStatus;
}
}
UserEntity
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity(name = "users")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 5313493413859894403L;
// this Id is a primary key and auto incremented
// once a new record is inserted into database table
#Id
#GeneratedValue
private long id;
#Column(nullable = false)
private String userId;
#Column(nullable = false, length = 50)
private String firstName;
#Column(nullable = false, length = 50)
private String lastName;
#Column(nullable = false, length = 120)
private String email;
#Column(nullable = false)
private String encryptedPassword;
private String emailVerificationToken;
#Column(nullable = false)
private Boolean emailVerificationStatus = false;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getEncryptedPassword() {
return encryptedPassword;
}
public void setEncryptedPassword(String encryptedPassword) {
this.encryptedPassword = encryptedPassword;
}
public String getEmailVerificationToken() {
return emailVerificationToken;
}
public void setEmailVerificationToken(String emailVerificationToken) {
this.emailVerificationToken = emailVerificationToken;
}
public Boolean getEmailVerificationStatus() {
return emailVerificationStatus;
}
public void setEmailVerificationStatus(Boolean emailVerificationStatus) {
this.emailVerificationStatus = emailVerificationStatus;
}
}
UserServiceImpl
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.appsdeveloperblog.app.ws.UserRepository;
import com.appsdeveloperblog.app.ws.io.entity.UserEntity;
import com.appsdeveloperblog.app.ws.service.UserService;
import com.appsdeveloperblog.app.ws.shared.dto.UserDTO;
#Service
public class UserServiceImpl implements UserService {
#Autowired
UserRepository userRepository;
#Override
public UserDTO createUser(UserDTO user) {
// (0) check whether the email already exist in database
if(userRepository.findByEmail(user.getEmail()) != null) {
throw new IllegalArgumentException("Email already exists.");
}
// 1. create an object UserEntity,
UserEntity userEntity = new UserEntity();
// 2. copy info from userDTO to userEntity
BeanUtils.copyProperties(user, userEntity);
// 3. encryptedPassword can't be got from user
// we have to assign value here for testing
userEntity.setEncryptedPassword("test");
// 4. the second data that is generated during this class is userID
userEntity.setUserId("testUserId");
// 5. now we can save userEntity into database,
// since it contains info from user, have to use userRepository
// after Auto-wired, we can use its methods
// use save method, we can save userEntity into database
UserEntity storedUserDetails = userRepository.save(userEntity);
// 6. we can return it back to RestController
// so we need an UserDTO object
UserDTO returnValue = new UserDTO();
BeanUtils.copyProperties(storedUserDetails, returnValue);
return returnValue;
}
}
UserController
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.appsdeveloperblog.app.ws.service.UserService;
import com.appsdeveloperblog.app.ws.shared.dto.UserDTO;
import com.appsdeveloperblog.app.ws.ui.model.request.UserDetailsRequestModel;
import com.appsdeveloperblog.app.ws.ui.model.response.UserRest;
#RestController // to make this class receive requests from HTTP
#RequestMapping("users") // http://localhost:8080/users + methods
public class UserController {
#Autowired
UserService userService;
#GetMapping
public String getUser() {
return "get user was called";
}
#PostMapping
public UserRest createUser(#RequestBody UserDetailsRequestModel userDetails) {
// 1. instantiate a new object, which will be returned.
UserRest returnValue = new UserRest();
System.out.println(userDetails.getFirstname());
// 2. instantiate a new User Data transfer object,
// which could be shared across different layers
// we will populate this object with info we received from request body
UserDTO userDTO = new UserDTO();
// 3. use class BeanUtils class, which is from spring framework
// to copy properties from source object(userDetails) to our data transfer object
// so, we can populate info from request body into our data transfer object
// so, we have a data transfer object, which is populated info from request body
BeanUtils.copyProperties(userDetails, userDTO);
// 4.
// (1) userDTO, will be created at UI level, then be passed to service layer
// (2) service class will perform some additional business logic
// and generate some additional values, these values will be added to userDTO,
// (3) then userDTO will be used in business logic with a data layer
// to prepare an entity class, which will be stored in database
UserDTO createdUser = userService.createUser(userDTO);
// 5. populate returnValue object
// copy information from createdUser into returnValue
// other sensitive info, like password, should not be included
BeanUtils.copyProperties(createdUser, returnValue);
// 6. return, to mobile applications,or in here to Postman(HTTP client)
return returnValue;
}
#PutMapping
public String updateUser() {
return "update user was called";
}
#DeleteMapping
public String deleteUser() {
return "delete user was called";
}
}
Configuration on Postman
enter image description here
enter image description here
The Error I got
enter image description here
I spent a day on it. Help, please.

Try this:
#PutMapping
public String updateUser(#RequestBody) {
return "update user was called";
}

Related

How to display error message if record exists

I am trying to validate that if the email exists in my database, the error message will come out instead of the White Error Page.
I tried using this link but it is not working for me. Below are my codes.
Codes for Model Class
public class Employee {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "email", unique = true)
#Email
private String email;
#Column(name = "posit")
private String position;
#Column(name = "mobile")
private String phone_num;
public Employee() {}
public Employee(String firstName, String lastName, String email, String position, String phone_num) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.phone_num = phone_num;
this.position = position;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone_num() {
return phone_num;
}
public void setPhone_num(String phone_num) {
this.phone_num = phone_num;
}
}
Codes for EmployeeServiceInterface
public interface EmployeeService {
Employee save(Employee employee);
}
Codes for EmployeeServiceImplementation
#Service
public class EmployeeServiceImpl implements EmployeeService{
#Autowired
private EmployeeRepository employeeRepository;
#Override
public Employee save(Employee employee) {
this.employeeRepository.save(employee);
return employee;
}
public boolean exist(String email){
return employeeRepository.existsByEmail(email);
}
Controller
#Controller
public class EmployeeRegistrationController {
#Autowired
private EmployeeService employeeService;
private EmployeeServiceImpl employeeImpl;
#PostMapping("/saveEmployee")
public String saveEmployee(#ModelAttribute("employee") Employee employee) {
// save employee to database
employeeService.save(employee);
if(employeeService.exist==true){
return "User already exist";
}
return "success";
}
}

Spring Boot; passing user's First Name to welcome.jsp after logging in

A lot of the articles online for Spring Boot deals with Spring Security and it does not help me in the slightest. I am trying to implement a registration and login page and once the user successfully logins, it will take them to a welcome page where it should display their first name, something like "Welcome first name or Welcome username". I have tried passing the first name through a
model.addAttribute("firstName", accountInstance.getFirstName());
but that doesn't seem to work. Any hints to achieve this would be much appreciated
Login Controller
#Controller
public class LoginController {
#Autowired
private AccountRepository accountRepo;
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String showLoginPage(ModelMap model) {
model.addAttribute("login", new AccountEntity());
return "login";
}
#RequestMapping(value = "/login", method = RequestMethod.POST)
public Object submitLoginIn(#ModelAttribute("login") AccountEntity accountForm, Model model) {
AccountEntity accountInstance = accountRepo.findByEmail(accountForm.getEmail().toLowerCase());
// Password Verifier using Argon2
Argon2PasswordEncoder argon2PasswordEncoder = new Argon2PasswordEncoder();
boolean passwordMatch = argon2PasswordEncoder.matches(accountForm.getPassword(), accountInstance.getPassword());
// issue where if i use caps email, throws null pointer exception
if (accountInstance == null || !passwordMatch) {
System.out.println("Invalid Email or Password");
// return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
return "login";
} else if (accountInstance.isEnabled() == false) {
System.out.println("Cant login cause not verified");
return "login";
} else {
System.out.println("account exist");
model.addAttribute("firstName", accountInstance.getFirstName());
return "redirect:welcome"; // Change later
}
}
}
Account Repository
public interface AccountRepository extends CrudRepository<AccountEntity, Long> {
// Optional<AccountEntity> findById(Long Id);
AccountEntity findByUserName(String userName);
AccountEntity findByPassword(String password);
AccountEntity findByEmail(String email);
AccountEntity findByVerificationCode(String verificationCode);
}
Account Entity
#Entity(name = "user")
public class AccountEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String userName;
private String email;
private String password;
// private String gender;
private Integer age;
private Date createdDate;
private boolean enabled;
#Column(updatable = false)
private String verificationCode;
// Getters and Setters
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
/*
* public String getGender() { return gender; }
*
* public void setGender(String gender) { this.gender = gender; }
*/
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getVerificationCode() {
return verificationCode;
}
public void setVerificationCode(String verificationCode) {
this.verificationCode = verificationCode;
}
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
Welcome.jsp
<p> Welcome, ${firstName.firstName} </p>
<!-- <p> Welcome, ${firstName} </p> -->
SO #Bollywood was correct with the redirecting:welcome. Doing so didn't pass the value I wanted to the jsp. Changing it to return "welcome" instead of return "redirect:welcome" worked!

Spring doesn't save List in oneToMany relationship

I've this Address Entity
package com.appdeveloperblog.app.ws.io.entity;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
#Entity(name = "addresses")
public class AddressEntity implements Serializable {
private static final long serialVersionUID = 3652691377296902875L;
#Id
#GeneratedValue
private long id;
#Column(length = 30, nullable = false)
private String addressId;
#Column(length = 15, nullable = false)
private String city;
#Column(length = 15, nullable = false)
private String country;
#Column(length = 100, nullable = false)
private String streetName;
#Column(length = 7, nullable = false)
private String postalCode;
#Column(length = 10, nullable = false)
private String type;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "users_id")
private UserEntity userDetails;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAddressId() {
return addressId;
}
public void setAddressId(String addressId) {
this.addressId = addressId;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public UserEntity getUserDetails() {
return userDetails;
}
public void setUserDetails(UserEntity userDetails) {
this.userDetails = userDetails;
}
}
and this a Users Entity
package com.appdeveloperblog.app.ws.io.entity;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
#Entity(name = "users")
public class UserEntity implements Serializable {
private static final long serialVersionUID = -3772691377276902875L;
#Id
#GeneratedValue
private long id;
#Column(nullable = false)
private String userId;
#Column(nullable = false, length = 50)
private String firstName;
#Column(nullable = false, length = 50)
private String lastName;
#Column(nullable = false, length = 120, unique = true)
private String email;
#Column(nullable = false)
private String encryptedPassword;
private String emailVerificationToken;
#Column(nullable = false)
private Boolean emailVerificationStatus = false;
#OneToMany(mappedBy = "userDetails", cascade = CascadeType.ALL)
private List<AddressEntity> addresses;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getEncryptedPassword() {
return encryptedPassword;
}
public void setEncryptedPassword(String encryptedPassword) {
this.encryptedPassword = encryptedPassword;
}
public String getEmailVerificationToken() {
return emailVerificationToken;
}
public void setEmailVerificationToken(String emailVerificationToken) {
this.emailVerificationToken = emailVerificationToken;
}
public Boolean getEmailVerificationStatus() {
return emailVerificationStatus;
}
public void setEmailVerificationStatus(Boolean emailVerificationStatus) {
this.emailVerificationStatus = emailVerificationStatus;
}
}
and this function which I use it in service layer to save the data into the Mysql Database
#Override
public UserDto createUser(UserDto user) {
if (userRepository.findByEmail(user.getEmail()) != null)
throw new RuntimeException("Record already exists");
for(int i = 0 ; i < user.getAddresses().size() ; i++)
{
AddressDTO address = user.getAddresses().get(i);
address.setUserDetails(user);
address.setAddressId(utils.generateAddressId(30));
user.getAddresses().set(i, address);
}
ModelMapper modelMapper = new ModelMapper();
UserEntity userEntity = modelMapper.map(user, UserEntity.class);
String publicUserId = utils.generateUserId(30);
userEntity.setUserId(publicUserId);
userEntity.setEncryptedPassword(bCryptPasswordEncoder.encode(user.getPassword()));
UserEntity storedUserDetails = userRepository.save(userEntity);
// BeanUtils.copyProperties(storedUserDetails, returnValue);
UserDto returnValue = modelMapper.map(storedUserDetails, UserDto.class);
return returnValue;
}
after I post the data to the API using Postman POST request it save only the data into the users table and all the data in addresses table have been igonred
POST request Example:
{
"firstName" : "Sergey",
"lastName" : "Kargopolov",
"email" : "tno#test.com",
"password" : "123",
"addresses":[
{
"city":"Vancouver",
"country":"Canada",
"streetName":"123 Street name",
"postalCode": "ABCBA",
"type":"billing"
}
]
}
Below classes are the stripped down version of what you are trying to achieve. Please compare with your classes and it should work fine only difference is I have remove additional fields to test it easily. Check code in UserController map method.
UserEntity.java
#Entity
#Table(name = "users")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 4865903039190150223L;
#Id
#GeneratedValue
private long id;
#Column(length = 50, nullable = false)
private String firstName;
#Column(length = 50, nullable = false)
private String lastName;
#OneToMany(mappedBy = "userDetails", cascade = CascadeType.ALL)
private List<AddressEntity> addresses;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<AddressEntity> getAddresses() {
return addresses;
}
#Override
public String toString() {
return "UserEntity [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", addresses="
+ addresses + "]";
}
public void setAddresses(List<AddressEntity> addresses) {
this.addresses = addresses;
}
}
AddressEntity.java
#Entity(name = "addresses")
public class AddressEntity implements Serializable {
private static final long serialVersionUID = 3652691377296902875L;
#Id
#GeneratedValue
private long id;
#Column(length = 15, nullable = false)
private String city;
#Column(length = 15, nullable = false)
private String country;
#JsonIgnore
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "users_id")
private UserEntity userDetails;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public UserEntity getUserDetails() {
return userDetails;
}
public void setUserDetails(UserEntity userDetails) {
this.userDetails = userDetails;
}
#Override
public String toString() {
return "AddressEntity [id=" + id + ", city=" + city + ", country=" + country + "]";
}
}
UserDto.java
public class UserDto implements Serializable {
private static final long serialVersionUID = 6835192601898364280L;
private long id;
private String firstName;
private String lastName;
private List<AddressDTO> addresses;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<AddressDTO> getAddresses() {
return addresses;
}
public void setAddresses(List<AddressDTO> addresses) {
this.addresses = addresses;
}
}
AddressDTO.java
public class AddressDTO {
private long id;
private String city;
private String country;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
UserController.java
#RestController
public class UserController {
#Autowired
UserRepository repository;
#PostMapping("map")
#ResponseBody
public UserEntity map(#RequestBody UserDto userDto) {
ModelMapper modelMapper = new ModelMapper();
UserEntity userEntity = modelMapper.map(userDto, UserEntity.class);
for (AddressEntity address : userEntity.getAddresses()) {
address.setUserDetails(userEntity);
}
repository.save(userEntity);
return userEntity;
}
}
Sample Request:
{
"firstName" : "Sergey",
"lastName" : "Kargopolov",
"addresses":[
{
"city":"Vancouver",
"country":"Canada"
}
]
}
Output:
{
"id": 7,
"firstName": "Sergey",
"lastName": "Kargopolov",
"addresses": [
{
"id": 8,
"city": "Vancouver",
"country": "Canada"
}
]
}

Hibernate connecting table unique on columns problem

I have problem with hibernate because he creates connecting table (I don't know why will be nice if can tell me where and why), and what is worst he using unique on columns and i cant add more then one user with the same role.
Whole project: https://github.com/dextep/sms/tree/master/src/main/java/pl/popiel/sms
Database look
User.class
package pl.popiel.sms.model.user;
import org.hibernate.validator.constraints.UniqueElements;
import javax.persistence.*;
import javax.validation.constraints.Email;
import java.util.Set;
#Entity
#Table(name="sms_users")
#SequenceGenerator(name = "sms_users_seq", sequenceName = "sms_users_seq", allocationSize = 1)
public class User {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sms_users_seq")
private long id;
#Email
private String email;
private String password;
private String firstName;
private String lastName;
#Column(name="mobile_nr")
private String mobileNumber;
#ElementCollection(targetClass=Role.class)
private Set<Role> roles;
public String getFullName() {
return firstName != null ? firstName.concat(" ").concat(lastName) : "";
}
public User() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getMobileNumber() {
return mobileNumber;
}
public void setMobileNumber(String mobileNumber) {
this.mobileNumber = mobileNumber;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Role.class
package pl.popiel.sms.model.user;
import org.hibernate.validator.constraints.UniqueElements;
import org.springframework.stereotype.Indexed;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="sms_roles")
#SequenceGenerator(name = "sms_roles_seq", sequenceName = "sms_roles_seq", allocationSize = 1)
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sms_roles_seq")
private long id;
private String role;
public Role() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
I didn't notice that I miss the #ManyToMany annotation at 'roles' in User class.
Solve:
#ManyToMany
private Set<Role> roles;

Retrieve data from a specific entity in an inheritance relationship in Spring Data Mongo

I have implemented an inheritance relationship using Spring Data MongoDB
I have an abstract entity that contains all the attributes common to all the others.
#Document(collection = PersonEntity.COLLECTION_NAME)
public abstract class PersonEntity {
public final static String COLLECTION_NAME = "persons";
#Id
private ObjectId id;
#Field("first_name")
private String firstName;
#Field("last_name")
private String lastName;
private Integer age;
public PersonEntity(){}
#PersistenceConstructor
public PersonEntity(String firstName, String lastName, Integer age) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public ObjectId getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getFullName(){
return this.firstName + " - " + this.lastName;
}
}
This entity inherits the entities UserSystemEntity and SonEntity. These have specific #Field attributes and do not define the #Document annotation. So all documents are stored in the collection of "PERSONS".
To work with these entities I have created the corresponding repositories. Here I put the repository for the entity SonEntity.
#Repository
public interface SonRepository extends MongoRepository<SonEntity, ObjectId> {
Iterable<SonEntity> findByParentId(ObjectId id);
Long countByParentId(ObjectId id);
Long countByParentIdAndId(ObjectId parentId, ObjectId id);
}
The problem I have, is that when I use this repository to obtain a list of entities "SonEntity" by the following method:
#Override
public Page<SonDTO> findPaginated(Pageable pageable) {
Page<SonEntity> childrenPage = sonRepository.findAll(pageable);
return childrenPage.map(new Converter<SonEntity, SonDTO>(){
#Override
public SonDTO convert(SonEntity sonEntity) {
return sonEntityMapper.sonEntityToSonDTO(sonEntity);
}
});
It returns me documents of all entity types (UserSystemEntity, ParentEntity, SonEntity).
How can I configure this correctly to retrieve only the documents of the SonEntity entity?
Thanks in advance.
"SonEntity" Entity code:
public final class SonEntity extends PersonEntity {
#DBRef
private SchoolEntity school;
#DBRef
private ParentEntity parent;
public SonEntity() {
}
#PersistenceConstructor
public SonEntity(String firstName, String lastName, Integer age, SchoolEntity school, ParentEntity parent) {
super(firstName, lastName, age);
this.school = school;
this.parent = parent;
}
public SchoolEntity getSchool() {
return school;
}
public void setSchool(SchoolEntity school) {
this.school = school;
}
public ParentEntity getParent() {
return parent;
}
public void setParent(ParentEntity parent) {
this.parent = parent;
}
}
"UserSystemEntity" code:
public class UserSystemEntity extends PersonEntity {
#Field("email")
protected String email;
#Field("password")
protected String password;
#Field("is_locked")
protected Boolean locked = Boolean.FALSE;
#Field("last_login_access")
protected Date lastLoginAccess;
#DBRef
protected AuthorityEntity authority;
public UserSystemEntity() {
}
#PersistenceConstructor
public UserSystemEntity(String firstName, String lastName, Integer age, String email, String password, AuthorityEntity authority) {
super(firstName, lastName, age);
this.email = email;
this.password = password;
this.authority = authority;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Boolean isLocked() {
return locked;
}
public void setLocked(Boolean locked) {
this.locked = locked;
}
public Date getLastLoginAccess() {
return lastLoginAccess;
}
public void setLastLoginAccess(Date lastLoginAccess) {
this.lastLoginAccess = lastLoginAccess;
}
public AuthorityEntity getAuthority() {
return authority;
}
public void setAuthority(AuthorityEntity authority) {
this.authority = authority;
}
#Override
public String toString() {
return "UserSystemEntity [email=" + email + ", password=" + password + ", locked=" + locked + ", authority="
+ authority + "]";
}
}
"ParentEntity" code:
public final class ParentEntity extends UserSystemEntity {
public ParentEntity() {
}
#PersistenceConstructor
public ParentEntity(String firstName, String lastName, Integer age, String email, String password,
AuthorityEntity authority) {
super(firstName, lastName, age, email, password, authority);
}
}
Here you can verify that when trying to list all entities of type "SonEntity" appear data of other entities. The user "admin" is stored in the DB as a document of type UserSystemEntity:
The information is stored in MongoDB as follows:

Resources