A decent description of the "Configuration By Exception" concept is the 
following [*]:

"Java EE 5 introduced the idea of configuration by exception (sometimes 
referred to as programming by exception or convention over configuration). This 
means, unless specified differently, the container or provider should apply the 
default rules. In other  words, having to supply a configuration is the 
exception to the rule. This allows you to write the minimum amount of code to 
get your application running, relying on the container and provider defaults."

To some extent the OFBiz framework already applied this pattern is some areas 
(you may remember when we made the entity group-name "org.ofbiz" the default 
value and then were able to remove a bunch of configuration files); however I 
see a lot of room for further apply it, starting from the ofbiz-component.xml 
files.

For example, considering the ofbiz-component.xml file in framework/example:

<ofbiz-component name="example"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
        
xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/ofbiz-component.xsd";>
    <!-- define resource loaders; most common is to use the component resource 
loader -->
    <resource-loader name="main" type="component"/>

    <!-- place the config directory on the classpath to access configuration 
files -->
    <classpath type="dir" location="config"/>
    <classpath type="dir" location="dtd"/>

    <!-- load single or multiple external libraries -->
    <classpath type="jar" location="build/lib/*"/>

    <!-- entity resources: model(s), eca(s), group, and data definitions -->
    <entity-resource type="model" reader-name="main" loader="main" 
location="entitydef/entitymodel.xml"/>
    <entity-resource type="model" reader-name="main" loader="main" 
location="entitydef/entitymodel_view.xml"/>
    <!-- <entity-resource type="eca" reader-name="main" loader="main" 
location="entitydef/eecas.xml"/> -->
    <entity-resource type="data" reader-name="seed" loader="main" 
location="data/ExampleTypeData.xml"/>
    <entity-resource type="data" reader-name="seed" loader="main" 
location="data/ExampleSecurityData.xml"/>
    <entity-resource type="data" reader-name="seed" loader="main" 
location="data/ExamplePortletData.xml"/>
    <entity-resource type="data" reader-name="seed" loader="main" 
location="data/ExamplePortalSeedData.xml"/>
    <entity-resource type="data" reader-name="seed" loader="main" 
location="data/ExampleHelpData.xml"/>
    <entity-resource type="data" reader-name="demo" loader="main" 
location="data/ExampleDemoData.xml"/>

    <!-- service resources: model(s), eca(s) and group definitions -->
    <service-resource type="model" loader="main" 
location="servicedef/services.xml"/>
    <service-resource type="eca" loader="main" location="servicedef/secas.xml"/>
    <!--
    <service-resource type="group" loader="main" 
location="servicedef/groups.xml"/>
    -->

    <test-suite loader="main" location="testdef/tests.xml"/>

    <!-- web applications; will be mounted when using the embedded container -->
    <webapp name="example"
        title="Example"
        menu-name="secondary"
        server="default-server"
        location="webapp/example"
        base-permission="OFBTOOLS,EXAMPLE"
        mount-point="/example"/>
    <webapp name="birt"
        title="BIRT"
        server="default-server"
        location="webapp/birt"
        base-permission="OFBTOOLS,WEBTOOLS"
        mount-point="/birt"
        app-bar-display="false"/>
        
</ofbiz-component>


If we assume that the "default" layout of an OFBiz component is the one used by 
the "example" component (and actually by all our components) we could simply 
have:

<ofbiz-component name="example"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
        
xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/ofbiz-component.xsd";>
    <!-- define resource loaders; most common is to use the component resource 
loader so we use it; if you want a different one then use the resource-loader 
element-->
    <!-- the following folders, if present, will be added to the classpath: 
config, dtd; use the "classpath" element with attribute type="dir" to add more 
-->
    <!-- all the jar files in the following folders, if present, will be added 
to the classpath: build/lib, lib; use the "classpath" element with attribute 
type="jar" to add more -->
    <!-- all the entity definitions files and eca definition files and group 
definition files in the folder "entitydef" will be loaded using the 
reader-name="main" and loader="main"; use the element "entity-resource" to 
specify different resources -->
    <!-- the data files in the "data" subfolders will be loaded considering the 
subfolder name as the "reader-name": for example data/seed/ will be loaded when 
seed data are loaded, data/demo will be loaded when demo data is loaded; you 
can create a new reader-name simply adding a new subfolder -->
    <!-- service definition files, eca(s) and group definitions will be loaded 
from the servicedef folder; use the service-resource element ...-->
    <!-- all the test suites in the testdef folder will be executed using the 
loader="main"; use "test-suite" to specify a different resource -->
    <test-suite loader="main" location="testdef/tests.xml"/>

    <!-- web applications; will be mounted when using the embedded container -->
    <!-- I am pretty sure we could simplify these ones as well, but at this 
point you get the idea... -->
    <webapp name="example"
        title="Example"
        menu-name="secondary"
        server="default-server"
        location="webapp/example"
        base-permission="OFBTOOLS,EXAMPLE"
        mount-point="/example"/>
    <webapp name="birt"
        title="BIRT"
        server="default-server"
        location="webapp/birt"
        base-permission="OFBTOOLS,WEBTOOLS"
        mount-point="/birt"
        app-bar-display="false"/>
</ofbiz-component>

It should be possible to create a component that uses default resource names 
and locations without the need to define the ofbiz-component.xml file; for 
special components that require non-standard configurations then the 
ofbiz-component.xml file will be used as we are doing now.

What do you think? If we start to think in this direction I am pretty sure we 
could be able to simplify a lot of the OFBiz configuration files (service 
definitions, entity definitions etc...).

Kind regards,

Jacopo


[*]: http://moon26.blogspot.com/2011/04/configuration-by-exception_13.html

Reply via email to