Getting Started

Probably the best way to get started is to look at some examples. Here is some simple example code that reads and writes a bean (together with some comments). It's a good place to start.

Mapping beans to XML

There are various ways of mapping beans to an XML structure. For example consider a simple bean

public class CustomerBean {
    public String getName();
    public Order[] getOrders();
    public String[] getEmailAddresses();
}

This could be mapped to XML in various ways. A couple of examples of these different ways follow.

Example 1

This example uses attributes for primitive types.

<CustomerBean name='James'>
    <order id='1'>...</order>
    <order id='2'>...</order>
    <emailAddress>jstrachan@apache.org</emailAddress>
</CustomerBean>

Example 2

This example uses elements for all properties and wraps collections in an extra element (which can be quite common in XML schemas). Also note that some element names have been changed.

<customer>
    <name>James</name>
    <orders>
        <order id='1'>...</order>
        <order id='2'>...</order>
    </orders>
    <email-addresses>
        <email-address>jstrachan@apache.org</email-address>
    </email-addresses>
</customer>    

Betwixt aims to provide a diversity of possible mappings such that the developer can choose, if they wish, how their beans appear as XML to support whatever XML encoding scheme that is desired. If no particular mapping is provided then Betwixt will create a default mapping for you. Also the customization mechanism allows you to just override the parts you want to and let Betwixt default the rest. So if you just want to rename a property in XML for a certain type, thats all you need to do. No need to hand-code what Betwixt can deduce for itself.

Customizing the mapping of a bean to XML (basic)

.betwixt files

The XMLIntrospector will look for files of the form className.betwixt on the classpath using the same ClassLoader used to load the given class and use that document to specify the mapping to XML. If this file does not exist then the default introspection rules are used. (Note that there are also various more advanced ways to vary this rule. For more details see multi mapping for more details)

The simplest possible file may just set the name of the element. e.g.

<?xml version='1.0' encoding='UTF-8' ?>
<info>
<element name='channel'/>
<addDefaults/>
</info>

The above means to use the name 'channel' for the outer most element for the given type. The <addDefaults> means to add the defaults from the introspector. This allows you to just rename a few properties then let the introspector do the rest. There is also a <hide> element which allows one or more properties to be hidden. Also note that the <element> and <attribute> tags can be nested to any kind of depth allowing whatever XML structure you wish. This can be useful if you wish to wrap collections in some arbitrary collection tags or to group properties of a bean together in some XML structure. e.g.

<?xml version='1.0' encoding='UTF-8' ?>
<info primitiveTypes='attribute'>
<hide property='something'/>
<element name='channel'/>
    <element name='customerList'>
    <element name='customer' property='customers'/>
    </element>
    <element name='foo'>
    <attribute name='qqq' property='ppp'/>
    <element name='bar' property='xyz'/>
    <addDefaults/>
</element>
</info>

Note that the .betwixt file specifies the mapping for a single bean. So, whilst you can add extra elements (as above), it can't be used to specify to names for child beans through nesting element elements.

The primitiveTypes attribute in the <info> element is optional and can be used to specify whether primitive java types (strings, numbers, dates etc) are specified as attributes or elements by default.

Finally static text can be specified using a value attribute inside an <element> or <attribute> tag. e.g. to add constant attributes such as a version label to the generated XML...

<?xml version='1.0' encoding='UTF-8' ?>
<info primitiveTypes='element'>
<element name='rss'/>
    <attribute name='version' value='0.91'/>
    <element name='channel'/>
    <addDefaults/>
</element>
</info>

The plain <addDefaults> tag adds default properties and the adders (it can find) for all the properties (both explicitly described in the .betwixt file and the default ones discovered). Usually, this is really pretty useful but sometimes more finely grained control is needed. In this case, there are two properties that can be set to given this extra control:

  • add-properties If this property is set to any value other than true the discovery of default properties will be suppressed.
  • add-adders if this property is set to any value other than true the matching of adders will be suppressed.
  • guess-name if this property is set to any value other than true the guessing of names for elements without a name attribute will be suppressed. Note that this may need to be set to false when mapping mixed collections. By default, Betwixt will guess names.

Using <addDefaults add-properties='false' add-adders='false'/> doesn't really make any sense but no error will be thrown.