Spring data rest validation for PUT and PATCH running after DB update

末鹿安然 提交于 2019-12-11 07:24:21

问题


I have a SDR project and I am successfully validating the user entity for POST request but as soon as I update an existing entity using either PATCH or PUT the DB is updated BEFORE the validation is executed (the validator is being executed and error is returned but the DB is being updated anyway).

Do I need to setup a separate config for update ? Am I missing an extra step for that?

Entity

@Entity
@JsonIgnoreProperties(ignoreUnknown = true)
public class Member {

    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "member_id_gen")
    @SequenceGenerator(name = "member_id_gen", sequenceName = "member_id_seq")
    @Id
    @JsonIgnore
    private long id;

    @Version
    private Integer version;

    @NotNull
    protected String firstName;
    @NotNull
    protected String lastName;

    @Valid
    protected String email;

}

Repository

@RepositoryRestResource(collectionResourceRel = "members", path = "member")
public interface MemberRepository extends PagingAndSortingRepository<Member, Long>  {

     public Member findByFirstName(String firstName); 

     public Member findByLastName(String lastName); 

}

Validator

@Component
public class BeforeSaveMemberValidator implements Validator {

    public BeforeSaveMemberValidator() {}

    private String EMAIL_REGEX = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$";

    @Override
    public boolean supports(Class<?> clazz) {
        return Member.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        Member member = (Member) target;

        if(ObjectUtils.isEmpty(member.getFirstName())) {
            errors.rejectValue("firstName", "member.firstName.empty");
        }

        if(ObjectUtils.isEmpty(member.getLastName())) {
            errors.rejectValue("lastName", "member.lastName.empty");
        }

        if(!ObjectUtils.isEmpty(member.getDni()) && !member.getDni().matches("^[a-zA-Z0-9]*$")) {
            errors.rejectValue("dni", "member.dni.invalid");
        }

        if(!ObjectUtils.isEmpty(member.getEmail()) && !member.getEmail().matches(EMAIL_REGEX)) {
            errors.rejectValue("email", "member.email.notValid");
        }
    }
}

BeforeSave service

@Service
@RepositoryEventHandler(Member.class)
public class MemberService {

    @HandleBeforeCreate
    @HandleBeforeSave
    @Transactional
    public void beforeCreate(Member member) {
        ...
    }

}

回答1:


I think you should rename your validator, for example, to MemberValidator then assign it as described here:

@Override
protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener v) {
  v.addValidator("beforeCreate", new MemberValidator());
  v.addValidator("beforeSave", new MemberValidator());
}

But I suggest you to use Bean validation instead of your custom validators. To use it in SDR project you can inject LocalValidatorFactoryBean, then assign it for 'beforeCreate' and 'beforeSave' events in configureValidatingRepositoryEventListener:

@Configuration
@RequiredArgsConstructor // Lombok annotation
public class RepoRestConfig extends RepositoryRestConfigurerAdapter {

    @NonNull private final LocalValidatorFactoryBean validatorFactoryBean;

    @Override
    public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener v) {
        v.addValidator("beforeCreate", validatorFactoryBean);
        v.addValidator("beforeSave", validatorFactoryBean);
        super.configureValidatingRepositoryEventListener(v);
    }
}

In this case your SDR will automatically validate payloads of POST, PUT and PATCH requests for all exposed SDR repositories.

See my example for more details.



来源:https://stackoverflow.com/questions/46999658/spring-data-rest-validation-for-put-and-patch-running-after-db-update

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!