Spring Data JPA - findByAlias vs. findUserByAlias - error with both - spring

I am using spring boot 2 with JPA and Spring Security.
I have a handler method that, depending upon a dropdown, will find all links either similar to a specific title or posted by a specific user. I know my database is set up properly.
I am getting a null pointer exception at this line:
Optional<User> user = userRepository.findUserByAlias("searchTerm");
I have tried changing the method to findByAlias(...) with the same result.
This is the code for my UserRepository:
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
Optional<User> findUserByAlias(String alias);
Optional<User> findByAlias(String alias);
}
and this is my handler method wherein the error occurs at this line:
Optional<User> user = userRepository.findUserByAlias("searchTerm");
#GetMapping("/search")
public String showSearchResults(#RequestParam("searchTerm") String searchTerm, #RequestParam("searchBy") String searchBy, Model model) {
System.out.println("INSIDE showSearchResults + searchTerm =" + searchTerm);
List<Link> searchResults;
if(searchBy.equals("user")) {
System.out.println("INSIDE IF EQUALS 'user'");
// get the user by alias
Optional<User> user = userRepository.findUserByAlias("searchTerm");
// if the user is present the find all links by the user id
if (user.isPresent()) {
searchResults = linkRepository.findAllByUser_Id(user.get().getId());
} else {
searchResults = null;
}
}
if(searchBy.equals("title")){
searchResults = linkRepository.findAllByTitleLike("%" + searchTerm + "%");
} else {
searchResults = null;
}
model.addAttribute("searchTerm", new SearchTerm());
model.addAttribute("searchResults", searchResults);
return "search-results";
}
and this is my User class:
#Entity
public class User implements UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long id;
#Column
private String email;
#Column
private String password;
#Column
private boolean enabled;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(
name = "users_roles",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "role_id", referencedColumnName = "id")
)
private Set<Role> roles = new HashSet<>();
#Column
private String firstName;
#Column
private String lastName;
#Column
private String fullName;
#Column
private String alias;
#Transient
private String confirmPassword;
public User(){
}
public User(String email, String password, boolean enabled,
String firstName, String lastName,
String fullName, String alias) {
this.email = email;
this.password = password;
this.enabled = enabled;
this.firstName = firstName;
this.lastName = lastName;
this.fullName = fullName;
this.alias = alias;
}
public void addRole(Role role){
roles.add(role);
}
public void addRoles(Set<Role> roles) {
roles.forEach(this::addRole);
}
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 boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
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 getFullName() {
return firstName + " " + lastName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String getConfirmPassword() {
return confirmPassword;
}
public void setConfirmPassword(String confirmPassword) {
this.confirmPassword = confirmPassword;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
for(Role role : roles){
authorities.add(new SimpleGrantedAuthority(role.getName()));
}
return authorities;
}
#Override
public String getUsername() {
return null;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
}
So I have two questions:
1.) First and most importantly - why am I getting null pointer exception? I'm at a loss as to how to go about debugging this.
2.) What is the difference between findByAlias and findUserByAlias?
Any advice would be much appreciated.
Thank you for your help,
Marc

How is your userRepository injected into your controller? It seems that is the most likely reason for the null pointer.

Related

How should I Map foreign keys in entity classes to model class (pojo) objects

Model Class for User:
#Component
public class UserModel {
private Integer userId;
private Integer roleId;
private String firstName;
private String email;
private String password;
public Integer getUserId() {
return userId;
}
public Integer getRoleId() {
return roleId;
}
public String getFirstName() {
return firstName;
}
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public void setName(String firstName) {
this.firstName = firstName;
}
public void setEmail(String email) {
this.email = email;
}
public void setPassword(String password) {
this.password = password;
}
}
Model Class for Role of the User:
#Component
public class RolesModel {
private Integer roleId;
private String roleName;
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
}
Entity Class for User:
#Entity
#Table(name = "userBloodBank")
public class User {
#Id
#GeneratedValue (strategy = GenerationType.AUTO)
private Integer userId;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="roleId")
private Roles roles;
#NotNull
#Column
#Pattern(regexp="[A-Z][a-zA-Z]*",message="Only enter words starting with captital letter")
private String firstName;
#NotNull
#Column
#Email
#Pattern(regexp = "^[a-zA-Z0-9+_.-]+#[a-zA-Z0-9.-]+$", message = "Enter a proper email ID")
private String email;
#NotNull
#Column
#Pattern(regexp= "^(?=.*[0-9])"
+ "(?=.*[a-z])(?=.*[A-Z])"
+ "(?=.*[##$%^&+=])"
+ "(?=\\S+$).{8,20}$", message="Enter minimum 8 characters and maximum 20 characters")
private String password;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public Roles getRoles() {
return roles;
}
public void setRoles(Roles roles) {
this.roles = roles;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
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;
}
}
Entity Class for Role:
#Entity
#Table(name="Roles")
public class Roles {
#Id
#GeneratedValue (strategy = GenerationType.AUTO)
private Integer roleId;
#NotNull
#Column
#Pattern(regexp="(Recipient|Donor|BloodBankAdmin|Admin)", message = "Choose among Recipient|Donor|BloodBankAdmin|Admin")
private String roleName;
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
}
In the above case Role Id has oneToOne relationship and how will I map this to model object of role and user? Help me with the code to create the function "convertModelToEntity()" and "convertEntityToModel".
You can add below code in your User-entity class to map entity with Model.
public static UserModel convertEntityToModel(User user) {
UserModel userModel = new UserModel();
userModel.setUserId(user.getUserId());
userModel.setRoleId(user.getRoles().getRoleId());
userModel.setFirstName(user.getFirstName());
userModel.setEmail(user.getEmail());
userModel.setPassword(user.getPassword());
return userModel;
}
This will return User-model.
I think you should add the Roles-model(or list of Roles-model) in User Model.

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!

Why all properties of a Model passed from AOP to controller with other arguments are null

AOP
#Around(
"execution(* net.inter.warp.bridge.controller.*.*(.., net.inter.warp.bridge.model.User)) && " +
"args(.., authenticatedUser)"
)
public Object withAuthenticatedUser(ProceedingJoinPoint joinPoint, User authenticatedUser) throws Throwable {
System.out.println(joinPoint + " -> " + authenticatedUser);
User user = null;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null)
user = (User) userService.loadUserByUsername(authentication.getName());
else
throw new UnauthorizedException("err 1");
if (user == null)
throw new UnauthorizedException("err 2");
return joinPoint.proceed(new Object[]{user});
}
Controller (all properties of authenticatedUser are null)
package net.inter.warp.bridge.controller;
#GetMapping("/boxes/{id}")
public ResponseEntity<Box> getBoxById(#PathVariable(value = "id") Long boxId, User authenticatedUser)
throws NoDynamicTableFoundException, ResourceNotFoundException {}
Controller (This works as there is no more parameters except for authenticatedUser)
package net.inter.warp.bridge.controller;
#GetMapping("/boxes/{id}")
public ResponseEntity<Box> getBoxById(User authenticatedUser)
throws NoDynamicTableFoundException, ResourceNotFoundException {}
AOP seems to hate other paramethers... authenticatedUser is not null, every property of authenticatedUser is null.
Model (I am not sure this issue is related to this)
#Entity
#Table(name="users")
#ToString
public class User extends AuthEntity implements UserDetails
{
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
String[] userRoles = this.roles.stream().map((role) -> role.getName()).toArray(String[]::new);
Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(userRoles);
return authorities;
}
#Override
public String getUsername() {
return this.email;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
#Column(nullable=false)
#NotNull(message = "")
private String name;
#Column(nullable=false, unique=true)
#Email
//#NotBlank(message = "")
private String email;
#Column
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
#JsonIgnore
private String password;
#Column(length = 20, columnDefinition ="bigint")
//#NotNull(message = "")
private Long organization_id;
#ManyToOne(optional=false)
#JoinColumn(name = "organization_id",referencedColumnName="id", insertable=false, updatable=false)
//#JsonIgnore
private Organization organization;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
//#Fetch(org.hibernate.annotations.FetchMode.SELECT)
#JoinTable(
name="user_role",
joinColumns={#JoinColumn(name="user_id")},
inverseJoinColumns={#JoinColumn(name="role_id")})
private List<Role> roles;
/*
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
//#Fetch(org.hibernate.annotations.FetchMode.SELECT)
#Fetch(value = FetchMode.SUBSELECT)
#JoinTable(
name="hyperbridge_resource.user_workspace",
joinColumns={#JoinColumn(name="user_id")},
inverseJoinColumns={#JoinColumn(name="workspace_id")})
private List<Workspace> workspaces;
*/
#Column(length = 1, columnDefinition ="char")
private String active;
#Column(name = "reset_token")
#JsonIgnore
private String resetToken;
#Column(name = "reset_token_time")
#DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime resetTokenTime;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
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 Long getOrganization_id() {
return organization_id;
}
public void setOrganization_id(Long organization_id) {
this.organization_id = organization_id;
}
public Organization getOrganization() {
return organization;
}
public void setOrganization(Organization organization) {
this.organization = organization;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
/* public List<Workspace> getWorkspaces() {
return workspaces;
}
public void setWorkspaces(List<Workspace> workspaces) {
this.workspaces = workspaces;
}*/
public String getActive() {
return active;
}
public void setActive(String active) {
this.active = active;
}
public String getResetToken() {
return resetToken;
}
public void setResetToken(String resetToken) {
this.resetToken = resetToken;
}
public LocalDateTime getResetTokenTime() {
return resetTokenTime;
}
public void setResetTokenTime(LocalDateTime resetTokenTime) {
this.resetTokenTime = resetTokenTime;
}
}
Try this, doc:
#Around(
"execution(* net.inter.warp.bridge.controller.*.*(..) && " +
"args(authenticatedUser,..)"

Lazy fetch elements

I'm fetching Company along with productSLA using join fetch query, since the Company has userlist and it doesn't get initialized. Therefore at the time when i send response using responseentity.ok it throws lazy init exception. I don't want user list for that purpose is there any way i can send it to front end without getting lazy init exception some one suggested me to do this using dto.
I am using angular on front end. When i was using jsp i never faced this kind of problem.
#Entity
#Table(name = "USER_TABLE")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer userId;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL,fetch=FetchType.EAGER)
private List<Ticket> raisedTickets;
#NotNull
#Column(unique = true)
#Email(message = "Invalid Email")
private String email;
#NotNull
#Column
#Length(min = 4, max = 12, message = "First name must be between 4 to 12 character long")
private String firstName;
#NotNull
#Column
#Length(min = 4, max = 12, message = "Last name must be between 4 to 12 character long")
private String lastName;
#NotNull
#Column
#Length(min = 8, max = 100, message = "Password must be 4 to 12 character long")
private String password;
#NotNull
#Column
#Length(min = 3, max = 30, message = "Company Name must be between 3 to 12 character long")
private String companyName;
#Column(name = "USER_ROLE")
#Enumerated(EnumType.STRING)
private UserRolesEnum userRole;
#ManyToOne
#JoinColumn(name = "COMPANY_ID", nullable = false)
#NotNull
private Company company;
#OneToMany(mappedBy="user", cascade=CascadeType.ALL)
private List<ProductAssociated> productAssociatedList=new ArrayList<ProductAssociated>();
public User() {
}
public User(String firstName, String lastName, String email, String password, String companyName,
UserRolesEnum role) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
this.companyName = companyName;
this.userRole = role;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer id) {
this.userId = id;
}
public List<Ticket> getRaisedTickets() {
return raisedTickets;
}
public void setRaisedTickets(List<Ticket> raisedTickets) {
this.raisedTickets = raisedTickets;
}
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 getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public UserRolesEnum getUserRole() {
return userRole;
}
public void setUserRole(UserRolesEnum userRole) {
this.userRole = userRole;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public List<ProductAssociated> getProductAssociatedList() {
return productAssociatedList;
}
public void setProductAssociatedList(List<ProductAssociated> productAssociatedList) {
this.productAssociatedList = productAssociatedList;
}
public void addProductAssociated(ProductAssociated productAssociated) {
productAssociatedList.add(productAssociated);
productAssociated.setUser(this);
}
#Entity
#Table(name="PRODUCT_SLA")
public class ProductSLA {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="SLA_ID")
private Integer slaId;
#NotNull
#Column(name="RESPONSE_TIME")
private int responseTime;
#Column(name="RESOLVE_TIME")
private int resolveTime;
#NotNull
#Column(name="PRIORITY")
#Enumerated(EnumType.STRING)
private PriorityEnum priority;
#ManyToOne
#JoinColumn(name="COMPANY_ID", nullable = false)
private Company company;
#ManyToOne
#JoinColumn(name="PRODUCT_ID", nullable = false)
private Product product;
public ProductSLA() {
super();
}
public ProductSLA(Integer slaId, int responseTime, int resolveTime, PriorityEnum priority) {
super();
this.slaId = slaId;
this.responseTime = responseTime;
this.resolveTime = resolveTime;
this.priority = priority;
}
public Integer getSlaId() {
return slaId;
}
public void setSlaId(Integer slaId) {
this.slaId = slaId;
}
public int getResponseTime() {
return responseTime;
}
public void setResponseTime(int responseTime) {
this.responseTime = responseTime;
}
public int getResolveTime() {
return resolveTime;
}
public void setResolveTime(int resolveTime) {
this.resolveTime = resolveTime;
}
public PriorityEnum getPriority() {
return priority;
}
public void setPriority(PriorityEnum priority) {
this.priority = priority;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
}
#Entity
#Table(name = "COMPANY_TABLE")
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "COMPANY_ID")
private Integer companyId;
#NotNull
#Column(name = "COMPANY_NAME", unique = true)
private String companyName;
#NotNull
#Column(name = "ADDRESS_LINE1")
private String addressLine1;
#Column(name = "ADDRESS_LINE2")
private String addressLine2;
#NotNull
#Column(name = "CITY")
private String city;
#NotNull
#Column(name="STATE_NAME")
private String state;
#NotNull
#Column(name = "COUNTRY")
private String country;
#NotNull
#Column(name = "PHONE")
private String phone;
#NotNull
#Column(name = "POSTAL_CODE")
private String postalCode;
#NotNull
#Column(name = "COMPANY_WEBSITE")
private String companyWebsite;
#OneToMany( mappedBy = "company", cascade = CascadeType.ALL)
private List<User> userList = new ArrayList<User>();
#OneToMany(mappedBy = "product", cascade = CascadeType.ALL)
private List<ProductSLA> productSLAList = new ArrayList<ProductSLA>();
#OneToMany(mappedBy = "company", cascade = CascadeType.ALL, orphanRemoval=true)
private List<AccessLevel> accessLevelList=new ArrayList<AccessLevel>();
public Company() {
super();
}
public Company(Integer companyId, String companyName, String addressLine1, String addressLine2, String city,
String state, String country, String phone, String postalCode, String companyWebsite) {
super();
this.companyId = companyId;
this.companyName = companyName;
this.addressLine1 = addressLine1;
this.addressLine2 = addressLine2;
this.city = city;
this.state = state;
this.country = country;
this.phone = phone;
this.postalCode = postalCode;
this.companyWebsite = companyWebsite;
}
public Integer getCompanyId() {
return companyId;
}
public void setCompanyId(Integer companyId) {
this.companyId = companyId;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getAddressLine2() {
return addressLine2;
}
public void setAddressLine2(String addressLine2) {
this.addressLine2 = addressLine2;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getCompanyWebsite() {
return companyWebsite;
}
public void setCompanyWebsite(String companyWebsite) {
this.companyWebsite = companyWebsite;
}
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
public void addUser(User user) {
userList.add(user);
user.setCompany(this);
}
public List<ProductSLA> getProductSLAList() {
return productSLAList;
}
public void setProductSLAList(List<ProductSLA> productSLAList) {
this.productSLAList = productSLAList;
}
public void addProductSLA(ProductSLA productSLA) {
productSLAList.add(productSLA);
productSLA.setCompany(this);
}
public List<AccessLevel> getAccessLevelList() {
return accessLevelList;
}
public void setAccessLevelList(List<AccessLevel> accessLevelList) {
this.accessLevelList = accessLevelList;
}
public void addAccessLevel(AccessLevel accessLevel) {
accessLevelList.add(accessLevel);
accessLevel.setCompany(this);
}
}
edit
i found solutions but i am confused which one to use and how to use, because there are many solutions there.
Avoid Jackson serialization on non fetched lazy objects
Assuming your hibernate session is closed already in the controller (which is a fair assumption to make since we don't want to expose our hibernate sessions outside spring/hibernate layer) you will run into this type of problem if you try to access a collection which was not loaded when it was inside the session.
Alright!
I'm also assuming that you are returning a one or collection of "hibernate managed entities" as opposed to DTOs. What I'm sensing is that when that entity is converted into JSON all the getters are called by underlying framework unless they are marked 'ignore' (or something like that). OR may be your UI is calling userList at which point it's throwing exception since a proxy was returned by hibernate.
Regardless, it's better to return a DTO and populate it however way you like. There are various reasons why returning a DTO (or a collection of DTOs) is preferred over returning an entity.
To resolve this problem, i've used http message converter,
Application Configuration looks like this:
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(jacksonMessageConverter());
super.configureMessageConverters(converters);
}
and
public MappingJackson2HttpMessageConverter jacksonMessageConverter(){
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Hibernate5Module());
messageConverter.setObjectMapper(mapper);
return messageConverter;
}
Dependency Required
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.8.7</version>
</dependency>
There is a dirty solution also for this,if you are willing to modify every getters:
jackson 2 object to json ignore lazy loading

[org.hibernate.mapping.Column(authorities)]

I have follow Hibernate error:
"Could not determine type for: java.util.List, at table: user, for columns: [org.hibernate.mapping.Column(authorities)]"
What can cause a problem?
Also, is it possible use it without model role, and set return getAuthority role "USER" by default?
User model:
#Entity
#Table(name = "user")
public class User implements UserDetails {
private int id;
private String username;
private String password;
private List<Role> roles;
#Id
#GeneratedValue
#Column(name = "id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Basic
#Column(name = "username")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Basic
#Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public String getUsername() {
return this.username;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
#Override
public List<Role> getAuthorities() {
return this.roles;
}
#OneToMany(mappedBy = "user")
public List<Role> getRoles() {
return this.roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
Role model:
#Entity
#Table(name = "role")
public class Role implements GrantedAuthority {
private int id;
private User user;
private String role;
public Role() {
}
public Role(String role){
this.role = role;
}
#Id
#GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#ManyToOne
#JoinColumn(name="user_id")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Override
public String getAuthority() {
return this.role;
}
#Basic
#Column(name="role")
public String getRole(){
return this.role;
}
public void setRole(String role){
this.role = role;
}
}
I found solution myself. I set #Transient annotation to all method, which i don't want that it shouldn't be column in table.
You must replace all annotations for the attributes not to the getter methods.

Resources