loading table of contents...

4.2.1. Defining Data Views

Data views are defined declaratively using XML according to a schema /META-INF/dataviews.xsd which is located inside cae-contentbeanservices-api.jar. Behind the scenes, subclasses of the application classes are generated. This process is transparent, as the remainder of the application should be written to the application class interfaces. Looking at a data view object’s class, however, it becomes obvious that it is actually an instance of a subclass of the original business class. How these classes behave, will be described later.

A sample XML data view definition using the example from above looks as follows:

<dataview appliesTo=”com.company.PageImpl”>
  <property name=”name”/>
  <property name=”description”/>
  <property name=”content”/>
  <property name=”parent” associationType=”composition”>
    <dataview appliesTo=”com.company.PageImpl” name=”forLinking”>
      <property name=”name”/>
    </dataview>
  </property>
</dataview>

This definition says: The default (no name attribute) data view of a PageImpl materializes the properties name, description, content and parent as fields where the latter is itself a bean of type PageImpl with data view forLinking (which is defined inline) applied. The association between the two data views is a composition. That means: the outer object embeds its private parent instance which is not shared with other beans, that is, the outer element owns the inner element exclusively. Specifically, no cache lookup is performed to retrieve the inner element, but it is always created when the outer element is created. The various association types will be described later.

This data view defines a view on Page documents that makes the following properties cached and quickly accessible:

  • page.{name,description,content,parent}

  • page.parent.name

All other properties are inherited from your *Impl classes and are therefore accessed dynamically. That does not mean that they are necessarily slow (there is a document cache after all).

To use the defined data views, the data view factory dynamically constructs two subclasses of PageImpl, one for each data view definition. When the default data view is loaded, the data view factory will look into the cache with a key <Page content bean, null (default)> (Remember that the Page content bean’s equality is defined in terms of its content id). If the key is not in the cache, the factory will create an instance of the first subclass and load the properties description, content and name by invoking the business methods and storing the results. Furthermore, it will load parent (another lightweight PageImpl) and construct data view forLinking for it. To do so, it will not do a cache lookup but instantiate the corresponding second subclass of PageImpl directly. The result is stored as the materialized parent property of the result.

The generated code for the definition from above is roughly equivalent to the following:

class PageImpl$$ extends PageImpl {
  String name = super.getName();
  ...
  PageImpl parent =
   (PageImpl)dataviewFactory.lookupUncached(
        super.getParent(), “forLinking”);

  ...
  Page getParent() {
    return this.parent;
  }
  ...
}

It is possible to define data views with the same name for different classes. During the lookup for that name, the class of the object determines which data view definition is chosen – a dynamic dispatch very much like for content bean creation or the templates. This way, it is possible to apply a data view to a property value with a varying runtime class.

The default data view has a special meaning: it is the data view that is loaded at the beginning of a request when rendering the bean referenced by the URI. So this data view should correspond to the properties that the default view and its included fragment views require.