SpringBoot #OneToMany Postman Request not working - json

1.User Class with OneToMany Annotation in relation to Roles class that can be many
2.Roles Class with #ManyToOne and #JoinColumn Annotation
3.Controller class with the endpoint
4.Postman request with Json Object throws an Exception, JSON parse error: Cannot deserialize instance of com.cvt.programmingTask.model.User out of START_ARRAY token
Class User()
package com.cvt.programmingTask.model;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name = "user")
public class User {
#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_id", unique=true)
private String emailId;
#OneToMany(mappedBy = "user")
private Set<Roles> roles;
public User() {
}
public User(String firstName, String lastName, String emailId, Set<Roles> roles) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
this.roles = roles;
}
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 getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public Set<Roles> getRoles() {
return roles;
}
public void setRoles(Set<Roles> roles) {
this.roles = roles;
}
}
Class Roles :
package com.cvt.programmingTask.model;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name="roles")
public class Roles {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "name")
private String name;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="user_id", nullable=false)
private User user;
public Roles() {
}
public Roles(Long id, String name, User user) {
super();
this.id = id;
this.name = name;
this.user = user;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
User Controller Java File
package com.cvt.programmingTask.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.cvt.programmingTask.exception.ResourceNotFoundException;
import com.cvt.programmingTask.model.User;
import com.cvt.programmingTask.repository.UserRepository;
/**
* #author edibi
*
*/
//#CrossOrigin(origins = "http://localhost:4200")
#RestController
#RequestMapping("/api/v1")
public class UserController {
#Autowired
private UserRepository userRepository;
//get all users
#GetMapping("/users")
public List<User> getAllUsers(){
return userRepository.findAll();
}
//create user rest api
#PostMapping("/users")
public User createUser(#RequestBody User user) {
return userRepository.save(user);
}
//get user
#GetMapping ("/users/{id}")
public ResponseEntity<User> getUserById(#PathVariable Long id) {
User user = userRepository.findById(id)
.orElseThrow(()->new ResourceNotFoundException("User does not exist with id : " +id));
return ResponseEntity.ok(user);
}
//update user
#PutMapping("/users/{id}")
public ResponseEntity<User> updateUser(#PathVariable Long id, #RequestBody User userDetails){
User user = userRepository.findById(id)
.orElseThrow(()->new ResourceNotFoundException("User does not exist with id : " +id));
user.setFirstName(userDetails.getFirstName());
user.setLastName(userDetails.getLastName());
user.setEmailId(userDetails.getEmailId());
user.setRoles(userDetails.getRoles());
User updatedUser = userRepository.save(user);
return ResponseEntity.ok(updatedUser);
}
//delete User rest api
#DeleteMapping("/users/{id}")
public ResponseEntity< Map<String, Boolean> >deleteUser(#PathVariable Long id){
User user = userRepository.findById(id)
.orElseThrow(()->new ResourceNotFoundException("User does not exist with id : " +id));
userRepository.delete(user);
Map<String, Boolean> response = new HashMap<>();
response.put("deleted", Boolean.TRUE);
return ResponseEntity.ok(response);
}
}
Can you help me out really don't know what'S wrong. Thanks

Related

Why do i have User registration error with MySql

I'm new to MySql and i have an error this happens when I try to register a new user
java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'id, roles) values (25, 'USER')' at line 1
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) ~[mysql-connector-java-8.0.21.jar:8.0.21]
RegistrationController.Java
`
package com.example.fitter.controller;
import com.example.fitter.domain.Role;
import com.example.fitter.domain.User;
import com.example.fitter.repos.UserRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.Collections;
import java.util.Map;
#Controller
public class RegistrationController {
#Autowired
private UserRepo userRepo;
#GetMapping("/registration")
public String registration() {
return "registration";
}
#PostMapping("/registration")
public String addUser(User user, Map<String, Object> model) {
User userFromDb = userRepo.findByUsername(user.getUsername());
if (userFromDb != null) {
model.put("message", "User exists!");
return "registration";
}
user.setActive(true);
user.setRoles(Collections.singleton(Role.USER));
userRepo.save(user);
return "redirect:/login";
}
}
`
WebSecurityConfig.Java
``` package com.example.fitter.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import javax.sql.DataSource;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.passwordEncoder(NoOpPasswordEncoder.getInstance())
.usersByUsernameQuery("select username, password, active from usr where username=?")
.authoritiesByUsernameQuery("select u.username, ur.roles from usr u inner join user_role ur on u.id = ur.user_id where u.username=?");
}
}
User.Java
package com.example.fitter.domain;
import javax.persistence.*;
import java.util.Set;
#Entity
#Table(name = "usr")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String username;
private String password;
private boolean active;
#ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER)
#CollectionTable(name = "userRole", joinColumns = #JoinColumn(name = "user id"))
#Enumerated(EnumType.STRING)
private Set<Role> roles;
public User(){}
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 getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
'
This one seems wrong:
#JoinColumn(name = "user id")
I suppose it is user_id in the table, so it should be:
#JoinColumn(name = "user_id")
That was so stupid Error in User.Java instead of #CollectionTable(name = "userRole", joinColumns = #JoinColumn(name = "user id"))
#CollectionTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id"))

error while running the spring boot program

Description
I have created a database with three tables
users (user_id, name, password),
the Role table with columns
role_id, role and the third column Role_user with user_id,role_id.
error while running the program,
I have stored the username, passwords with the help of hashing with SHA2, for security purposes.
While running the program it is throwing the error as mentioned above. How should I resolve this error?
package com.techprimers.security.securitydbexample.model;
import javax.persistence.*;
import java.util.Set;
#Entity
#Table(name = "user")
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private int id;
#Column(name = "password")
private String password;
#Column(name = "name")
private String name;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id"), inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
public Users() {
}
public Users(Users users) {
this.roles = users.getRoles();
this.name = users.getName();
this.id = users.getId();
this.password = users.getPassword();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Role
package com.MonitoringDashboardNew.Model;
import javax.persistence.*;
#Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "role_id")
private int roleId;
#Column(name = "role")
private String role;
public Role() {
}
public int getRoleId() {
return roleId;
}
public void setRoleId(int roleId) {
this.roleId = roleId;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
CustomUserDetails
package com.MonitoringDashboardNew.Model;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.stream.Collectors;
public class CustomUserDetails extends Users implements UserDetails {
public CustomUserDetails(final Users users) {
super(users);
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return getRoles()
.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRole()))
.collect(Collectors.toList());
}
#Override
public String getPassword() {
return super.getPassword();
}
#Override
public String getUsername() {
return super.getName();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
Repository
package com.MonitoringDashboardNew.Repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.MonitoringDashboardNew.Model.Users;
#Repository
public interface UsersRepository extends JpaRepository<Users, Integer> {
Optional<Users> findByName(String username);
}
Service
package com.MonitoringDashboardNew.Services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.MonitoringDashboardNew.Model.CustomUserDetails;
import com.MonitoringDashboardNew.Model.Users;
import com.MonitoringDashboardNew.Repository.UsersRepository;
import java.util.Optional;
#Service
public abstract class CustomUserDetailsService implements UserDetailsService {
#Autowired
private UsersRepository usersRepository;
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
Optional<Users> optionalUsers = usersRepository.findByName(name);
// Optional<Users> optionalUsers = usersRepository.findById(id);
optionalUsers
.orElseThrow(() -> new UsernameNotFoundException("Username not found"));
return optionalUsers
.map(CustomUserDetails::new).get();
}
}
SecurityConfuguration
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import com.MonitoringDashboardNew.Services.CustomUserDetailsService;
#EnableGlobalMethodSecurity(prePostEnabled = true)
#EnableWebSecurity
#EnableJpaRepositories()
#Configuration
#Component
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private CustomUserDetailsService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(getPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("**/monitoring/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin().permitAll();
}
private PasswordEncoder getPasswordEncoder() {
return new PasswordEncoder() {
#Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
#Override
public boolean matches(CharSequence charSequence, String s) {
return true;
}
};
}
}
Error
Description:
Field userDetailsService in com.example.demo.SecurityConfiguration required a bean of type 'com.MonitoringDashboardNew.Services.CustomUserDetailsService' that could not be found.
The injection point has the following annotations:
#org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.MonitoringDashboardNew.Services.CustomUserDetailsService' in your configuration.
Your CustomUserDetailsService is abstract and cannot be created.
#Service
public abstract class CustomUserDetailsService implements UserDetailsService {
Make it non abstract:
#Service
public class CustomUserDetailsService implements UserDetailsService {

Spring Boot: Found shared references to a collection error

I'm trying to build a small Spring Boot CRUD app with some basic e-commerce functionality (i.e. add to cart, etc.). My Basic entities are customer, cheese, roles and orders.
Customer's have a many-to-many relationship with Cheese (the fictional object I'm selling) objects. In addition, Orders have a many-to-many relationship with Cheese objects. When my customer checks out, I am intending to transfer the cart contents (i.e. the list of Cheeses) to the Order object, along with customer id, total price, etc. I want the "Orders" to be able to be logged by myself, as well as to provide an order history for the customer. The instantiating of the order object with customer.getCheeses() is what is giving me the shared collection error.
I can somewhat get around this by creating new Cheese items, however, that messes up my database, creating duplicates upon every new order.
The processing of orders is done in the completeOrder() function in UserController. All of the html/thymeleaf seems to be working - I can post it if it will help.
Cheese
package com.example.demo.models;
import javax.persistence.*;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
#Entity
public class Cheese {
#NotNull
#Size(min=2, max=20)
private String name;
#NotNull
#Size(min=2, max=20)
private String description;
#NotNull
#DecimalMax("10000.0") #DecimalMin("0.0")
private BigDecimal price;
#Id
#GeneratedValue
private int id;
#ManyToMany(mappedBy = "cheeses")
private List<Customer> customers = new ArrayList<>();
#ManyToMany(mappedBy = "cheeses")
private List<Orders> orders = new ArrayList<>();
public Cheese() {}
public Cheese(String name, String description, BigDecimal price) {
this.name = name;
this.description = description;
this.price = price;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Orders> getOrders() {
return orders;
}
public void setOrders(List<Orders> orders) {
this.orders = orders;
}
}
Customer
package com.example.demo.models;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
#Entity
public class Customer implements Serializable {
#NotNull
#Size(min = 2, max = 25)
private String name;
#GeneratedValue
#Id
private int accountNumber;
private BigDecimal accountFunds;
#NotNull
#Size(min = 2)
private String password;
#NotNull
#Size(min = 2, max = 25)
#Email
private String email;
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name="user_roles",
joinColumns={#JoinColumn(name="CUSTOMER_EMAIL", referencedColumnName = "email")},
inverseJoinColumns={#JoinColumn(name="ROLE_ID", referencedColumnName="id")})
private List<Role> roles;
//#ElementCollection
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name="cheese_customers",
joinColumns={#JoinColumn(name="CUSTOMER_ID", referencedColumnName = "accountNumber")},
inverseJoinColumns={#JoinColumn(name="PRODUCT_ID", referencedColumnName="id")})
private List<Cheese> cheeses = new ArrayList<>();
public Customer(String name, String password, String email) {
this.name = name;
this.password = password;
this.email = email;
this.accountFunds = new BigDecimal(225.00);
}
public Customer() {}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAccountNumber() {
return accountNumber;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public BigDecimal getAccountFunds() {
return accountFunds;
}
public void setAccountFunds(BigDecimal accountFunds) {
this.accountFunds = accountFunds;
}
public List<Cheese> getCheeses() {
return cheeses;
}
public void setCheeses(List<Cheese> cheeses) {
this.cheeses = cheeses;
}
}
Orders
package com.example.demo.models;
import javax.persistence.*;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
#Entity
public class Orders {
#GeneratedValue
#Id
private int orderId;
#ManyToMany(cascade= CascadeType.ALL)
#JoinTable(name="customer_orders",
joinColumns={#JoinColumn(name="ORDER_ID", referencedColumnName = "orderId")},
inverseJoinColumns={#JoinColumn(name="PRODUCT_ID", referencedColumnName="id")})
private List<Cheese> cheeses = new ArrayList<>();
private int customerId;
private BigDecimal totalPrice;
private Date date;
public Orders() {}
public Orders(List<Cheese> cheeses, int customerId, BigDecimal totalPrice) {
this.cheeses = cheeses;
this.customerId = customerId;
this.totalPrice = totalPrice;
this.date = new Date();
}
private String getFormattedDate() {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
return format.format(this.date);
}
public int getOrderId() {
return orderId;
}
public List<Cheese> getCheeses() {
return cheeses;
}
public void setCheeses(List<Cheese> cheeses) {
this.cheeses = cheeses;
}
public int getCustomerId() {
return customerId;
}
public void setCustomerId(int customerId) {
this.customerId = customerId;
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
UserController
package com.example.demo.controllers;
import com.example.demo.models.Customer;
import com.example.demo.models.Orders;
import com.example.demo.models.data.CheeseDao;
import com.example.demo.models.data.CustomerDao;
import com.example.demo.models.data.OrdersDAO;
import com.example.demo.models.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.List;
#Controller
#RequestMapping("cheese")
public class UserController {
#Autowired
private CustomerDao customerDao;
#Autowired
UserService userService;
#Autowired
CheeseDao cheeseDao;
#Autowired
OrdersDAO ordersDAO;
#RequestMapping(value = "login")
public String loginPage(Model model) {
model.addAttribute("title", "Login Page");
model.addAttribute("customer", new Customer());
return "cheese/login";
}
#RequestMapping(value = "account")
public String accountInfo(Model model) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Customer customer = customerDao.findByEmail(authentication.getName());
model.addAttribute("name", customer.getName());
model.addAttribute("funds", customer.getAccountFunds());
model.addAttribute("customer", customer);
model.addAttribute("cheeses", customer.getCheeses());
model.addAttribute("total", userService.getCartTotal(customer));
return "cheese/account";
}
#PostMapping(value = "account")
public String removeItem(#RequestParam int cheeseId) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Customer customer = customerDao.findByEmail(authentication.getName());
if (customer.getCheeses().contains(cheeseDao.getCheeseById(cheeseId))) {
customer.getCheeses().remove(cheeseDao.getCheeseById(cheeseId));
}
customerDao.save(customer);
return "redirect:/cheese/account";
}
#RequestMapping(value = "checkout")
public String orderCheckout(Model model) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Customer customer = customerDao.findByEmail(authentication.getName());
model.addAttribute("cheeses", customer.getCheeses());
model.addAttribute("total", userService.getCartTotal(customer));
return "cheese/checkout";
}
#GetMapping("signup")
public String displaySignUpForm(Model model) {
model.addAttribute("title", "Sign Up");
model.addAttribute("customer", new Customer());
return "cheese/signup";
}
#PostMapping(value = "signup")
public String processSignUp(Model model, #ModelAttribute Customer customer, Errors errors) {
if (errors.hasErrors()) {
return "cheese/signup";
}
userService.createUser(customer);
return "cheese/success";
}
#GetMapping("ordersuccess")
public String showForm() {
return "cheese/ordersuccess";
}
#PostMapping("checkout")
public String completeOrder() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Customer customer = customerDao.findByEmail(authentication.getName());
double accountFunds = customer.getAccountFunds().doubleValue();
double cartTotal = userService.getCartTotal(customer).doubleValue();
if (accountFunds >= cartTotal) {
accountFunds = accountFunds - cartTotal;
customer.setAccountFunds(new BigDecimal(accountFunds));
Orders order = new Orders(customer.getCheeses(), customer.getAccountNumber(), new BigDecimal(cartTotal));
customer.getCheeses().clear();
customerDao.save(customer);
ordersDAO.save(order);
return "redirect:/cheese/ordersuccess";
}
return "redirect:cheese/checkout";
}
#GetMapping("orders")
public String viewOrderHistory(Model model) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Customer customer = customerDao.findByEmail(authentication.getName());
List<Orders> orders = ordersDAO.findOrdersByCustomerId(customer.getAccountNumber());
model.addAttribute("orders", orders);
return "cheese/orders";
}
}
So what you are trying to do is fetch and fill the cheese collection when you get a customer? Normally, in order to do that, you must set lazy loading to false, otherwise the session closes before you can fetch the collection.
To be able to load the customer with it's cheese collection, you must got to your Hibernate query and use a "join fetch" command. Something like this.
sessionFactory.getCurrentSession().createQuery("from Customer C join fetch C.cheeses").list();
This will force the query to fetch the cheese collection before the session closes. Also, one more thing, normally I would use a Set to avoid duplicates in the collection. I hope this helps.

Spring Security: Getting MySQL duplicate entry error when registering more than one user

I am trying to register and log-in users with Spring Security, as well as give them roles, which is required by spring security. I am currently receiving the following error when registering more than one user.
The error is:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'USER' for key 'UK_8sewwnpamngi6b1dwaa88askk'
The role_name can be the same for many users, so I made an 'id' for roles that is the primary key, and is autogenerated. My "USER_ROLES" table in my MySQL database only has one entry, which is the first email, and role_name, "USER". The Customer table has all the entries, regardless of errors. I'll keep working on this.
Thanks for looking.
Customer.java
package com.example.demo.models;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
#Entity
public class Customer implements Serializable {
#NotNull
#Size(min=2, max=25)
private String name;
#GeneratedValue
#Id
private int accountNumber;
private BigDecimal accountFunds;
#NotNull
#Size(min=2)
private String password;
#NotNull
#Size(min=2, max=25)
#Email
private String email;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "USER_ROLES", joinColumns = {
#JoinColumn(name = "CUSTOMER_EMAIL", referencedColumnName = "email")
}, inverseJoinColumns = {
#JoinColumn(name = "ROLE_NAME", referencedColumnName = "name")
})
private List<Role> roles;
public Customer(String name, String password, String email) {
this.name = name;
this.password = password;
this.email = email;
}
public Customer() {}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAccountNumber() {
return accountNumber;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public BigDecimal getAccountFunds() {
return accountFunds;
}
public void setAccountFunds(BigDecimal accountFunds) {
this.accountFunds = accountFunds;
}
}
Role.java
package com.example.demo.models;
import javax.persistence.*;
import java.util.List;
#Entity
public class Role {
#Id
#GeneratedValue
private int id;
private String name;
#ManyToMany(mappedBy = "roles")
private List<Customer> customers;
public Role(String name, List<Customer> customers) {
this.name = name;
this.customers = customers;
}
public Role(String name) {
this.name = name;
}
public Role() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Customer> getCustomers() {
return customers;
}
public void setCustomers(List<Customer> customers) {
this.customers = customers;
}
}
UserService.java
package com.example.demo.models.services;
import com.example.demo.models.Customer;
import com.example.demo.models.Role;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
public void createUser(Customer customer) {
Role userRole = new Role("USER");
List<Role> roles = new ArrayList<>();
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
customer.setPassword(encoder.encode(customer.getPassword()));
roles.add(userRole);
customer.setRoles(roles);
userRepository.save(customer);
}
public void createAdmin(Customer customer) {
Role userRole = new Role("ADMIN");
List<Role> roles = new ArrayList<>();
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
customer.setPassword(encoder.encode(customer.getPassword()));
roles.add(userRole);
customer.setRoles(roles);
userRepository.save(customer);
}
}
UserRepository
package com.example.demo.models.services;
import com.example.demo.models.Customer;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<Customer, String> {
}
SecurityConfig
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import javax.sql.DataSource;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
DataSource dataSource;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select email as principal, password as credentials, true from customer where email=?")
.authoritiesByUsernameQuery("select customer_email as principal, role_name as role from user_roles where customer_email=?")
.passwordEncoder(passwordEncoder()).rolePrefix("ROLE_");
}
#Override
protected void configure(HttpSecurity http) throws Exception{
http
.csrf().disable()
.authorizeRequests()
.antMatchers(
"/**/webjars/**",
"/cheese/signup",
"/cheese/login",
"/cheese/success").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/cheese/login")
.defaultSuccessUrl("/cheese/account")
.permitAll();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Ok, so I got it to work. SecurityConfig is the SAME, except you need to change 'role_name' to 'role_id'.
Just to give a little bit of explanation, I did the following:
Add id to roles, make it Primary Key/autogenerated.
For the Customer many-to-many, I joined the customer email to (inverse join) the role 'id'
For the Role, I did a one-to-many mapping. joining the role 'id' with (inverse join) customer email.
This way I ended up with a 'user_roles' table where the role_id was mapped to the customer email, and a 'role' table where the role_id was mapped to the role (i.e. "USER", "ADMIN", etc.), allowing for duplicates. I am still a beginner, so maybe even this is not the best way to do it, but it worked for me.
The code...
Customer.java
package com.example.demo.models;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
#Entity
public class Customer implements Serializable {
#NotNull
#Size(min = 2, max = 25)
private String name;
#GeneratedValue
#Id
private int accountNumber;
private BigDecimal accountFunds;
#NotNull
#Size(min = 2)
private String password;
#NotNull
#Size(min = 2, max = 25)
#Email
private String email;
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name="user_roles",
joinColumns={#JoinColumn(name="CUSTOMER_EMAIL", referencedColumnName = "email")},
inverseJoinColumns={#JoinColumn(name="ROLE_ID", referencedColumnName="id")})
private List<Role> roles;
public Customer(String name, String password, String email) {
this.name = name;
this.password = password;
this.email = email;
}
public Customer() {}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAccountNumber() {
return accountNumber;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public BigDecimal getAccountFunds() {
return accountFunds;
}
public void setAccountFunds(BigDecimal accountFunds) {
this.accountFunds = accountFunds;
}
}
Role.java
package com.example.demo.models;
import javax.persistence.*;
import java.util.List;
#Entity
public class Role {
#Id
#GeneratedValue
private int id;
private String name;
#OneToMany(cascade=CascadeType.ALL)
#JoinTable(name="user_roles",
joinColumns={#JoinColumn(name="ROLE_ID", referencedColumnName="id")},
inverseJoinColumns={#JoinColumn(name = "CUSTOMER_EMAIL", referencedColumnName = "email")
})
private List<Customer> customers;
public Role(String name, List<Customer> customers) {
this.name = name;
this.customers = customers;
}
public Role(String name) {
this.name = name;
}
public Role() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Customer> getCustomers() {
return customers;
}
public void setCustomers(List<Customer> customers) {
this.customers = customers;
}
}

Hibernate one to many input using json with POSTMAN

The problem is one to many hibernate mapping is not working in this json format. I think it's a logical error, syntax error is not shown.
My Controller is:
#RequestMapping(value = "/save", method = RequestMethod.POST, produces =MediaType.APPLICATION_JSON_VALUE,headers="Accept=application/json,application/xml")
public #ResponseBody JsonRecord setCurrentDataList(#RequestBody Employee emp) {
try {
int id=employeeServices.save(emp);
} catch (Exception e) {
return new JsonRecord(false,e.getMessage());
}
return new JsonRecord(true,"Successful",emp);
}
Employee Entity Class is:
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.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.IndexColumn;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.JsonProperty;
#Entity
#Table(name="Employee")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
#JsonAutoDetect(getterVisibility=JsonAutoDetect.Visibility.NONE)
public class Employee implements Serializable{
private static final long serialVersionUID = -723583058586873479L;
#Id
#GeneratedValue
#Column(name ="empId")
#JsonProperty("empId")
private Integer empId;
#JsonProperty("empName")
private String empName;
#JsonProperty("empAddress")
private String empAddress;
#JsonProperty("salary")
private double salary;
#JsonProperty("empAge")
private Integer empAge;
#OneToMany(mappedBy="employee",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
#Fetch(FetchMode.SELECT)
private List<Education> education;
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getEmpAddress() {
return empAddress;
}
public void setEmpAddress(String empAddress) {
this.empAddress = empAddress;
}
public double getSalary() {
return salary;
}
public void setSalary(double d) {
this.salary = d;
}
public Integer getEmpAge() {
return empAge;
}
public void setEmpAge(Integer empAge) {
this.empAge = empAge;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "employee")
#JsonManagedReference
public List<Education> getEducation() {
return education;
}
public void setEducation(List<Education> education) {
this.education = education;
}
}
Education Entity is:
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;
import javax.persistence.Table;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonProperty;
#Entity
#Table(name="Education")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
#JsonAutoDetect(getterVisibility=JsonAutoDetect.Visibility.NONE)
public class Education{
#Id
#GeneratedValue
#Column(name ="eduID")
#JsonProperty("eduID")
private int eduID;
#JsonProperty("qualification")
private String qualification;
#JsonProperty("stream")
private String stream;
#ManyToOne
#JoinColumn(name="empid")
private Employee employee;
public int getEduID() {
return eduID;
}
public void setEduID(int eduID) {
this.eduID = eduID;
}
public String getQualification() {
return qualification;
}
public void setQualification(String qualification) {
this.qualification = qualification;
}
public String getStream() {
return stream;
}
public void setStream(String stream) {
this.stream = stream;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "empId", nullable = false)
#JsonBackReference
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}
JSON input:
{
"empName": "myname",
"empAddress": "my address",
"salary": 1000,
"empAge": 24,
"education":[{
"qualification":"mca",
"stream":"mca"
}]
}
One to many mapping is not working with this json format.How to implement this mapping in json format? Please give me your valuable suggestions.
use
#OneToMany(cascade={CascadeType.ALL})
#Fetch(FetchMode.JOIN)
#JoinColumn(name="empId", referencedColumnName="empId")
private Set<Education> education;
instead of,
#OneToMany(mappedBy="employee",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
#Fetch(FetchMode.SELECT)
private List<Education> education;