Pluggability

Waffle was designed to provide default functionality that should be suitable for most any application. However in order to provide complete flexibility Waffle allows its foundational components to be over-written with custom implementations. As an example Waffle uses Ognl for data binding properties from a users request to the actions. It is easy to plug-in your own org.codehaus.waffle.bind.ControllerDataBinder by adding the following to the applications web.xml:

Similarly, to configure the servlet monitor to output to console:
Note:
The context param-name must match the fully qualified interface class name to override the default implementation that is automatically registered. On other hand, if want to register your own custom components you can use any key, prefixed by "register:". See below for more details.

The param-name defines the interface of the component to be over-written and the param-value represents the implementing class. The following table lists the components that can currently be customized in Waffle (excluding Monitors):

Interface Default Implementation
org.codehaus.waffle.action.ActionMethodExecutor org.codehaus.waffle.action.InterceptingActionMethodExecutor
org.codehaus.waffle.action.ActionMethodResponseHandler org.codehaus.waffle.action.DefaultActionMethodResponseHandler
org.codehaus.waffle.action.ArgumentResolver org.codehaus.waffle.action.HierarchicalArgumentResolver
org.codehaus.waffle.action.MethodDefinitionFinder org.codehaus.waffle.action.AnnotatedMethodDefinitionFinder
org.codehaus.waffle.action.MethodNameResolver org.codehaus.waffle.action.RequestParameterMethodNameResolver
org.codehaus.waffle.bind.BindErrorMessageResolver org.codehaus.waffle.bind.ognl.OgnlBindErrorMessageResolver
org.codehaus.waffle.bind.ControllerDataBinder org.codehaus.waffle.bind.ognl.OgnlControllerDataBinder
org.codehaus.waffle.bind.ViewDataBinder org.codehaus.waffle.bind.IntrospectingViewDataBinder
org.codehaus.waffle.bind.ValueConverterFinder org.codehaus.waffle.bind.ognl.OgnlValueConverterFinder
org.codehaus.waffle.context.ContextContainerFactory org.codehaus.waffle.context.PicoContextContainerFactory
org.codehaus.waffle.controller.ControllerDefinitionFactory org.codehaus.waffle.controller.ContextControllerDefinitionFactory
org.codehaus.waffle.controller.ControllerNameResolver org.codehaus.waffle.controller.ContextPathControllerNameResolver
org.codehaus.waffle.i18n.MessageResources org.codehaus.waffle.i18n.DefaultMessageResources
org.codehaus.waffle.validation.Validator org.codehaus.waffle.validation.DefaultValidator
org.codehaus.waffle.view.ViewDispatcher org.codehaus.waffle.view.DefaultViewDispatcher
org.codehaus.waffle.view.ViewResolver org.codehaus.waffle.view.DefaultViewResolver

Most application will never need to deal with any of these components. But it is nice to know that you can change any of the default behaviour if you so desire.

Custom components

Waffle also allows you to plug-in your own custom components which don't need to extend or implement any Waffle components. This is easy to do by adding context-param's to your web.xml file. Notice the register: prefix in the param-name node below. When Waffle runs across such context-param it will register it for use in your application. You can also use the prefix registerNonCaching: for those components that should be instantiated new each time.

For a more concrete example Waffle defines the interface org.codehaus.waffle.bind.ValueConverter. Implementations of this interface allows you to write custom conversions for a specific class type. The following is an example of how you can register your converters with Waffle. Waffle's DefaultValueConverterFinder is dependent on all org.codehaus.waffle.bind.ValueConverter that are registered in the web.xml. So the following example will provide 2 custom converters for use in your application.

Note:
Everything registered with Waffle must be registered under a unique name. The interface name should be used when over-writing default or providing unique behaviour.