EQUIP2 WebApp Defining the Dataspace
Chris Greenhalgh, 2007-01-30
Introduction
After creating a skeleton web application (in a suitable source
repository) and specifying the applicaiton (first version, at least),
the first EQUIP2-specific job is to define the Dataspace, in particular
to
- define the Data classes (Java Bean) to be used.
- update the build and database configuration accordingly.
- customise the database web forms interface to suit.
Defining the Data Classes
EQUIP2 can be viewed as (in part) an Object database. In a Web
application the Hibernate-based dataspace implementation is normally
used, so that the object dataspace is backed by a relational database
(using Hibernate's Object to Relational mapping capabilities). Normally
each class that may be persisted in the dataspace is defined using a
simple XML schema, and XLST transformations are then used to generate a
corresponding Java Bean, EQUIP2 helper class and Hibernate mapping file.
This is documented in the core EQUIP2 document Simple_Bean_Generator.html
For this tutorial application, from the specification EQUIP2_WebApp_Tutorial_Application_Specification.html
three Data classes are required:
Note that:
- each class is defined in a single XML file,
- each class corresponds to a single table in the database
- inheritance is NOT yet supported in EQUIP2
- Bean properties are defined by <property> elements
- Documentation provided in <description>
elements is copied through to form JavaDoc comments in the generated
files
- Type aliases can be introduced using the <type> element; this is
only really used for length-qualified types (strings).
- Constant values can be defined by <constant> elements;
these generate class static final fields.
- Java 1.5 enumerations are NOT currently supported - use int types
and constants.
- Class names must be fully qualified with their package (include java.lang.)
- There is support for using java.util.Date (mapping to SQL
datetime), but often the resolution is only 1s.
- If a primitive column is to be nullable then the Java boxed type
should be specified (e.g. java.lang.Integer
rather than int).
- For properties which contain IDs of other objects in the database
(foreign references) using a name of the form somethingClassnameID will allow
the web database forms to automatically handle the reference (e.g. the
Topic's reference to the Player who created it is called 'creatorPlayerID').
Updating the Build
See also EQUIP2_WebApp_Configuring_and_Building.html
Generating Data Classes and Support
The 'generate' target
of the project build.xml must be edited to
generate the Java Beans, EQUIP2 helper classes and Hibernate mapping
files for the specified data classes, e.g.
<java fork="true" classname="equip2.tools.j2se.xsltTransform" failonerror="true">
<classpath refid="classpath_tools"/>
<arg value="${equip2home}/etc/bean2java.xsl"/>
<arg value="etc/equip2.webapptutorial.db.Player.xml"/>
<arg value="${generated}/equip2/webapptutorial/db/Player.java"/>
<arg value="${equip2home}/etc/bean2javahelper.xsl"/>
<arg value="etc/equip2.webapptutorial.db.Player.xml"/>
<arg value="${generated}/equip2/webapptutorial/db/Player_helper.java"/>
<arg value="${equip2home}/etc/bean2hibernatehbm.xsl"/>
<arg value="etc/equip2.webapptutorial.db.Player.xml"/>
<arg value="${generated}/equip2/webapptutorial/db/Player.hbm.xml"/>
</java>
When the application is rebuilt (in particular the generate target) then the
generated files should be output under generated/,
e.g. for Player:
Configuring Hibernate
The main Hibernate configuration file, etc/hibernate.cfg.xml, must be
edited to include the generate Hibernate mapping files, e.g.:
<mapping resource="equip2/webapptutorial/db/Player.hbm.xml"/>
<mapping resource="equip2/webapptutorial/db/Topic.hbm.xml"/>
<mapping resource="equip2/webapptutorial/db/Comment.hbm.xml"/>
If the web application is now rebuilt and deployed Hibernate, at
startup, should add the corresponding tables (player, topic and comment, as specified in the
Bean XML files) to the database; use a standard database client to
check (e.g. "list tables;",
"describe table player;")
Customising the Web Form interface
In order to use the standard web form interface effectively some
data-class-specific configuration is required; this is done in the
webform configuration JSP webapp/WEB-INF/jsp/db/configuration.jsp.
The various facilities of the standard EQUIP2 database interface
forms are described in EQUIP2_WebApp_Standard_Dataspace_Web_Interface.html
Minimal Customisation
At the minimum the classes to be shown in the web form must be
specified:
_allClassNames = new String[] {
// all class names to appear on forms go here
"equip2.webapptutorial.db.Player",
"equip2.webapptutorial.db.Topic",
"equip2.webapptutorial.db.Comment"
};
The various class index pages should now give access to those
classes in the database; try http://.../equip2tutorial/db/class_index.htm
Note that with further configuration, below, it is possible to set a
default package name, so that they can appear as just 'Player', 'Topic' and 'Comment'.
JSP Customisation
The database forms for adding and editing individual objects in the
dataspace can be significantly further customised in configuration.jsp,
in particular to:
- specify which properties should be shown it class list views (_listProperties: Map<String(classname),String[](propertyname)>),
e.g. Player shows ID, name, status, role:
_listProperties.put(equip2.webapptutorial.db.Player.class.getName(),
new String[] { "ID", "name", "status", "role" });
- how to group and order properties on add/edit object forms (_propertyGroups, Map<String(classname),PropertyGroupBean[](propertygroups)>)
- whether any properties should be read-only on the object editor
forms (_fixedProperties, Map<String(classname),String[](propertynames)>)
- which related (linked) classes should be listed at the bottom of
an object view form, i.e. classes which contain objects which may have
a reference back to the currently viewed object (_linkedClasses, Map<String(classname),LinkedClassBean[](linkedclasses)>),
e.g. Players are referred to Topics (creatorPlayerID) (in this case
to appear sorted by dateCreated):
_linkedClasses.put(equip2.webapptutorial.db.Player.class.getName(),
new LinkedClassBean[] {
new
LinkedClassBean(equip2.webapptutorial.db.Topic.class.getName(),
"creatorPlayerID",
true,
"dateCreated", false)
});
- which (if any) properties are set-valued (_setValuedProperties)
- which properties are (integer) enumerations, and what the textual
form for each value is (_enumProperties,
Map<String(classname),Map<String(propertyname),EnumTypeBean[](enumvalues)>>),
e.g. Player status, player status, one of NEW, ACTIVE, BANNED or LEFT:
EnumTypeBean [] playerStatusEnum = new
EnumTypeBean[] {
new
EnumTypeBean(0, "STATUS_NEW"),
new EnumTypeBean(1,
"STATUS_ACTIVE"),
new EnumTypeBean(2,
"STATUS_BANNED"),
new
EnumTypeBean(3, "STATUS_LEFT") };
map = new
HashMap();
map.put("status", playerStatusEnum);
_enumProperties.put(equip2.webapptutorial.db.Player.class.getName(),
map);
- which properties are bit-mapped values, and what the bits means (_bitFlagProperties)
- alternative names for properties to show in view/edit forms (_niceNames, Map<String(classname),Map<String(propertyname),String(displayname)>>),
e.g. Player dateJoined and dateStatusChange to be shown as 'Date
Joined' and 'Date status last changed':
_niceNames.put(equip2.webapptutorial.db.Player.class.getName(),
makeMap2(new
String[] {"dateJoined","Date Joined",
"dateStatusChange","Date status
last changed"
}));
- alternative names for properties to show in instance lists (_niceListHeadings, as for _niceNames)
- maximum string length constraints for properties (_maxLengthProperties, Map<String(classname),Map<String(propertyname),String(length)>>),
e.g. Topic title might be limited in web form to 100 chars:
_maxLengthProperties.put(equip2.webapptutorial.db.Topic.class.getName(),
makeMap2(new String[] { "title", "100" }));
Spring Component Configuration
Further configuration is possible of the Java Controllers that underly
the database forms interface. This is done in the Spring db servlet
configuration, WEB-INF/db-servlet.xml:
(see also EQUIP2_WebApp_Configuring_and_Building.html)
- several controllers allow a default package name to be specified
to be used if classes are specified without package, e.g.:
<property
name="defaultPackageName"><value>equip2.webapptutorial.db</value></property>
- if classes have properties which refer to other classes but do
not have the standard form somethingClassnameID
then this can be specified by the linkedObjectProperties
property of the genViewController
bean.
- if CSV download is being used then the order of property headings
can be specified and the descriptive text to output using the dbViewController bean's classPropertiesInOrder and classPropertyDescriptions
properties.
- if CSV upload is being used, the auto-guessing of uploaded CSV
file class can be tailored by specifying the classFirstLines property of the
dbCsvUploadController
bean.
The web forms can also be configured to automatically allocate new
(internally unique) IDs to objects that are added in the web forms with
no ID specified; this is configured in WEB-INF/applicationContext.xml,
via the idAllocations
property of the dbIdAllocator
bean, e.g. in this application we wish to have Player IDs of the form
'P123':
<bean id="dbIdAllocator" class="equip2.spring.DbGenericIDAllocator">
...
<property name="idAllocations">
<map>
<entry key="equip2.webapptutorial.db.Player">
<bean class="equip2.spring.IDAllocationBean">
<property name="fixedPrefix" value="P"/>
</bean>
</entry>
...
Changes
2007-01-30