Reputation: 475
I just can't get validations to work. I have this simple endpoint that is part of an Spring Boot application:
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response create(@Valid UserDTO userDTO, @Context UriInfo uriInfo) {
User user = UserParser.parse(userDTO);
userService.save(user);
final URI uri = uriInfo.getAbsolutePathBuilder().path(String.valueOf(user.getId())).build();
return Response.created(uri).build();
}
Then, the UserDTO to validate:
@Getter
@Setter
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserDTO {
private Long id;
// redundant validations, for testing
@NotNull
@Size(min = 5, max = 80, message = "First name too short")
@NotBlank(message = "First name blank")
@NotEmpty(message = "First name empty")
private String firstName;
@NotNull
@Size(min = 2, max = 80, message = "Last name too short")
private String lastName;
@NotNull
private String email;
}
And it always processes any request, even with empty fields. I even created a test endpoint to see if the problem was having the validations inside the DTO
@Path("/validator/{testInt}")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String validator(@Valid @Min(value = 30, message = "testInt too small") @PathParam("testInt") Integer testInt) {
return String.valueOf(testInt);
}
But that doesn't work either, it happily returns any int it receives. In case it matters, my endpoint is a @Service
, and here is the relevant parts of my maven dependency tree:
[INFO] +- org.glassfish.jersey.ext:jersey-bean-validation:jar:2.22.1:compile
[INFO] | +- org.glassfish.hk2.external:javax.inject:jar:2.4.0-b31:compile
[INFO] | +- javax.validation:validation-api:jar:1.1.0.Final:compile
[INFO] | +- org.hibernate:hibernate-validator:jar:5.2.2.Final:compile
[INFO] | | +- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile
[INFO] | | \- com.fasterxml:classmate:jar:1.1.0:compile
[INFO] | +- javax.el:javax.el-api:jar:2.2.4:compile
[INFO] | \- org.glassfish.web:javax.el:jar:2.2.4:compile
I also set breakpoints inside HibernateValidator
, and saw that two of its methods get called, so looks like it's running. Just not validating.
EDIT: My jersey configuration
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(RequestContextFilter.class);
register(LoggingFilter.class);
register(JacksonFeature.class);
packages("com");
}
}
Upvotes: 9
Views: 9021
Reputation: 1284
The question was raised years ago, but for all using Stack Overflow as knowledge database, I want to record an additional solution thats works for me.
Despite contrary documentations I had to annotate the controller class with @Validated
and use @Valid
at method level in a Spring Boot (v2.1.3.RELEASE) with Hibernate (5.3.7.Final) and Hibernate Validator (6.0.14.Final) context. If one of both annotations was missing, I got also the above mentioned error scenario.
@RestController
@RequestMapping("/users")
@Validated
public class UserController {
@RequestMapping(value = "/create", method = RequestMethod.POST)
public User saveUser(@RequestBody @Valid UserDto user) {
<your service call>
}
}
Upvotes: 3
Reputation:
Add the following configuration to your JerseyConfig method
public JerseyConfig()
{
register(YourEndpoint.class);
property(org.glassfish.jersey.server.ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
}
Upvotes: 1
Reputation: 1807
ValidationFeature is auto discoverable as per jersey 2.0. You don't have to explicitly register it.
Include the flag, property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true)
in jersey resource config for the validation message to be sent in the response.
Make sure Jersey-bean-validation.jar is on the classpath (in your case it already is).
Simple Example,
//Web Resource
@Path("/accounts")
public Object getaccount(@Valid @BeanParam AccountRequest);
public class AccountRequest {
@NotNull
private String accountId;
}
refer, https://jersey.java.net/documentation/latest/bean-validation.html
Upvotes: 0
Reputation: 9162
In case it matters, my endpoint is a @Service
Try to set the stereotype to @Controller
Check if this bean is defined in your Web configuration.
@Bean
public javax.validation.Validator validator() {
return new org.springframework.validation.beanvalidation.LocalValidatorFactoryBean();
}
also check if your configuration has @EnableWebMvc
annotation
Upvotes: 0
Reputation: 10562
@Funtik's suggestion about making it an @Controller
is worth a try, but I suspect your problem is that you're not handling the error in your controller.
I'm not an expert on this, so recommend you do a little further reading, but I think you need to add a BindingResult, which will be populated in the event of validation errors. You then test that, and respond appropriately. So, I'd change your controller to something like:
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response create(@Valid UserDTO userDTO, BindingResult bindingResult, @Context UriInfo uriInfo) {
if (bindingResult.hasErrors()) {
return Response... // some error code, or however you want to handle validation errors
}
User user = UserParser.parse(userDTO);
userService.save(user);
final URI uri = uriInfo.getAbsolutePathBuilder().path(String.valueOf(user.getId())).build();
return Response.created(uri).build();
}
It's probably not an issue right now, but if you add a @ModelAttribute
annotated parameter to your method, bear in mind that the BindingResult
parameter needs to appear immediately after it, otherwise things don't work. I can't remember the exact problem you see if you don't do it, but it's tricky to find if you don't know the above. I've definitely seen it documented in the Spring docs somewhere, but can't find anything other than this forum post right now.
Upvotes: -1