0

I have the following POJO:

@Entity // This tells Hibernate to make a table out of this class public class User { @Id @GeneratedValue(strategy=GenerationType.AUTO) private Integer id; private String name; private String email; private String username; private String password; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) throws DataFormatException { if(name.equals("")) { throw new DataFormatException("Mpla Mpla"); } this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } 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; } @JsonCreator public User(@JsonProperty("name") String name, @JsonProperty("email") String email,@JsonProperty("username") String username,@JsonProperty("password") String password) throws DataFormatException { setName(name); this.email = email; this.username = username; this.password = password; } } 

And the following controller:

public class MainController { @Autowired // This means to get the bean called userRepository // Which is auto-generated by Spring, we will use it to handle the data private UserRepository userRepository; } @PostMapping(path="/add") // Map ONLY POST Requests public @ResponseBody String addNewUser (@RequestBody @Valid User user1) { // @ResponseBody means the returned String is the response, not a view name userRepository.save(user1); return "Saved"; } @GetMapping(path="/all") public @ResponseBody Iterable<User> getAllUsers() { // This returns a JSON or XML with the users return userRepository.findAll(); } 

The problem is that instead of producing the error DataFormatException it produces:

"exception": "org.springframework.http.converter.HttpMessageNotReadableException", "message": "JSON parse error: Can not construct instance of hello.Users.User, problem: Mpla Mpla; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of hello.Users.User, problem: Mpla Mpla\n at [Source: java.io.PushbackInputStream@7604dc21; line: 6, column: 1]", 

Although as can be seen above the problem is correct but the message is wrong. So what can be done in order to produce the wanted error and not the one produced by Jackson?

9
  • what will happen if you add a constructor without any argument? Commented Dec 21, 2017 at 8:19
  • I need a constructor with arguments in order to validate the input. Commented Dec 21, 2017 at 8:20
  • The exception is thrown by spring's message converter. Which convert json to Object. Meanwhile when converting if any kind of exception is thrown then it will wrapped from converter. so generally it is thrown as org.springframework.http.converter.HttpMessageNotReadableException! Commented Dec 21, 2017 at 8:21
  • @Zico thank you! Although i still need to throw my exception so the person who consumes it knows what is going on.. How can i handle this situation? Commented Dec 21, 2017 at 8:27
  • Exception throwing is not good design in REST design and it is difficult to understand from client side. It is better to return custom JSON response including message and code not exception! Commented Dec 21, 2017 at 9:10

1 Answer 1

0

use below code in your controller.

@RequestMapping(value = "/user/register", method = RequestMethod.POST) public SecurityToken register(@RequestBody @Valid SecurityUser user, BindingResult result) { List<ObjectError> st = result.getAllErrors(); String errorFields = ""; for (ObjectError error : st) { errorFields = errorFields + error.getDefaultMessage(); } if (!errorFields.equals("")) { throw new CustomException(errorFields); } return service.register(user); } 

you can use annotation for fields as :

import org.hibernate.validator.constraints.NotEmpty; public class SecurityUser { @NotEmpty(message = "Email id is mandatory.") private String emailId; 

For Exception handling you can use HandlerMethod in spring controller or ControllerAdvice.

@ControllerAdvice public class SecurityControllerAdvice { @ExceptionHandler(CustomException.class) @ResponseBody public CustomResponse handleSecurityException(CustomException se) { CustomResponse response = new CustomResponse(se.getMessage()); return response; } } 
Sign up to request clarification or add additional context in comments.

7 Comments

I do not think this will work cause HttpMessageNotReadableException can be thrown for any of the variables. How can i know which one them threw it so to return the right message. Example: password cannot be null or username cannot be null ?
you can use binding result for this purpose where you can get the fields error @RequestMapping(value = "/user/register", method = RequestMethod.POST) public SecurityToken register(@RequestBody SecurityUser user, BindingResult result) { //you can use below methods for your check and then can throw custom exception which can be handled by the AdviceController result.hasFieldErrors(); result.hasErrors(); result.getAllErrors(); result.hasErrors(); return service.register(user); }
for custom exception handling you can see below link : stackoverflow.com/questions/47899292/…
Can you implement it as an example in your post? I am not quite sure i understood your mechanic
@J.Doo I have modified my answer as per your requirement, please have a look.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.