I recently discovered that I became unfashionable by using the setAttributeXXX() and validateEntity() method for implementing business rules in ADF BC instead of using Validators. Not that I didn't know of Validators, I just thought that they would not give me proper control over exception and message handling. Because one of the things I would like to have, is one single message bundle in which I could use a consistent coding of my messages, like APP-00001, APP-00002, etc. Even more important, the other thing I would like to have is that I can translate all messages to Kalaallisut the minute I need to make my application available for the Inuit people of Greenland.
As you might know, up till JDeveloper 10.1.3 ADF BC will create an entity-specific message bundle to store the messages you provide with Validators. So with many entity objects big chance you end up with many message bundles, making that keeping error codes consistent becomes a nightmare. And what about all the separate files you need to translate! You might find yourself no longer to be able to tell the messages for the bundles.
But as Steve Muench was very persistent in trying to convince me using Validators I finally gave in and tried finding a way to tackle my problem, and succeeded! No worries, don't expect rocket science from me. I hate complex or obscure code, as building maintainable Information Systems already is hard enough as it is, and therefore always try to practice Simple Design.
I assume that you have created a layer of framework extension classes as described in section 2.5 of the ADF Developers Guide and that your entity base class is called MyAppEntityImpl. If you have not yet created such a layer, do that first and come back after you finished. Chop chop!
Basically the steps are as follows:
- Create extension classes that extend the exceptions that ADF BC will throw when validation fails
- Override the constructor of the super class and pass in the message bundle in the call to super()
- Override the setAttributeInternal() and validateEntity() methods in the MyAppEntityImpl.java entity base class and make they thrown your exceptions instead of the default ones.
Attribute-level Validators will throw the AttrValException. So what I did was create a MyAppAttrValException as follows:
public class AttrValException extends AttrValException
public MyAppAttrValException(String errorCode, Object params)
super(ResourceBundle.class, errorCode, params);
* When the message contains a semicolon, return the message
* starting with the position after the semicolon and limit the
* text to the message text from the resource bundle.
* @return the stripped message
public String getMessage()
String message = super.getMessage();
// strip off product code and error code
int semiColon = message.indexOf(":");
if (semiColon > 0)
message = message.substring(semiColon + 2);
And this is how I override the setAttributeInternal in the MyAppEntityImpl:
* Overrides the setAttributeInternal of the superclass in order to
* pass in a custom message bundle to MyAppAttrValException subclass
* of the AttrValException. To be able to uniquely identify the
* entries in the message bundle, the error code is extended with the
* fully qualified class name of the
protected void setAttributeInternal(int index, Object val)
catch (AttrValException e)
String errorCode = new StringBuffer(getClass().getName())
throw new MyAppAttrValException(errorCode, e.getErrorParameters());
In a similar way you can handle entity-instance-level Validators and Method Validator by extending the ValidationException and overriding the validateEntity() method to throw your MyAppValidationException.
As said, the message you provided when creating build-in Validators and Method Validators end up in an entity-specific message bundle. I've been told that this is going to change in JDeveloper 11g, but currently there is no stopping ADF BC from doing that.
So, at a convenient point in time (for example when most of your Validators have been implemented and tested), what you need to do is copying the error messages from the entity-specific message bundles to your custom message bundle.
To prevent duplicates in the keys of the custom message bundle, you should extend the key of each message with the fully qualified class name of the
The entries in the message bundle would look
"APP-00001 Employee's Salary may not be below zero" },
Well that wasn't rocket science, was it?