Chapter 1. Concepts

This chapter explains the building blocks of Baritus.

1.1. Using POJO's when buidling web applications

The ability to work with POJO's (Plain Old Java Objects) is one of the primary focusses of this framework.

The objects that you want to have populated from the HTTP request do not need to extend any base class or implement any interface. This way, you can populate classes from, for example, your domain model without the duplication of code you see often in Java web applications. And as you can nest objects as well, you could even populate several objects in one pass.

Type conversion and property navigation is done automatically, so there's is no need for configuration. Just provide a bean to populate and Baritus will do the rest. Population and is flexible and pluggable on several levels of abstraction. The default population delegate uses Ognl to resolve properties and set values.

If there are any errors during population, those errors are stored in the formBeanContext for later use. The original input values are stored in the formBeanContext as well, in order to be able to override the property value with the input value if a population or validation error occured.

As the controls are responsible for creating instances of the objects that should be populated (usually called form beans), no extra configuration is needed. Furthermore, you can do very interesting things with those objects before actually having them populated by Baritus. For instance, if you are working with a ORM tool (like Hibernate), you could load your persistent object, let Baritus populate it, and persist the changed object in the command method (perform) of your control. Tricks like these can be serious code savers, compared to where you work with a seperate domain- and form object and where you have to sync those two yourself.

As by default the formBeanContext is reused within one request, you have the option of reusing the allready populated form bean as well. And by setting property populateAndValidate from formBeanContext to false, you could even skip population/ validation in the current and laters steps in the command chain within one request.

Besides populating objects with HTTP request parameters, you can optionally have your objects populated with Maverick configuration parameters, request attributes and session attributes. It's all configurable for each instance of a control, or even for each request if you like.

1.2. Validation

Type conversion during population is in fact your first validation step. For further validation, like checking if a required property was set, or checking that a certain date is actually after the date of today, Baritus provides a flexible and pluggable validation mechanism.

De default provided validation mechanism is based on validation with Java objects that do the validation, and that are registered in the controls that want to use them. The default mechanism is probably powerfull enough for everything you want to do. It is possible however, to plug in one or more additional mechanisms. This way, you could use Commons Validator, FormProc, or possibly another validation framework with Baritus (though at this time no implementations are available).

The objects that do the validation come in two main forms:

  • nl.openedge.baritus.validation.FieldValidator. A field validator is coupled to one field, like a request parameter or a session attribute. Instances of FieldValidator are registered by name. The name that a field validator was registered with is matched against the population parameters. Field validators are useful for most common cases, like checking the length of an input etc. Field validators that are registered with the same name, are executed in the order that they were registered, UNTIL one of the validators fails or all validators passed.

  • nl.openedge.baritus.validation.FormValidator. A form validator is not coupled to one specific field, but is coupled to the control. This means that, independent of what fields are actually provided, the instances of FormValidator are executed. Form validators are useful for checking whether a property is not null (note that this differs from checking whether a field is not null) or checking more properties against each other.

Exactely when validators are used can be tuned with ValidationActivationRules. Validation activation rules can be registered on control (/form bean) level. These rules are checked before any validation is done. If one of the rules fails, no validation is done at all. If the control level rules allow validation, the FieldValidators are executed. Instances of FieldValidator can hold a reference to one rule. When a FieldValidator has a rule, this rule is used to check whether the field validator should be executed. If you want to stack rules for a field, you can put them in an instance of nl.openedge.baritus.validation.impl.NestedValidationActivationRule, and register this instance with the field validator. If all field validators succeeded, the form validators are executed, possibly dependent on a registered validation rule. If property doFormValidationIfFieldValidationFailed in ExecutionParams is true, form validation will allways be executed, whether the field validation succeeded or not.

If all population actions and validation actions have succeeded succesfully, the command method (perform) will be executed. If one of the actions failed, the command method will not be executed and the view that results from getErrorView (error by default) will be used. If property doPerformIfPopulationFailed from ExectuionParams is set to true (default is false), the command method is execution even if the population/ validation failed.

1.3. Interceptors

Interceptors provide a means to encapsulate cross-cutting code that is executed on pre-defined points in the line of execution.

Interceptors can be used to 'enrich' de model (formBeanContext), eg. load data, save session attributes, etc. Furthermore, as interceptors can throw 'FlowExceptions', interceptors can have an effect on the flow. They can overrule the command (perform method) and redirect to another view or do an arbitrairy redirect right away. This behaviour can be used to work with multi page forms coupled to one command or for instance implementing a generic 'system error' type of view.