Description
The javax/jakarta annotations contain a groups
property that can be used to enable different combinations of validation on a model depending on which group is currently active - https://jakarta.ee/learn/docs/jakartaee-tutorial/current/beanvalidation/bean-validation-advanced/bean-validation-advanced.html#_grouping_constraints.
When executed against a model, swagger-core currently treats any of the supported javax/jakarta annotations as applying a constraint to the schema, even where the annotated field/attribute specifies groups and is therefore is not mandatory on all requests. By default, swagger-core should only set fields as mandatory/constrained based on annotations where no groups are specified, but provide a way of the end-user adding other validation groups into the constraints where they want to treat certain groups as always being enabled.
Replication Steps
@Test
public void shouldIncludeOnlyNonGroupedJakartaValidatedFieldsAsMandatoryByDefault() {
ResolvedSchema schema = ModelConverters.getInstance(false).resolveAsResolvedSchema(new AnnotatedType().type(CustomClass.class));
String expectedJson = "{\"schema\":{\"required\":[\"nonGroupValidatedField\"],\"type\":\"object\",\"properties\":{\"nonGroupValidatedField\":{\"type\":\"string\"},\"singleGroupValidatedField\":{\"type\":\"integer\",\"format\":\"int32\"},\"multipleGroupValidatedField\":{\"type\":\"number\"},\"otherGroupValidatedField\":{\"type\":\"string\"},\"singleGroupValidatedField2\":{\"type\":\"string\"}}},\"referencedSchemas\":{\"CustomClass\":{\"required\":[\"nonGroupValidatedField\"],\"type\":\"object\",\"properties\":{\"nonGroupValidatedField\":{\"type\":\"string\"},\"singleGroupValidatedField\":{\"type\":\"integer\",\"format\":\"int32\"},\"multipleGroupValidatedField\":{\"type\":\"number\"},\"otherGroupValidatedField\":{\"type\":\"string\"},\"singleGroupValidatedField2\":{\"type\":\"string\"}}}}}";
SerializationMatchers.assertEqualsToJson(schema, expectedJson);
}
private interface ValidationGroup {
}
private interface OtherValidationGroup {
}
private static class CustomClass {
@NotNull
public String nonGroupValidatedField;
@Min(value = 1, groups = ValidationGroup.class)
public Integer singleGroupValidatedField;
@DecimalMin(value = "1.0", groups = {ValidationGroup.class, OtherValidationGroup.class})
public BigDecimal multipleGroupValidatedField;
@Pattern(regexp = ".*", groups = OtherValidationGroup.class)
public String otherGroupValidatedField;
@NotEmpty(groups = ValidationGroup.class)
public String singleGroupValidatedField2;
}
The above replicate a validator being run in default mode, e.g. Validation.buildDefaultValidatorFactory().getValidator().validate(new CustomClass());
, which is the default way that frameworks such as Spring invoke validators. Users using something similar to
Validation.buildDefaultValidatorFactory().getValidator().validate(new CustomClass(), ValidationGroup.class);
would add the annotations with ValidationGroup
in the groups
property into the enforced validation.