Sample Application Guide

The XSnapshot sample application illustrates how to use XSnapshot in a typical multi-tier Java web application, and specifically, how to apply it for data binding between ActionForms and the persistent domain model using Hibernate. This document describes the architecture of the sample application and how to build/run it.

Building and running from the source distribution

  1. Create a file called "user.build.properties" in the example directory. Set the following properties, if they are not already set in ~/.ant.properties:
    • tomcat.home
    • tomcat.manager.username
    • tomcat.manager.password
    • jdbc.driver.jar
    • jdbc.username
    • jdbc.password
  2. "ant war" will build a WAR file.
  3. "ant init-db" will initialize a blank DB schema. Alternatively, "ant create-schema" will export CREATE TABLE... to a .sql file that you can run with the tool of your choice.
  4. If you have the Tomcat manager app configured, start tomcat run "ant deploy". Otherwise, you can install the WAR in Tomcat by hand; note that the WAR depends on the datasource "jdbc/xsnapshotExample".
  5. Hit http://localhost:8080/xsnapshotExample/

Installing the sample app from a binary WAR

  1. Create the tables: a SQL script for PostgreSQL is included (postgresql-schema.sql)
  2. Install the WAR using the Tomcat manager app. The WAR contains a context.xml with a datasource "jdbc/xsnapshotExample". (You can install the WAR any other way you like, so long as this datasource is created.)
  3. hit http://localhost:8080/xsnapshotExample/

Organization

Directory tree:

build/ (produced by Ant, wiped by "ant clean")
src/   (Java source; package net.sf.xsnapshot.sample)
jsp/   (JSPs and XML descriptors)

The "business" subpackage contains the service layer. This is where the business logic of the application is performed. If the application is distributed, this is the layer that will be accessed remotely as a web service.

The business layer is fairly simple, and most of the methods are just database CRUD operations and call Hibernate directly. In more complex applications, you could move the dependency on persistence to a layer of DAO objects.

The "data" subpackage contains the domain model objects. These objects contain XDoclet tags for both Hibernate and XSnapshot.

The "presentation" subpackage contains presentation layer classes. All of the Struts form beans and actions go here.

"customType" contains some data structures and BeanUtils converters.

The control flow is:

  • First, if handling a POST, Actions call XSnapshot to turn generated form beans into POJO model objects. This conversion effectively binds the ActionForm fields to POJO fields, looking up any necessary entities by ID.
  • Actions call business logic with optional POJO arguments.
  • Business logic calls Hibernate to retrieve data/domain model objects.
  • Actions shove domain objects into request scope for display; note that if there is any lazy-loading, the open session in view pattern is required.
  • If populating a new ActionForm for editing, the Action will call XSnapshot to create the ActionForm from the POJO. This binds the POJO data fields to the ActionForm.
  • The Action forwards to view layer (JSPs)

Integration with Struts

This application demonstrates using XSnapshot to generate ActionForms with data bindings to an underlying POJO domain model. The data binding is declared with the XSnapshot tags, by defining a "form" snapshot that extends ActionForm (or ValidatorActionForm, etc.)

This autogenerated class might be extended, to add a constructor to initialize nested objects (to ensure they aren't null), or to optionally add a validate/reset method. So the actual form bean class referenced from struts-config.xml may be a subclass of the generated class.

Of particular interest is date handling. Some of our objects have Date properties, which cannot be copied into the form bean verbatim the same way Strings are. Instead, we replace the Date property with a DateInputModel, which in turn has three of its own properties (year, month, day). The HTML form in the JSP uses the dotted-introspection notation to set these nested properties (e.g., <html:select property="dateOfBirth.month">). Then, when the Action that processes this form uses XSnapshot to convert the form bean snapshot back to the POJO model, a converter (declared in the @xsnapshot.property tag) will be invoked to convert DateInputModel into a Date.