Derived Beans

What Is A Derived Bean?

A derived bean is one whose runtime class differs from the mapped property type (as determined during introspection).

Specifying The Bind Time Type

Using An Attribute To Specify Class

An easy way to specify the class to be loaded is for the class name to be specified by an xml attribute. By default, the className attribute (if present) is assumed to contain the name of the class to be loaded.

For example the following xml:

    <Animals> 
        <animal className='org.apache.commons.betwixt.io.read.FerretBean'> 
            <call>Dook</call>
            <colour>albino</colour> 
            <latinName>Mustela putoris furo</latinName>
            <name>Lector</name> 
        </animal> 
        <animal className='org.apache.commons.betwixt.io.read.CatBean'> 
            <call>Meow</call>
            <colour>black</colour> 
            <latinName>Felis catus</latinName>
            <name>Sam</name> 
        </animal> 
        <animal className='org.apache.commons.betwixt.io.read.DogBean'> 
            <breed>mongrol</breed>
            <call>Woof</call>
            <latinName>Canis familiaris</latinName> 
            <name>Bobby</name>
            <pedigree>false</pedigree> 
        </animal> 
    </Animals>

will construct objects of type FerretBean, CatBean and DogBean.

The attribute which contains the fully qualified class name can be configured through the classNameAttribute property of the BindingConfiguration.

The classname mapping is implemented by a ChainedBeanCreator. If this feature is not required, a custom bean creation chain should be used.

Mapping Derived Beans

Bind Time Type Verses Introspection Time Type

The introspection time type is the (expected) type as discovered during introspection. The bind time type is the actual type of the object found as Betwixt runs. For example, a property might have type Animal but when the getter of that property is called, the object returned might be a subclass (if Animal is a class) or an implementation (if Animal is an interface) - Cat, say. In this case, Animal would be the introspection time type but Cat the bind time type.

There are two approaches to deal with this situation: either the object can be mapped on the basis of it's bind time type (the actual class of the object) or on the basis of it's introspection time type. In the first case, all the properties present will be mapped, in the second only a subset.

For example, say that Animal has properties latinName and call and that Cat is a subclass with an additional colour property. Consider a bean with a property returning an Animal. If the introspection time type is used, only the latinName and call properties of aCat bean will be read and written whereas when bind time typing is used, all properties will be.

There are typical use cases which demonstate the need for each approach. Betwixt supports both in a flexible way, for both reading and writing but defaults to bind time typing (which is typically more intuitive).

Configuring Mapping Derivation

Whether the bind time type or the introspection time type should determine the mapping is configurable in two different ways. The MappingDerivationStrategy implementation set on the introspection configuration allows powerful but course-grained control over which types of property should have their mappings determine in which ways. Per-element control is also available through the dot betwixt document. This is typically used for more finely grained refinements. The dot betwixt settings override the strategy.

For example, the following code snippet configures an XMLIntrospector so that (unless overriden by a dot betwixt document setting), introspection time types will determine the mapping:

        XMLIntrospector xmlIntrospector = ...;
        xmlIntrospector.getConfiguration()
            .setMappingDerivationStrategy(
                MappingDerivationStrategy.USE_INTROSPECTION_TIME_TYPE);
}	

The optional mappingDerivation attribute on an <element> element. This attribute takes two enumerated values: bind and introspection. As might be expected, bind indicates that the element should use the bind time type whereas introspection indicates that the introspection time type should be used.

For example, when the following dot betwixt document is used, the pet property's mapping will be dertermined by the introsection time type mapping.

    <?xml version='1.0'?>
    <info>
        <element name='pet-record'>
            <element name='pet' property='pet' mappingDerivation='introspection'/>" +
        </element>
    </info>"
}	

Note that the mapping derivations are added together with all of the other defaults and so all elements without the mappingDerivation attribute will default to bind time typing unless and addDefaults is present.