Reputation: 6207
I'm generating POJOs from json schema using jsonschema2pojo. I want to use the jsr303/349 bean validation stuff. I added the necessary items to the classpath, added the necessary beans to trigger the validation, however jsonschema2pojo does not add @org.springframework.validation.annotation.Validated
to the generated classes and so the validation doesn't get triggered when a request comes into my spring boot application.
I was able to confirm that my validator is set up correctly by writing an empty class like so and changing the @RequestBody
type to the new type:
@Validated
class SomeClass extends SomeGeneratedClass {
}
When I did so validation works as expected. However, we're looking at dozens if not potentially a hundred or more of these extension objects and having a bunch of those is the epitome of wet (IE, not DRY) code and so this is less than ideal as a solution.
So my question is: Is there a way to trigger bean validation in spring on an incoming request if the object in question is not annotated with @Validated
? Note that jsonschema2pojo does not have a dependency currently on Spring and I find it unlikely the author would accept a pull request that adds one.
-- Code if it's helpful
An example JSON schema:
{
"type": "object",
"properties": {
"userIds": {
"type": "array",
"items": { "type": "string" },
"minSize": 1
}
},
"additionalProperties": false,
"required": ["userIds"]
}
Generated class:
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"userIds"
})
public class ExampleSchema {
/**
*
* (Required)
*
*/
@JsonProperty("userIds")
@Valid
@NotNull
private List<String> userIds = new ArrayList<String>();
/**
*
* (Required)
*
*/
@JsonProperty("userIds")
public List<String> getUserIds() {
return userIds;
}
/**
*
* (Required)
*
*/
@JsonProperty("userIds")
public void setUserIds(List<String> userIds) {
this.userIds = userIds;
}
public ExampleSchema withUserIds(List<String> userIds) {
this.userIds = userIds;
return this;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(userIds).toHashCode();
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof ExampleSchema) == false) {
return false;
}
ExampleSchema rhs = ((ExampleSchema) other);
return new EqualsBuilder().append(userIds, rhs.userIds).isEquals();
}
}
Validation bean setup in my WebConfig:
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor(LocalValidatorFactoryBean validator) {
final MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setValidator(validator);
return methodValidationPostProcessor;
}
@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
And my controller method:
@RequestMapping(value = "", method = RequestMethod.POST)
public void postExample(@RequestBody @Valid ExampleSchema example) {
//Perform actions on validated object
}
Upvotes: 2
Views: 1174
Reputation: 57
create an initbinder in your controller like this:
@Autowired
YourValidator validator;
@InitBinder()
protected void initBinder(WebDataBinder binder) {
binder.setValidator(validador);
}
And in your endpoint
public OrdenServicioTo guardarOrden(@ModelAttribute("dto")@Validated @RequestBody Object dto)
{
///YOurCode
}
Upvotes: 0
Reputation: 8324
In your class you're defining and instantiating the array in the same line.
private List<String> userIds = new ArrayList<String>();
So, when Spring validate the object, the List userIds is not null.
You have two options here.
You can remove the instantiation of the userIds.
private List userIds;
You can change the validation. Instead of using @NotNull
you can use @Size(min=1)
or you can use they both. Also you can use @NotEmpty
but you need the hibernate validator.
Upvotes: 1
Reputation: 29276
You can annotate Controller
or Service
with @Validated
rather than doing it for all objects that need to be validated, as:
@Validated
@Controller
public class Controller {
@RequestMapping(value = "", method = RequestMethod.POST)
public void postExample(@RequestBody @Valid ExampleSchema example){
//Perform actions on validated object
}
}
Upvotes: 0