I’m trying to return an Object as JSON.
Using the /user/id
endpoint, I want to display a User based on his Id.
When calling this controllerMethod I get the following Exception:
InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.sample.scrumboard.models.User_$$_jvsta02_1["handler"])
My contollerClass looks like this:
@RestController @RequestMapping(path="/user") @JsonIgnoreProperties(ignoreUnknown = true) public class UserRestController { private UserRepository repository; @Autowired public UserRestController(UserRepository repository){ this.repository = repository; } @GetMapping(value = "/list") public List<User> getUsers(){ return repository.findAll(); } @GetMapping(value = "/{id}") public @ResponseBody User getUserById(@PathVariable Long id, User user){ user = repository.getOne(id); return user; } }
I checked if al fields have a public getter and tried various options with @JSONIgnoreProperties, but I can’t find it.
Displaying all users as a JSONlist does work JSONlist with /user/list
. So the problem is only there when trying to display one Object, not a list of Objects.
From the repository it does find the User, but it’s unable to serialize that Object and put in on the screen.
The User class itself looks like this:
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "userId", nullable = false, updatable = false) private Long id; @NotNull @Size(min=2, max=20) private String firstName; @NotNull @Size(min=2, max=30) private String lastName; @NotNull @Size(min=2, max=20) private String userName; @NotNull @Size(min=2, max=30) private String passWord; @NotNull @Email private String email; //the mappedBy element must be used to specify the relationship field or property of the entity that is the owner of the relationship @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JsonIgnore private List<UserStory> userStoryList; public User() { } public User(String firstName, String lastName, String userName, String passWord, String email) { this.firstName = firstName; this.lastName = lastName; this.userName = userName; this.passWord = passWord; this.email = email; } @Override public String toString() { return "User{" + "id=" + id + ", firstName='" + firstName + ''' + ", lastName='" + lastName + ''' + ", userName='" + userName + ''' + ", passWord='" + passWord + ''' + ", email='" + email + ''' + '}'; } 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 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 String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public List<UserStory> getUserStoryList() { return userStoryList; } public void setUserStoryList(List<UserStory> userStoryList) { this.userStoryList = userStoryList; } }
How can I display my User returned from /user/id
?
A Solution?
As suggested below, I made it work using a Dto and ModelMapper.
I added
@Bean public ModelMapper modelMapper(){ return new ModelMapper(); }
ControllerMethod
@GetMapping(value = "/{id}") public UserDTO getUserById(@PathVariable Long id, User user, ModelMapper modelMapper){ user = repository.getOne(id); return modelMapper.map(user, UserDTO.class); }
And UserDto
public class UserDTO { private Long id; private String firstName; private String lastName; private String userName; private String passWord; private String email; private List<UserStory> userStoryList; //getters and setters
Now I’m able to show a User on the screen. Still I’m wondering if there is no solution using Jackson and without modelmapper and dto?
Advertisement
Answer
Maybe it’s not a good idea to use your entity (User) to expose the data about user via REST? Can you create UserDTO for your user that will implement Serializable and send this DTO via REST? In this case it should be necessary to convert User object that you’ve retrieved from the db to UserDTO.