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).
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.