0

I really don't know how does the security and spring data jpa work, but when I try to receive other users data from database it's acting like an infinite loop and shows only my account info over 9k times and then after few seconds it crashes in web browser with error SyntaxError: JSON.parse: unterminated string literal at line 1 column 39978 of the JSON data, My userRepository is a part of my UserDetailsServiceImplementation which is used in spring security as authentication with SQL database. It's work fine, I can log in on my account, but I can't query and view others' data info.

I've got no idea how to bypass it. Maybe it's a security feature to don't get access to other people credentials.

UserRepository

@Repository
public interface UserRepository extends JpaRepository<User, Long>{

    public User findByUsername(String username);

    @Query("SELECT * FROM user")
    public List<User> findAll();

}

Controller

@RestController
@RequestMapping("/v1/api")
public class HomeApiController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/users")
    public List<User> getUsers() {
        return userRepository.findAll();
    }

}

User

@Entity
@Table
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String username;

    @Column
    @JsonIgnore
    private String password;

    @Column
    private boolean enabled;

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Authority> authorities;

    public User() {
    }  
    then field based constructor + getters and setters

Authority

@Entity
@Table
public class Authority {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private Long id;

    @Column
    private String role;

    @ManyToMany(mappedBy = "authorities")
    private Set<User> user;

    public Authority() {
    }

    field constructor + getters and setters

i expected to query and retrieve all other users in user table in database which is also used to authorize users based on roles in system.

json output shows...

{"id":1,"username":"Admin","enabled":true,"authorities":[{"role":"ROLE_USER","user":[{"id":1,"username":"Admin","enabled":true,"authorities":[{"role":"ROLE_USER","user":[{"id":1,"username":"Admin","enabled":true,"authorities":[{"role":"ROLE_USER","user":[{"id":1,"username":"Admin","enabled":true,"authorities":[{"role":"ROLE_USER","user":

and it's infinite nested. i think there's something wrong with authorities when i clear user_role table then output works great

id 1 username "Admin" enabled true authorities []

what's wrong?

Romil Patel
  • 12,879
  • 7
  • 47
  • 76
  • oh thanks! that exactly solved my problem, i used JsonManagedReference, JsonBackReference annotations on my ManyToMany annotated fields. – NewCoder255 Aug 02 '19 at 09:56

1 Answers1

0

you have to annotate the User set in the Authority class with @JsonIgnore or Annotate the Authorities set in the User class depending on what you need in your API call.

@Entity
@Table
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column
private String username;

@Column
@JsonIgnore
private String password;

@Column
private boolean enabled;

@JsonIgnore
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), 
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Authority> authorities;

public User() {
} 

Or

@Entity
@Table
public class Authority {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Long id;

@Column
private String role;

@JsonIgnore
@ManyToMany(mappedBy = "authorities")
private Set<User> user;

public Authority() {
}

EDIT: Also I do recommend using DTOs to minimize the coupling and avoid such problems

thabetmw
  • 1
  • 2
  • What's the better idea creating separate DTOs or annotating existing class with JsonIgnore? – NewCoder255 Aug 02 '19 at 09:58
  • I do recommend using DTO since it reduces the coupling between your entities and the response but in the ene it depends on what you need to return in the API response, if you need to return all class fields data except one then it's better to only annotate the field with @JsonIgnore but let's assume that you need to return only the username and the role, in this case it's better to use a DTO object. check this link https://www.oodlestechnologies.com/blogs/Advantages-of-using-Data-Transfer-Object-in-Java/ – thabetmw Aug 02 '19 at 10:11