public class Person {
...
public void setPhone(String phone) { ... }
}
public class Employee extends Person {
...
@Override
public void setPhone(@Verified String phone) { ... }
}
Java Platform, Enterprise Edition (Java EE) 8 The Java EE Tutorial |
Previous | Next | Contents |
If you add validation constraints to objects in an inheritance hierarchy, take special care to avoid unintended errors when using subtypes.
For a given type, subtypes should be able to be substituted without
encountering errors. For example, if you have a Person
class and an
Employee
subclass that extends Person
, you should be able to use
Employee
instances wherever you might use Person
instances. If
Employee
overrides a method in Person
by adding method parameter
constraints, code that works correctly with Person
objects may throw
validation exceptions with Employee
objects.
The following code shows an incorrect use of method parameter constraints within a class hierarchy:
public class Person {
...
public void setPhone(String phone) { ... }
}
public class Employee extends Person {
...
@Override
public void setPhone(@Verified String phone) { ... }
}
By adding the @Verified
constraint to Employee.setPhone
, parameters
that were valid with Person.setPhone
will not be valid with
Employee.setPhone
. This is called strengthening the preconditions
(that is, the method parameters) of a subtype’s method. You may not
strengthen the preconditions of subtype method calls.
Similarly, the return values from method calls should not be weakened in subtypes. The following code shows an incorrect use of constraints on method return values in a class hierarchy:
public class Person {
...
@Verified
public USPhoneNumber getPhone() { ... }
}
public class Employee extends Person {
...
@Override
public USPhoneNumber getPhone() { ... }
}
In this example, the Employee.getPhone
method removes the @Verified
constraint on the return value. Return values that would be not pass
validation when calling Person.getEmail
are allowed when calling
Employee.getPhone
. This is called weakening the postconditions (that
is, return values) of a subtype. You may not weaken the postconditions
of a subtype method call.
If your type hierarchy strengthens the preconditions or weakens the
postconditions of subtype method calls, a
javax.validation.ConstraintDeclarationException
will be thrown by the
Bean Validation runtime.
Classes that implement several interfaces that each have the same method signature, known as parallel types, need to be aware of the constraints applied to the interfaces that they implement to avoid strengthening the preconditions. For example:
public interface PaymentService {
void processOrder(Order order, double amount);
...
}
public interface CreditCardPaymentService {
void processOrder(@NotNull Order order, @NotNull double amount);
...
}
public class MyPaymentService implements PaymentService,
CreditCardPaymentService {
@Override
public void processOrder(Order order, double amount) { ... }
...
}
In this case, MyPaymentService
has the constraints from the
processOrder
method in CreditCardPaymentService
, but client code
that calls PaymentService.processOrder
doesn’t expect these
constraints. This is another example of strengthening the preconditions
of a subtype and will result in a ConstraintDeclarationException
.
The following rules define how method validation constraints should be used in type hierarchies.
Do not add method parameter constraints to overridden or implemented methods in a subtype.
Do not add method parameter constraints to overridden or implemented methods in a subtype that was originally declared in several parallel types.
You may add return value constraints to an overridden or implemented method in a subtype.
Previous | Next | Contents |