0

Hello I have the next piece of code:

@Setter
@Getter
@Builder
public class User {
  
  @Pattern(regexp = "[a-zA-Z]*")
  private String username;

  public User(String username){
    this.username = username;
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Set<ConstraintValidation<User>> violations = factory.getValidator().validate(this);
    if(!violations.isEmpty) throw new ConstraintViolationExcetion(violations);
}

It is working, and when I try to create an User it always check the constraints (also with builder pattern), but i would like to avoid to generate the constructor and use the lombok anotation @AllArgsConstructor and use the PostConstruct from javax to validate.

@Setter
@Getter
@AllArgsConstructor
@Builder
public class User {
  
  @Pattern(regexp = "[a-zA-Z]*")
  private String username;

  @PostConstruct
  public void valid() {
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Set<ConstraintValidation<User>> violations = factory.getValidator().validate(this);
    if(!violations.isEmpty) throw new ConstraintViolationExcetion(violations);
}

I'm using JAVA11 including javax.annotation dependency. User is a regular object, not a bean of spring. But this way is not working... How can I make it work? Thanks.

2 Answers2

1

if you are using a java version of 9 or above @PostConstruct is deprecated, so you might need to add a dependency manually. could you add which java version are you using?

another reason why it is not working is because you did not apply @Component annotation and @PostConstruct only works with beans managed by spring container.

ref: Why is PostConstruct not called?

I would recommend you to look at BeanPostProccessor for AOP since it is more flexible and will allow you to do validations on your bean. this is also pure aop.

  • Added! Thanks. But i wold not like to include the `@Component` annotation because I think it is not the same as a controller or a service. May I be wrong? – rubengonzalez96 Dec 02 '21 at 08:26
  • `@Service`, `@Rpository`, `@Controller` are a `@Component` but just look at them as different roles. or as children of `@Component`, however, without one of those annotations `@PostConstruct` won't be able to work since no framework responds and manages them. so you must use it under a POJO with a `@Component` annotation. otherwise its ignored. – Fastaca Girasol Dec 02 '21 at 11:44
0

Finally I found the behavour I was looking for.

@Setter
@Getter
public class User {
  
  @Pattern(regexp = "[a-zA-Z]*")
  private String username;

  @Builder
  public User(String username){
    this.username = username;
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Set<ConstraintValidation<User>> violations = factory.getValidator().validate(this);
    if(!violations.isEmpty) throw new ConstraintViolationExcetion(violations);
}

Furthermore, I would implement a self validable class to be reusable.

public abstract class SelfValidating < T > {
    private Validator validator;
    public SelfValidating() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }
    protected void validateSelf() {
        Set < ConstraintViolation < T >> violations = validator.validate((T) this);
        if (!violations.isEmpty()) {
            throw new ConstraintViolationException(violations);
        }
    }
}

And then, my User class just would:

@Setter
@Getter
public class User extends SelfValidating<User> {
  
  @Pattern(regexp = "[a-zA-Z]*")
  private String username;

  @Builder
  public User(String username){
    this.username = username;
    this.validateSelf();
}

This idea is taken from Get Your Hands Dirty on Clean Architecture