I have a Spring Boot 2.0.2 web service that I'm building, I have a number of fields within an entity that I don't want to be empty. When trying to persist an entity with invalid fields, how do I grab the message from that particular field?
For example, I have an entity;
@Entity
@Table(name="users")
public class User {
@Column(name="password", columnDefinition = "VARCHAR(250)", nullable = false, length = 250)
@NotNull(message = "Missing password")
private String password;
}
I have a service class, which attempts to create a new user. When it tries to create a user where the password is missing, an exception is thrown;
2018-07-20 17:03:33.195 ERROR 78017 --- [nio-8080-exec-1] o.h.i.ExceptionMapperStandardImpl : HHH000346: Error during managed flush [Validation failed for classes [com.nomosso.restapi.models.User] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='Missing password', propertyPath=password, rootBeanClass=class com.nomosso.restapi.models.User, messageTemplate='Missing password'}
]]
2018-07-20 17:03:33.215 ERROR 78017 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction] with root cause
javax.validation.ConstraintViolationException: Validation failed for classes [com.nomosso.restapi.models.User] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='Missing password', propertyPath=password, rootBeanClass=class com.nomosso.restapi.models.User, messageTemplate='Missing password'}
]
I would like to grab the value of messageTemplate, so that I can handle it and return it in an API response, but I don't seem to be able to catch the Exception and grab the text.
Currently the API response looks like this;
{
"timestamp": 1532102613231,
"status": 500,
"error": "Internal Server Error",
"message": "Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction",
"path": "/user"
}
This isn't very helpful at all to the user of the service. I would like the response to be this;
{
"timestamp": 1532102613231,
"status": 400,
"error": "Bad request",
"message": "Missing password",
"path": "/user"
}
I am able to generate my own error responses, but in order to do so I need to get the message from the invalid entity.
UPDATE: Here is the service that tries to persist the entity;
@Service
public class UserService implements UserDetailsService {
private UserRepository userRepository;
private PasswordEncoder passwordEncoder;
@Autowired
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
/**
* Creates a new user account
* @param email email address
* @param password unencoded password
* @param firstname firstname
* @param lastname lastname
* @param displayName display name
* @return new User
*/
public User createUser(String email, String password, String firstname, String lastname, String displayName) {
User user = new User();
user.setEmail(email);
user.setFirstname(firstname);
user.setLastname(lastname);
user.setDisplayName(displayName);
if (password != null && !password.isEmpty()) {
user.setPassword(passwordEncoder.encode(password));
}
user.setEmailVerified(false);
user.setCreatedAt(new Date());
user.setUpdatedAt(user.getCreatedAt());
userRepository.save(user);
return user;
}
}
Finally, my user repository looks like this (spring data);
public interface UserRepository extends CrudRepository<User, String> {
}