1

In JSR-303, is there any way to change the value while validating?

public class MyEntity {

    public String getName() {
        return name;
    }

    // is it true that JSF/JAXB/JPA will always use this setter method?
    public void setName(final String name) {
        if (name == null) {
            throw new NullPointerException("null name");
        }
        final String collapsed = new CollapsedStringAdapter().unmarshal(name);
        if (collapsed.length() < NAME_SIZE_MIN) {
            throw new IllegalArgumentException("too short");
        }
        if (collapsed.length() > NAME_SIZE_MAX) {
            throw new IllegalArgumentException("too long");
        }
        this.name = collapsed;
    }

    @NotNull
    @Size(min = 1, max = 40)
    @CollapsedStringSize(min = 1, max = 40) // xs:token
    private String name;

    @NotNull
    @Size(min = 0, max = 255)
    @NormalizedStringSize(min = 0, max = 255) // xs:normalizedString
    private String description;
}

Say, I'm going to make a custom validator something look like

@Constraint(validatedBy = CollapsedStringSizeValidator.class)
public @interface CollapsedStringSize {
    int min() default 0;
    int max() default Integer.MAX_VALUE;
}

public class CollapsedStringSizeValidator
    implements ConstraintValidator<CollapsedStringSize, String> {

    @Override
    public boolean isValid(String object,
                           ConstraintValidatorContext constraintContext) {

        if (object == null) {
            return true;
        }

        final String collapsed = new CollapsedStringAdapter().unmarshal(object);

        // how can I get the min/mix anyway?

        return collapsed.length() >= min && collapsed.length() <= max;
    }
}

Is there any way to change the value before or while a validator validate/validating?
Do I have to stuck with the setter?

DataNucleus
  • 15,497
  • 3
  • 32
  • 37
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
  • May I ask why you want to change the value while the engine is validating? Could your describe more information about your case? – Mike Lue Mar 14 '12 at 09:14
  • actually my original concern is keeping the value as a valid form (collapsed/normalized) before marshalling to XML or before persisting to DB. – Jin Kwon Mar 14 '12 at 10:48
  • 1
    Well, if your can figure out the "valid form" of input data automatically, using setter is possible before the data is persisted into database. The main use of validation framework is to validate data, which can't be corrected automatically, without complicating your code of business logic. Moreover, validation framework let you just write the validation logic at a testable unit. – Mike Lue Mar 15 '12 at 02:18

1 Answers1

1

In your example, the setName() should be:

public void setName(final String name) {
    if (name == null) {
        this.name = null;
        return;
    }
    this.name = new CollapsedStringAdapter().unmarshal(name);
}

As above modification, you don't have to use @CollapsedStringSize anymore. The @Size is sufficient for your validation.

In JPA, if you want to process data after the JPA engine has loaded data into your entity object, you may try @PostLoad.

buræquete
  • 14,226
  • 4
  • 44
  • 89
Mike Lue
  • 839
  • 4
  • 8
  • You're right. I don't even require the `null` check because there is `@NotNull` too. Is it true that JPA/JSF may directly set the value from the DB/Facelet to the field by reflection or something without existing setter method? So should I consider `@PostLoad` besides the setter? – Jin Kwon Mar 15 '12 at 06:36
  • I'm not familiar with JSF. For JPA, check out [this question](http://stackoverflow.com/questions/3976469/is-hibernate-jpa-taking-in-consideration-the-transiant-modifier-not-the-anno) for detailed information – Mike Lue Mar 15 '12 at 06:49