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.
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.
This example uses attributes for primitive types.
<CustomerBean name='James'> <order id='1'>...</order> <order id='2'>...</order> <emailAddress>jstrachan@apache.org</emailAddress> </CustomerBean>
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.
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.