JSR-303: Yet Another Cross-field Validation Problem
I have a @Money
constraint that indicates the annotated Double
property is, well, money. I wrote a ConstraintValidator
that checks if a @Money
property has a valid value, which depends on a Currency
instance. For example, USD has both dollar and cent values whereas Japanese Yen doesn't, so while 19.99 is a valid value for USD, it isn't for JPY. The Currency
value is stored in another property of the same bean.
The problem is looking up the Currency
property of a given bean within the ConstraintValidator
. I thought about making it class-level validation, but it would be quite cumbersome and redundant to write at the class level which fields are money, and more importantly, you can only generate one error message, even if there is more than one money property that is invalid.
Any suggestions, even Hiberna开发者_运维知识库te Validator specific ones are welcome.
Thanks!
IMO, the simplest solution is to create a separate java class say Money
that holds both information, the type of money (i.e. Currency) and the value of money.
public class Money {
private Currency currency;
private Double value;
public Currency getCurrency() { return currency; }
public void setCurrency(Currency currency) { this.currency = currency; }
public Double getValue() { return value; }
public void setValue(Double value) { this.value = value; }
public boolean isValid() {
if(getCurrency() == null || getValue() == null) {
return false;
}
// critical logic goes here
// sample code
if("JPY".equalsIgnoreCase(currency.getCurrencyCode())) {
int intValue = getValue().intValue();
double diff = getValue() - intValue;
if(diff > 0) {
return false;
}
}
/*double fractionValue = value - (value % (currency.getDefaultFractionDigits() * 10));
if(fractionValue > currency.getDefaultFractionDigits() * 10) {
return false;
}*/
return true;
}
}
After this, create a constraint say @ValidMoney
and MoneyValidator
.
public class MoneyValidator implements ConstraintValidator<ValidMoney, Money> {
@Override
public void initialize(ValidMoney constraintAnnotation) {
// TODO Auto-generated method stub
}
@Override
public boolean isValid(Money value, ConstraintValidatorContext context) {
return value.isValid();
}
}
Example:-
public class Bid {
@ValidMoney
private Money bidAmount;
}
精彩评论