This is a short guide to quickly getting started with using XSnapshot. We quickly resnapshot the basic purpose and philosophy of xsnapshot, and then describe how to quickly start using it in a project. For more in depth discussion of the more advanced features refer to the User Guide (incomplete).
XSnapshot is a tool for generating snapshot classes based on javabean domain classes (which we call model classes). It allows you to specify which properties of the domain classes to include in snapshot classes, and to specify various transformations to apply to them. XSnapshot will then generate the snapshot classes, as well as helper classes that perform the conversions between snapshots and models. Finally XSnapshot includes a set of classes to help in configuring it at runtime and performing the conversions.
There are four basic steps to using xsnapshot:
XSnapshot is a module for XDoclet, which lets you do code generation based on javadoc-like tags you add to your source classes. Thus the first step in using XSnapshot is adding the appropriate tags to your model classes that will drive the generation of the snapshot classes and helpers.
XSnapshot tags fall into two categories: class-level tags and property-level tags. Class-level tags are used to declare the snapshot classes defined for a model class. Property-level tags then specify properties to be included in each snapshot, and how the conversion should happen.
Please refer to the Tags Guide for detailed information on all the tags and attributes available for marking up your classes.
Now that you have added xsnapshot tags to your model classes, you need to add targets to your ant build script that will generate the snapshot and helper classes and the registry configuration file.
First, define a classpath that will be used by the xsnapshotdoclet task. this needs to include all the standard xdoclet jars, the xsnapshot jar, all of your model classes, as well as any jars containing any classes referenced from your model classes, if these classes are pertinent to the xsnapshot definitions (for example, if one of your model classes extends a class which comes from an external jar, that needs to be part of the classpath). for example:
<path id="xsnapshotdoclet.classpath"> <fileset dir="${jar.repository.dir}" includes="${xsnapshot-module.jar}"/> <fileset dir="${xdoclet.home}/lib"> <include name="*.jar"/> </fileset> <pathelement location="${j2ee.dir}/lib/j2ee.jar"/> <pathelement location="${ant.home}/lib/ant.jar"/> </path>
Next, add the target to generate the xsnapshots. Here is a sample target:
<target name="generate-xsnapshots" description="Builds xsnapshots files, if necessary" depends="-setup"> <taskdef name="xsnapshotdoclet" classname="com.vecna.xsnapshot.ant.XSnapshotDocletTask" classpathref="xsnapshot.classpath"/> <xsnapshotdoclet destdir="${build.generated-src.dir}" verbose="true" mergedir="${xdoclet.merge.dir}"> <fileset dir="${src.dir}" includes="${persistent.package}/**/*.java"/> <packageSubstitution packages="${persistent.subpackage}" substituteWith="${snapshots.subpackage}"/> <snapshot/> <helper/> </xsnapshotdoclet> <xsnapshotdoclet destdir="${build.config.dir}" verbose="true" mergedir="${xdoclet.merge.dir}"> <fileset dir="${src.dir}" includes="${persistent.package}/**/*.java"/> <packageSubstitution packages="${persistent.subpackage}" substituteWith="${snapshots.subpackage}"/> <properties/> </xsnapshotdoclet>
The first line defines the xsnapshot doclet task, using the classpath defined before.
The xsnapshotdoclet task defines three subtasks, <snapshot/>
, <helper/>
, and <properties/>
to generate the snapshots, helpers and the configuration file respectively. because you
will generally want the output from the former two to go to a different
place than the latter, you will need to run xsnapshotdoclet twice. Best practice is to have
the <snapshot/>
and <helper/>
output classes to a generated-src directory somewhere under
your build directory. The above example shows the two executions of <xsnapshotdoclet/>
.
Mergedir refers to the directory where xsnapshot will look for merge files.the
<fileset/>
element specifies the classes on which to run xsnapshot.
the <packageSubstitution/>
element allows you to define an automatic package replacement
that should take place when xsnapshot encounters non fully qualified classnames. Normally,
xsnapshot qualifies them, with the package of the class in which they are found; the package
substitution modifies that.
Next, you should add the generated-src directory where xsnapshotdoclet generates the snapshots and helpers to the set of source files for your compile task, and add the runtime xsnapshot jar file to the classpath used for compiling. Also make sure that the generated configuration file is assembled into a place where it can be read at context initialization. see the section below on the latter.
The XSnapshotRegistry class is the runtime representation of xsnapshot configuration, such as which helpers are to be used for which snapshots. Thus, your web application needs to create and initialize an instance of XSnapshotRegistry, and then make it accessible to code that will be converting models to snapshots, and vice versa.
XSnapshot provides several options for performing the configuration.
XSnapshotContextLoader
class in com.vecna.xsnapshot.web
. This is the simplest method.
Simply register this class as a listener in web.xml, then add a init-param with the name
xsnapshot.properties that points to the location of the confiration file. XSnapshotContextLoader
will create and initialize an instance of XSnapshotRegistry
and store a reference to it in XSnapshotRegistrySingleton
. See the javadoc XSnapshotContextLoader
for more detailes.
XSnapshotPropertiesConfigurator
class in com.vecna.xsnapshot.cfg
. This class contains a static
method to configure an existing instance of XSnapshotRegistry
based on configuration contained
in an instance of org.apache.commons.configuration.Configuration
. XSnapshotContextLoader
ultimately delegates
to this.
XSnapshotRegistryFactoryBean
in
com.vecna.xsnapshot.spring
makes it easy to configure and make available an instance of XSnapshotRegistry
through a Spring application context. See the Spring Integration HOWTO for details.
the final step in using XSnapshot is adding code to your business methods to convert
between snapshots and models. XSnapshotUtils
is the facade class that business methods should
use to do this - they should NEVER refer to helper classes explicitly.
XSnapshotUtils
can be used in two ways - it has a set of static methods that take an instance
of XSnapshotRegistry
as an argument, and you can also create an instance of it passing it an
XSnapshotRegistry
and then use instance methods. If you wish to use the singleton pattern for the registry,
there is also the XSnapshotSingletonUtils
class which simply is a wrapper for XViewUtils
that uses the registry held by XSnapshotRegistrySingleton
.
See the JavaDoc for XSnapshotUtils
for detailed
descriptions of the methods.
Note that the code in the helpers generated by xsnapshot for converting snapshots to models only copies over a very limited subset of the properties. To fully convert the snapshot to the model, you need to write additional code which properly copies over the rest of the properties. There are two ways to do this:
copyIntoModel
method, and copy over the rest of the properties. Then make sure to
register these helpers with XSnapshotRegistry. This is easiest to do when integrating
XSnapshot with Spring.