Why GET method returns object in object

Viewed 70

I have 2 entity: User and UserDetails
Only one user detail can belong to one user.

    /* class User */
@Entity
@Table(name = "users")
public class User {

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

    @Column(name = "login")
    private String login;

    @Column(name = "password")
    private String password;

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL,
            fetch = FetchType.LAZY, optional = false)
    private UserDetails userDetails;

    /* getters and setters */
}
    /* class UserDetails */

@Entity
@Table(name = "userdetails")
public class UserDetails {

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

    @Column(name = "name")
    private String name;

    @Column(name = "surname")
    private String surname;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    /* getters and setters */
}

This is class UserDetailsController:

@RestController
@RequestMapping("/userDetails")
public class UserDetailsController {
    @GetMapping("/{id}")
    public UserDetails findById(@PathVariable Long id) {
        return userDetailsRepository.findById(id).orElseThrow(() -> new UserDetailsNotFoundException(id));
    }

    @GetMapping("/")
    public Iterable<UserDetails> findAll() {
        return userDetailsRepository.findAll();
    }

    @PostMapping("/")
    public UserDetails save(@RequestBody UserDetails userDetails) {
        return userDetailsRepository.save(userDetails);
    }

    @PostMapping(value = "/", params = {"name", "surname", "user_id"})
    public UserDetails saveWithParams(@RequestParam("name") String name, @RequestParam("surname") String surname,
                                      @RequestParam("user_id") Long userId) {
        UserDetails userDetails = new UserDetails();
        userDetails.setName(name);
        userDetails.setSurname(surname);
        User user = userRepository.findById(userId).orElseThrow(() -> new UserNotFoundException(userId));
        userDetails.setUser(user);
        return userDetailsRepository.save(userDetails);
    }
}

This is how I'm trying to use my controller in .http file:

GET http://localhost:8080/userDetails/

###

GET http://localhost:8080/userDetails/4

###

POST http://localhost:8080/userDetails/
Content-Type: application/json

{
  "name": "my name",
  "surname": "my surname",
  "user": {
    "user_id": 12
  }
}

###

POST http://localhost:8080/userDetails/
Content-Type: application/x-www-form-urlencoded

user_id=12&name=testName&surname=testSurname

###

1. Why first POST method not works: exception user_id can't be null?
2. Why both GET all method in userDetails returns something like this?:

enter image description here

2 Answers

Why first POST method not works: exception user_id can't be null

Because you are receiving data as Request param not request body. So all data is null. So thats why it gives you error. If you want to send as request body then create a DTO class with those field and map using @RequestBody

public UserDetails saveWithParams(@RequestBody UserDetailsDTO reqestBody) {
    ...
}

Why both GET all method in userDetails returns something like this?

You are sending entity where the relations are defined that way so it will fetch data recursively. You can solve it using @JsonIgnore on user of UserDetails class so that user will not fetched again.

@JsonIgnore
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
  1. You are using a @RequestParam annotation. In this case your POST request url should be like:

POST http://localhost:8080/userDetails?name=myname&surname=mysurname&user_id=5

If you want pass it in body wrap your three variables in some class and annotate that with @RequestBody Yourclass yourClass instead of @RequestParam

  1. It is because your User entity is connected with UserDetails. To resolve that you can either use @JsonIgnore or create special DTO object that will be returned from your service layer with needed properties (aggregated from User and UserDetails)
Related