A customer wrote in asking for an example of implementing a BC4J validation rule that can be attached declaratively to any date-valued attribute to constrain it to be a date in the future. I crafted up a quick example FutureDateValidator workspace that shows how to do it here.
To create a new rule, I just edited the properties of my *.jpx file and visited the "Registered Rules" panel. I clicked the (New) button and gave my new validator a name. In the validator class, I wrote the validateValue() method to check for a date in the future like this:
public boolean validateValue(Object value) { if (value instanceof Date) { Date dateValue = (Date)value; return dateValue.compareTo(Date.getCurrentDate()) >= 1; } return true; }
and then in the vetoableChange() method, which the framework calls when the Entity object attribute to which the rule gets attached has its value changed, I wrote the bit of code to throw an appropriate AttrValException with a custom validation error message coming from a ErrorMessages message bundle I created in the project:
public void vetoableChange(PropertyChangeEvent eventObj) { Object value = eventObj.getNewValue(); EntityImpl entity = (EntityImpl)eventObj.getSource(); String entityName = ((EntityDefImpl)entity.getStructureDef()).getFullName(); String attrName = eventObj.getPropertyName(); if (!validateValue(value)) { throw new AttrValException(ErrorMessages.class, ErrorMessages.DATE_MUST_BE_IN_FUTURE, entityName, attrName, value, null); /* No extra exception details */ } }
With that rule written, I can go around in the BC4J design time and attach this reusable rule to any Date attribute that might need this FutureDate rule in a declarative way from the Validation panel of the Entity Object Editor.
The customer was originally approaching the problem by thinking to implement a special Date domain subclass that checked for a date in the future in its domain's validate() method, but I advised against using a domain for that kind of validation because when he would be querying rows having dates in the past -- which maybe he created correctly yesterday! -- BC4J would be constructing rows having his custom OnlyFutureDate domain and the validation would fail during fetch time if the date had in the meantime "slipped" into the past, based on the current System time.
9:59:44 PM
|