Dear Stackoverflow community,
I am new to working with generics and have problems with using genericts correctly. What I want to do is, that a static method can take a generic Object as a parameter. My idea is, to pass Entity Objects as parameter and after return a UserDetailsImpl object. So I want to make this method able to handle different entity classes and dont write boilerplatecode. For this I write an easy Box class for it.
Box.java
public class Box<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
Now I try to use it to pass generic object as parameter in my UserDetailsImpl.java class in the static build method:
package com.yildiz.tradilianz.security.services;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class UserDetailsImpl implements UserDetails {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String email;
@JsonIgnore
private String password;
private Collection<? extends GrantedAuthority> authorities;
public UserDetailsImpl(Long id, String username, String email, String password,
Collection<? extends GrantedAuthority> authorities) {
this.id = id;
this.username = username;
this.email = email;
this.password = password;
this.authorities = authorities;
}
public static UserDetailsImpl build(Box<Object> user) {
List<GrantedAuthority> authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName().name()))
.collect(Collectors.toList());
return new UserDetailsImpl(
user.getId(),
user.getUsername(),
user.getEmail(),
user.getPassword(),
authorities);
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
public Long getId() {
return id;
}
public String getEmail() {
return email;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return 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 boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
UserDetailsImpl user = (UserDetailsImpl) o;
return Objects.equals(id, user.id);
}
}
Now the problem is, that the passed Object doesn't know the whole get() methods I try to access like user.getId(), user.getRoles(), user.getPassword() etc. I want that the generic Box Class contains any Object but how to declare this method I need to access from it?
Otherwise it ends up with "The method getRoles() is undefined for the type Box"
What I wanted to pass as generic Object is my customer entity class, but if it returns null instead i want to test if retailer entity class works and so on in **UserDetailsServiceImpl **:
package com.yildiz.tradilianz.security.services;
import org.apache.commons.validator.routines.EmailValidator;
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 org.springframework.transaction.annotation.Transactional;
import com.yildiz.tradilianz.auth.User;
import com.yildiz.tradilianz.auth.UserRepository;
import com.yildiz.tradilianz.customer.Customer;
import com.yildiz.tradilianz.customer.CustomerDTO;
import com.yildiz.tradilianz.customer.CustomerRepository;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
CustomerRepository customerRepository;
@Autowired
CustomerDTO customerDTO;
@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// Check for username or email passed through username parameter
boolean valid = EmailValidator.getInstance().isValid(username);
if (valid == false) {
/*
* Build with UserDetailsImpl but if user for Customer class is null I want to try another repository and do
* something like this:
* Retailer user = retailerRepository.findByUsername(username); And if it is not null
* it should pass user Object which class is Retailer and so on.
*
*/
Customer user = customerRepository.findByUsername(username);
return UserDetailsImpl.build(user);
} else {
Customer user = customerRepository.findByEmail(username):
return UserDetailsImpl.build(user);
}
}
}
customer entity class
package com.yildiz.tradilianz.customer;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;
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.JoinTable;
import javax.persistence.ManyToMany;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import org.hibernate.annotations.CreationTimestamp;
import com.yildiz.tradilianz.auth.ERole;
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotBlank
@Size(max = 20)
private String username;
@NotBlank
@Size(max = 120)
private String password;
@Column(nullable = false)
private String givenName;
@Column(nullable = false)
private String surname;
private String birthday;
private String streetAddress;
private String city;
private String postalCode;
@Column(updatable = false, nullable = false)
private String email;
private String phoneNumber;
@CreationTimestamp
private Timestamp timestamp;
private Double balance;
private Integer bonuspoints;
private String role;
protected Customer() {
}
public Customer(String username,String password, String givenName, String surname, String birthday, String streetAddress, String city,
String postalCode, String email, String phoneNumber, Double balance, Integer bonuspoints, String role) {
this.username = username;
this.password = password;
this.givenName = givenName;
this.surname = surname;
this.birthday = birthday;
this.streetAddress = streetAddress;
this.city = city;
this.postalCode = postalCode;
this.email = email;
this.phoneNumber = phoneNumber;
this.balance = balance;
this.bonuspoints = bonuspoints;
this.role = role;
}
@Override
public String toString() {
return ("Benutzername: "+username+ "Passwort: "+password+ "Vorname: " + givenName + " Nachname: " + surname +
" Geburtstag: " + birthday + " Stra?e: "+ streetAddress + " Stadt: " + city + " Postleitzahl: " +
postalCode + " E-Mail-Adresse: " + email+ " Telefonnummer: " + phoneNumber + "Kontostand: " + balance +
" Bonuspunkte: " + bonuspoints+" Rolle:"+role);
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public Long getId() {
return id;
}
public String getGivenName() {
return givenName;
}
public String getSurname() {
return surname;
}
public String getBirthday() {
return birthday;
}
public String getStreetAddress() {
return streetAddress;
}
public String getCity() {
return city;
}
public String getPostalCode() {
return postalCode;
}
public String getEmail() {
return email;
}
public String getPhoneNumber() {
return phoneNumber;
}
public Timestamp getTimestamp() {
return timestamp;
}
public Integer getBonuspoints() {
return bonuspoints;
}
public Double getBalance() {
return balance;
}
public String getRole() {
return role;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setGivenName(String givenName) {
this.givenName = givenName;
}
public void setSurname(String surname) {
this.surname = surname;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public void setStreetAddress(String streetAddress) {
this.streetAddress = streetAddress;
}
public void setCity(String city) {
this.city = city;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public void setEmail(String email) {
this.email = email;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public void setBalance(Double balance) {
this.balance = balance;
}
public void setBonuspoints(Integer bonuspoints) {
this.bonuspoints = bonuspoints;
}
public void setRole(String role) {
this.role = role;
}
}
**
Can you pls give me tipps how I do it the right way?
question from:
https://stackoverflow.com/questions/65888941/java-defining-generic-class-as-parameter-for-static-method-to-pass-entity-objec