Chapter 35. Petclinic Sample

35.1. Introduction

Compass::Samples [petclinic] is the Spring petclinic sample powered by Compass. The main aim of the sample is to show how simple it is to add compass to an application, especially if one of the frameworks the application uses is one of the ones compass seamlessly integrates with.

Integrating compass into the petclinic sample, did not require any Java code to be written. Although several unit tests were added (good programming practice). Integration consisted of extending the Spring configuration files and writing a search and index jsp pages. The following sections will explain how integration was achieved.

The Compass petclinic sample shows how to integrate Compass with Spring and other frameworks. An important note, of course, is that Compass can be integrated with applications that do not use the Spring framework. Although Spring does make integration a bit simpler (and building applications much simpler).

35.2. Running The Sample

To run the petclinic sample, you will to install Apache Ant and have ANT_HOME/bin on your path. The following table lists the available ant targets.

Table 35.1. 

usage (also the default target)Lists all the available targets.
cleanClean all the output dirs.
buildCompile main Java sources and copy libraries.
docsCreate complete Javadoc documentation.
warfileBuild the web application archive.
setupDBInitialize the database.
testsRun the tests (a database does not have to be running).
allClean, build, docs, warfile, tests.

35.3. Data Model In Petclinic

Petclinic data model is based on POJOs (Plain Old Java Objects), including Pet, Vet, Owner, and Visit among others. The model also includes the base classes Entity (which holds the id of an entity), NamedEntity (holds a name as well), and Person (holds person information).

35.3.1. Common Meta-data (Optional)

As we explained in the Common Meta-data section, Common meta-data provides a global lookup mechanism for meta-data and alias definitions. It integrates with OSEM definitions and Gps::Jdbc mappings, externalising (and centralising) the actual semantic lookup keys that will be stored in the index. It also provides an Ant task to provides a constant Java class definitions for all the common meta-data definitions which can be used by Java application to lookup and store Compass Resource.

Defining a common meta-data definition is an optional step when integrating Compass. Though taking the time and creating one can provides valuable information and centralisation of the system (or systems) semantic definitions.

In the petclinic sample, the Common meta-data file is located in the org.compass.sample.petclinic package, and is called petclinic.cmd.xml. A fragment of it is shown here:

<?xml version="1.0"?>
<!DOCTYPE compass-core-meta-data PUBLIC
    "-//Compass/Compass Core Meta Data DTD 2.2//EN"


    <meta-data-group id="petclinic" displayName="Petclinic Meta Data">

        <description>Petclinic Meta Data</description>

        <alias id="vet" displayName="Vet">
            <description>Vet alias</description>

        <!-- ...... more alias definitions -->

        <meta-data id="birthdate" displayName="Birthdate">
            <description>The birthdate</description>
            <name format="yyyy-MM-dd">birthdate</name>

        <!-- ...... more meta-data definitions -->



The above fragment of the common meta-data definitions, declares an alias called vet and meta-data called birthdate. The birthdate meta-data example shows one of the benefits of using common meta-data. The format of the date field is defined in the meta-data, instead of defining it in every mapping of birtdate meta-data (in OSEM for example).

35.3.2. Resource Mapping

One of the features of the search engine abstraction layer is the use of Resource and Property. As well as simple and minimal Resource Mapping definitions.

Although it is not directly used, the Jdbc implementation of the data access layer uses Search Engine API, based on Resources and resource mappings (the Jdbc device of Compass::Gps can automatically generate them).

35.3.3. OSEM

One of the main features of Compass is OSEM (Object / Search Engine Mapping), and it is heavily used in the petclinic sample. OSEM maps Java objects (domain model) to the underlying search engine using simple mapping definitions.

The petclinic sample uses most of the features provided by OSEM, among them are: contract, with mappings defined for the Entity, NamedEntity, and Person (all are "abstract" domain definitions), Cyclic references are defined (for example between pet and owner), and many more. The OSEM definitions can be found at the petclinic.cpm.xml file.

35.4. Data Access In Petclinic

Petclinic provides an abstraction layer on top of the actual implementation of the data access layer. The Petclinic can use Hibernate, Apache ORB, or JDBC for database access. Compass can seamlessly integrate with each of the mentioned layers.

The main concern with the data access layer (and Compass) is to synchronise each data model change made with Compass search engine index. Compass provides integration support for indexing the data using any of the actual implementation of the data access layer.

35.4.1. Hibernate

Compass::Gps comes with the Hibernate device. The device can index the data mapped by Hibernate, and mirror any data changes made by Hibernate to the search engine index. Since we are using Hibernate with Spring, the device used is the Spring Hibernate device.

The integration uses the OSEM definitions, working with Compass object level API to interact with the underlying search engine. The spring application context bean definitions for the compass (required by the Hibernate Gps device) instance is defined with OSEM definitions and spring based transaction support. The applicationContext-hibernate.xml in the test package, and the applicationContext-hibernate.xml in the WEB-INF directory define all the required definitions to work with hibernate and compass. Note, that only the mentioned configuration has to be created in order to integrate compass to the data access layer.

35.4.2. JDBC

Compass::Gps comes with the JDBC device. The Jdbc device can connect to a database using jdbc, and based on different mappings defentions, index it's content and mirror any data changes. When using the Jdbc device, the mapping is made on the Resource level (cannot use OSEM).

It is important to understand the different options for integrating Compass for a Jdbc (or a Jdbc helper framework like Spring or iBatis) data access implementation. If the system has no domain model, than Resource level API and mapping must be used. The Jdbc device can automate most of the actions needed to index and mirror the database. If the system has a domain model (such as the petclinic sample), two options are available: working on the Resource level and again using the Jdbc device, or using OSEM definitions, and plumb Compass calls to the data access API's (i.e. save the Vet in compass when the Vet is saved to the database). In the petclinic sample, the Jdbc device option was taken in order to demonstrate the Jdbc device usage. An API level solution should be simple, especially if the system has decent and centralized data access layer (which in our case it does).

The integration uses the Jdbc Gps Device mapping definitions and works with Compass object level API to work with the search engine. The spring application context bean definitions for the compass (required by the Jdbc Gps device) instance are defined with Jdbc mapping resolvers, and Local transactions. The applicationContext-jdbc.xml in the test package, and the applicationContext-jdbc.xml in the WEB-INF directory define all the required definitions to work with jdbc and compass. Note, that only the mentioned configuration has to be created in order to integrate compass to the data access layer.

The petclinic sample using the Jdbc Gps Device and defines several Jdbc mappings to the database. Some of the mappings use the more complex Result Set mappings (for mappings that require a join operation) and some use the simple Table mapping. The mapping definitions uses the common meta-data to lookup the actual meta-data values.

Note, that an important change made to the original petclinic sample was the addition the Version column. The version column is needed for automatic data mirroring (some databases, like Oracle, provides a "version column" by default).

The Resource mapping definition are automatically generated using mapping resolvers, and compass use them.

Note, that the Jdbc support currently only works with Hsql database (since the sql queries used in the Result Set mappings use hsql functions).

35.5. Web (MVC) in Petclinic

The petclinic sample uses Spring MVC framework for web support. Compass::Spring module comes with special support for the Spring MVC framework.

The only thing required when using the Compass and Spring mvc integration is writing the view layer for the search / index operations. These are the index.jsp, search.jsp and serachResource.jsp Jstl view based files.

The index.jsp is responsible for both initiating the index operation for CompassGps (and it's controlled devices), as well as displaying the results for the index operation.

The search.jsp and the searchResource.jsp are responsible for initiating the search operation as well as displaying the results. The difference between them is the search.jsp works with OSEM enabled petclinic (when using Hibernate or Apache OJB), and the searchResource.jsp works with resource mapping and resource level petclinic (when using Jdbc).

Note, that when using Jdbc, remember to change the views.proeprties file under the WEB-INF/classes directory and have both the searchView.url and the searchResultsView.url referring to searchResource.jsp view. And when using either Hibernate or OJB, change it to point to search.jsp.