type=page
status=published
title=Using Method Constraints in Type Hierarchies
next=partcdi.html
prev=bean-validation-advanced003.html
~~~~~~
Using Method Constraints in Type Hierarchies
============================================

[[CIHGJBGI]]

[[using-method-constraints-in-type-hierarchies]]
Using Method Constraints in Type Hierarchies
--------------------------------------------

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:

[source,oac_no_warn]
----
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:

[source,oac_no_warn]
----
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:

[source,oac_no_warn]
----
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`.

[[sthref125]]

[[rules-for-using-method-constraints-in-type-hierarchies]]
Rules for Using Method Constraints in Type Hierarchies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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.
