Writing Beans (Advanced)

Writing DynaBeans

A DynaBean is a pseudo-bean whose properties may differ between instances of the same Class. Pseudo-introspection of the available properties uses a pseudo-class of type DynaClass. For more details see BeanUtils .

Betwixt now supports the (correct) writing of objects implementing DynaBean. Rather than using standard introspection for these objects, Betwixt now interrogates the DynaClass. Using .betwixt files with DynaBeans is not yet supported. The special behaviour of DynaBean classes will be overridden when a .betwixt file is present.

Writing Entity Beans

Entity beans are a kind of Enterprise Java Bean. For more details see the J2EE specification. They are a common way to persist data. When dealing with an entity bean, you usually deal with the remote interface rather than the concrete implementation. There is no guarantee that the class presented by the container will be the class your created to provide the bean's functionality. Indeed, Proxy implementations are one common way in which the remote interfaces are implemented.

This causes some difficulties for Betwixt. Betwixt (by default) will introspect the actual implementation presented by the container. Fortunately, the normalization mechanism described here can be used to allow betwixt to introspect the actual interface (rather than the implementation).

There are two different strategies that can be used. The first is to create a special ClassNormalizer which extracts an interface from a Proxy. (Thanks to Christoph Gaffga for suggesting this.) For example:

        XMLIntrospector introspector = ...;
        introspector.setClassNormalizer( new ClassNormalizer() {
                public Class normalize( Class clazz ) {
                    if ( Proxy.isProxyClass(clazz) && clazz.getInterfaces().length >0 ) {
                        return clazz.getInterfaces()[0];
                    }
                    return clazz;
                }
            });

Of course, this will only work if your J2EE implementation uses Proxy classes to implement it's Entity Beans.

The alternative is to use a ListedClassNormalizer and register all remote interfaces. For example:

        XMLIntrospector introspector = ...;
        ListedClassNormalizer classNormalizer = new ListedClassNormalizer();
        classNormalizer.addSubstitution( MyRemoteInterfaceOne.class );
        classNormalizer.addSubstitution( MyRemoteInterfaceTwo.class );
        ...
        introspector.setClassNormalizer( classNormalizer );

Suppressing The Expression Of Attributes

Sometimes there are certain values for some attributes which should result in the attribute not being expressed at all. A typical use case is the requirement for null property values to result in the absence of the mapped attributes (as opposed to their expression with an empty value).

Betwixt allows this behaviour to be customized through the setting of the ValueSuppressionStrategy property of the writer's BindingConfiguration to an appropriate ValueSuppressionStrategy implementation.

By default, Betwixt suppresses empty attributes.

Suppressing The Expression Of Elements At Bind Type

The expression of elements can be suppressed at bind time in a similar fashion. This is particularly useful when particular property values must not to expressed. This can help to prevent complete tree traversal when using tools such as Hibernate. Again, a custom ValueSuppressionStrategy implementation should be created.

Pretty Print

Pretty Printing

BeanWriter supports pretty printing. When pretty printing, extra white space will be inserted with the aim of making the xml produced more readable by humans. Pretty printing is off by default. Call enablePrettyPrint to switch it on. For example:

    BeanWriter writer = ...
    ...
    writer.enablePrettyPrinting();

Setting Initial Indent

Pretty printing indents elements so that the xml can be read more easily. The number of indentations for the root element defaults to one. Some users may prefer this to start at zero. This value is configurable through the initialIndentLevel property of BeanWriter. For example

    BeanWriter writer = ...
    ...
    writer.setInitialIndentLevel(0);