Haider
Haider

Reputation: 615

Is there a way to show constraint message

I have class CategoryDTO and i want to show the message "Description can't be null" in rest docs instead of "Must not be null".Though i know i can change this message my creating a constraint properties file and adding below line to it

javax.validation.constraints.NotNull.description=Must not be blank or null 

But i want to show the message in NotNull annotation

public class CategoryDTO 
{
    private String id;

    @NotNull(message = "Description can't be null")
    @Size(min = 2 , max=30 , message = "Size must be greater than 2 and less than 30")
    private String description;
}

Edit:

   @Test
    void testFindAll() 
    {

        CategoryDTO fruits = new CategoryDTO();
        fruits.setDescription("Fruits");
        fruits.setId(UUID.randomUUID().toString());


        CategoryDTO Nuts = new CategoryDTO();
        Nuts.setDescription("Nuts");
        Nuts.setId(UUID.randomUUID().toString());

        ConstrainedFields fields = new ConstrainedFields(CategoryDTO.class);

        BDDMockito.when(categoryService.findAll()).thenReturn(Flux.just(fruits,Nuts));

        webTestClient.get().uri(CategoryController.rootURL + "/categories")
        .exchange().expectBodyList(CategoryDTO.class).
        hasSize(2).consumeWith(WebTestClientRestDocumentationWrapper.document("v1/get-all-categories",              
                responseFields(
                        fields.withPath("[]").description("An array of categories"),
                        fields.withPath("[].id").description("Id of category"),
                        fields.withPath("[].description").description("Description of category")
                        )
                ));
    }

Upvotes: 0

Views: 509

Answers (2)

Haider
Haider

Reputation: 615

With the help of Andy's answer here is the final outcome

import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.snippet.Attributes.key;

import java.util.regex.Pattern;

import org.springframework.restdocs.constraints.ConstraintDescriptions;
import org.springframework.restdocs.constraints.ResourceBundleConstraintDescriptionResolver;
import org.springframework.restdocs.payload.FieldDescriptor;
import org.springframework.util.StringUtils;

public class ConstrainedFields
{
    private final ConstraintDescriptions constraintDescriptions;

    public ConstrainedFields(Class<?> input) {

        ResourceBundleConstraintDescriptionResolver fallback = new ResourceBundleConstraintDescriptionResolver();
        this.constraintDescriptions = new ConstraintDescriptions(input, (constraint) -> {
            String message = (String) constraint.getConfiguration().get("message");
            if (message != null && !Pattern.compile("\\{(.*?)\\}").matcher(message).matches()) {
                return message;
            }
            return fallback.resolveDescription(constraint);
        });     
    }

    public FieldDescriptor withPath(String path) 
    {
        return fieldWithPath(path).attributes(key("constraints").value(StringUtils
                .collectionToDelimitedString(constraintDescriptions
                        .descriptionsForProperty(path), ". ")));
    }
}

Upvotes: 1

Andy Wilkinson
Andy Wilkinson

Reputation: 116061

By default, REST Docs' ConstraintDescriptions uses a ResourceBundleConstraintDescriptionResolver to obtain a description for each constraint. As its name suggests, it uses a ResourceBundle to provide the descriptions. You can provide your own implementation of ConstraintDescriptionResolver to use a different mechanism. In your case, you want to use the message from the constraint annotation as shown in the following example:

ConstraintDescriptions descriptions = new ConstraintDescriptions(CategoryDTO.class, (constraint) -> {
    return (String) constraint.getConfiguration().get("message");
});
List<String> descriptionProperty = descriptions.descriptionsForProperty("description");
System.out.println(descriptionProperty);

When executed, the above will output the following:

[Description can't be null, Size must be greater than 2 and less than 30]

If you don't always configure the message attribute, you may want to fall back to the resource bundle resolver, as shown in the following example:

ResourceBundleConstraintDescriptionResolver fallback = new ResourceBundleConstraintDescriptionResolver();
ConstraintDescriptions descriptions = new ConstraintDescriptions(CategoryDTO.class, (constraint) -> {
    String message = (String) constraint.getConfiguration().get("message");
    if (message != null) {
        return message;
    }
    return fallback.resolveDescription(constraint);
});

Upvotes: 1

Related Questions