Imagine Business Objects looking like ordinary Java Objects. They have setters and getters and your code calls those to do obvious things.
Now imagine these objects are self-aware of their validation requirements. They know they need a valid email address in that field, they know an amount cannot be less than 100 and so on. The calling code doesn’t know about any of this, but it gets a runtime exception when the data is not valid.
Let’s go a little further: You have an Order object with several Item objects attached. Each of those has an amount, the price of the item, and those need to be summed to a total in the Order. The Order knows this. When the calling code adds items or changes the amounts in the items it recalculates the total. It also does it if items are deleted, and it applies the freight and various discounts as well. Your calling code knows nothing of this. It just sees the amount changing.
The obvious way to do this is to code the business rules into the objects. We don’t do that. In fact we don’t directly code our business objects. We generate them with JAXB and we like to use the HyperJAB3 plugin to add persistence annotations, making them JPA compatible. And we also get JAXB to add the Madura hooks too.
We leave the rest up to Madura which uses the generated hooks to implement the business rules, and we interpret the term ‘business rules’ quite broadly. Here are some more examples of things we use them for. We do all these from the XSD file:
- The order reference field can have up to 30 characters, no more.
- The label for the order reference field is ‘order.reference’, a key to be looked up in the language resource before rendering.
- Only a user with SUPERVISOR permission can update the item amount field. Render it disabled for the others.
- Only a user with PAYROLL permission can see the wages amount field. Do not render it for the others.
- The Customer name field is required. Mark it on the UI somehow and disable the submit button until it is filled in.
- Also disable the submit button if any fields are in error, required or otherwise.
- Render the amount as a 2 decimal, with punctuation according to the user’s current locale.
- The Customer status field can only have values from an enum list. It has a default value of ‘retail’.
The business objects, generated from the XSD, look like anemic objects, and they are in the sense that they don’t contain the business rules, just a few hooks and annotations. The validation engine (part of Madura Objects) uses those to enforce the rules. So we call this a delegating anemic model. The important point is that the business rules are below the application code which is unaware of them. Clearly you can have multiple applications, perhaps using different technologies, using these objects, each of which has no knowledge or interest in implementing the rules.
So far almost everything has involved just one field at a time. You can specify a field length etc for each field. But what if the business rules involves multiple fields? That’s where the RulesPlugin comes in. The validation engine can be extended by configuring it with plugins and the plugin shown here is the RulesPlugin which implements business rules. This is actually Madura Rules, which is capable of cross validating fields and much more.