简体   繁体   中英

SpringBoot Bean Validation annotation

I am currently writing some @SpringBootTest for bean validation in services.

@Data
@Document
public final class Supplier {

    @Id
    @NotEmpty
    private String supplierId;
    ...
    @NotEmpty
    private String hash;
    ....
}

Test

Annotated with:

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.MOCK)

and

 @Test
    void testValidation() {
        Supplier invalidSupplier = SupplierTestDataUtil.createSupplier("1234");
        invalidSupplier.setSupplierId(null);

        //works
        assertThrows(ConstraintViolationException.class, () -> supplierService.publish(invalidSupplier));

        //works
        assertThrows(ConstraintViolationException.class, () -> supplierService.persist(invalidSupplier));
        
        //works not
        assertThrows(ConstraintViolationException.class, () -> supplierService.saveAndPublish(invalidSupplier));

        //works
        assertThrows(ConstraintViolationException.class, () -> supplierService.delete(invalidSupplier));
    }

Service:

@Transactional
public Supplier saveAndPublish(@NotNull Supplier supplier) {
    supplier.setHash(messageDigester.digest(supplier));
    Supplier persisted = persist(supplier);
    publish(supplier);
    return persisted;
}

@Transactional
public Supplier persist(@Valid @NotNull Supplier supplier) {
    return repository.save(supplier);
}

Supplier at saveAndFlush must not be valid at this point because required hash will be generated and set inside that method. Nevertheless my expectation was that ConstraintViolationException will be also thrown because I also call persist and publish method and pass that invalid document.

My point is that you can bypass BeanValidation within the same class.

The ConstraintViolationException will be thrown by a Spring Validator which won't be used if you call persist "manually". If persist is called from a Spring context, the @Valid annotation will tell Spring to validate the object based on the class's validation constraints.

You could:

  1. Validate hash always "manually" (without the @NotEmpty annotation)
  2. Call supplier.setHash(messageDigester.digest(supplier)); before calling saveAndPublish and add the @Valid annotation to the Supplier argument of saveAndPublish
  3. Add a Validator instance as a field to your service and call it manually on the Supplier to be validated (in case of saveAndPublish after setting the hash, of course)
  4. Implement two different types of Supplier , eg, AddSupplier (without hash being validated; used by saveAndPublish ) and EditSupplier (with hash being validated; used by persist )

(this is probably an incomplete list)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM