XmlSnapshotService
Allows an XML document to be generated capturing the data of a root entity and specified related entities.
An XSD schema (to which the XML will be compatible) can also be generated.
This XML/XSD can be used for various purposes, such as mail merge/reporting, or adhoc auditing.
The service offers a basic API to create a snapshot of a single object, and a more flexible API that allows the size of the graph to be customized.
API
interface XmlSnapshotService {
XmlSnapshotService.Snapshot snapshotFor(Object domainObject) (1)
XmlSnapshotService.Snapshot.Builder builderFor(Object domainObject) (2)
T getChildElementValue(Element el, String tagname, Class<T> expectedCls) (3)
}
1 | snapshotFor(Object)
Exports the state of a domain object into a Snapshot (which can then be converted into XML, for example). |
2 | builderFor(Object)
Creates a Snapshot.Builder that allows the contents of the snapshot to include other related state. |
3 | getChildElementValue(Element, String, Class)
Convenience method to extract value of an XML element, based on its type. |
Members
Implementation
The framework provides a default implementation of this service, o.a.c.core.runtimeservices.xmlsnapshot.XmlSnapshotServiceDefault
.
Usage
The most straight-forward usage of this service is simply:
XmlSnapshot snapshot = xmlsnapshotService.snapshotFor(customer);
Element customerAsXml = snapshot.getXmlElement();
This will return an XML (document) element that contains the names and values of each of the customer’s value properties, along with the titles of reference properties, and also the number of items in collections.
As well as obtaining the XML snapshot, it is also possible to obtain an XSD schema that the XML snapshot conforms to.
XmlSnapshot snapshot = ...;
Element customerAsXml = snapshot.getXmlElement();
Element customerXsd = snapshot.getXsdElement();
This can be useful for some tools. For example, Altova Stylevision can use the XML and XSD to transform into reports. Please note that this link does not imply endorsement (nor even a recommendation that this is a good design).
Builder API
The contents of the snapshot can be adjusted by including "paths" to other references or collections. To do this, the builder is used. The API for this is:
public interface XmlSnapshotService {
...
public interface Builder {
void includePath(final String path);
void includePathAndAnnotation(String path, String annotation);
XmlSnapshotService.Snapshot build();
}
@Programmatic
public XmlSnapshotService.Builder builderFor(Object domainObject);
}
We start by obtaining a builder:
XmlSnapshot.Builder builder = xmlsnapshotService.builderFor(customer);
Suppose now that we want the snapshot to also include details of the customer’s address, where address
in this case is a reference property to an instance of the Address
class.
We can "walk-the-graph" by including these references within the builder.
builder.includePath("address");
We could then go further and include details of every order in the customer’s orders
collection, and details of every product of every order:
builder.includePath("orders/product");
When all paths are included, then the builder can build the snapshot:
XmlSnapshot snapshot = builder.build();
Element customerAsXml = snapshot.getXmlElement();
All of this can be strung together in a fluent API:
Element customerAsXml = xmlsnapshotService.builderFor(customer)
.includePath("address")
.includePath("orders/product")
.build()
.getXmlElement();
As you might imagine, the resultant XML document can get quite large very quickly with only a few "include"s.
If an XSD schema is beng generated (using |
Automatic inclusions
If the domain object being snapshotted implements the SnapshottableWithInclusions
interace, then this moves the responsibility for determining what is included within the snapshot from the caller to the snapshottable object itself:
public interface SnapshottableWithInclusions extends Snapshottable {
List<String> snapshotInclusions();
}
If necessary, both approaches can be combined.
As an alternative to using One reason for doing this is to provide a stable API between the domain model and whatever it is that might be consuming the XML. With a view model you can refactor the domain entities but still preserve a view model such that the XML is the same. |
See Also
-
provides a mechanism for obtaining a string representations of a single domain object.
-
is a simple wrapper around standard JAXB functionality for generating both XMLs and XSDs from JAXB-annotated classes.
Note that there is built-in support for JAXB classes (ie annotated with @XmlRootElement) to be used as view models.