Search code examples
javahibernate-validator

using javax.validation to validate bean with choices


I'm implementing an in-memory API gateway to a SOAP service utilizing JAXB. One of the schema elements is a "choice", and there are several elements in the choice block.

I'm attempting to mirror the generated JAXB classes in the client namespace, so for this "choice" scenario I have a bean class with several properties, only one of which will be non-null.

I'm attempting to use the @NotNull annotation from javax.validation, along with the ValidatorFactory and Validator. However, a "choice" scenario makes this a little more complicated. I'm guessing this would call for a custom ConstraintValidator, along with a custom annotation to refer to the custom ConstraintValidator.

For instance, here's some fake code that resembles a part of my structure:

public class InquireRandomInformationRequest {
    @NotNull(message ="subscriberSelector cannot be null")
    @Valid
    private SubscriberSelector   subscriberSelector;  // required
    private SelectorMode         mode;                // optional
 ...
}

public class SubscriberSelector {
    // Choice 1
    private String                    billingAccountNumber;             // \d{8,9,12,13}; required
    private MarketInfo                billingMarket;                    // optional

    // Choice 2
    private String                    subscriberNumber;                 // \d{10}; required
    private ValidationCriteria        validationCriteria;               // optional
    private BillingAccountInformation billingAccountInformation;        // optional
    private MemoProductType           memoProductType;                  // optional

    // Choice 3
    private String                    unifiedBillingAccountNumber;      // [0-9A-Za-z]{13}; required
...
}

I understand that I need the @Valid annotation on the "subscriberSelector" property for the validator to validate the sub-object. Past that, I'm not quite sure what I need to do to handle the choices problem.

To fit my example, I will need exactly one of "billingAccountNumber", "subscriberNumber", or "unifiedBillingAccountNumber" to be non-null (although I could compromise on simply taking the first non-null one in a particular sequence). In each "choice group", the other properties are optional, but it's possible that another property could be "required" if that particular choice group is selected (the selector property is non-null, in other words).

I've looked through the Hibernate Validator documentation, but I'm not sure exactly how to apply that for this situation.

If I define a custom annotation and a custom ConstraintValidator, where is the annotation referenced? On the class (like "SubscriberSelector") or on the "subscriberSelector" property (the former seems more logical to me).


Solution

  • You can define constraints on the class or on the property depending on your requirements.

    Usually, the constraints are placed on the property but, in the case you mention, as multiple properties are concerned and interdependent, you should place the constraint at the class level.

    See https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-declaring-bean-constraints in our documentation.