Compass is built using a layered architecture. Applications interacts with the underlying Search Engine through three main Compass interfaces: Compass, CompassSession and CompassTransaction. These interfaces hide the implementation details of Compass Search Engine abstraction layer.
Compass provide access to search engine management functionality and CompassSession's for managing data within the Search Engine. It is created using CompassConfiguration (loads configuration and mappings files). When Compass is created, it will either join an existing index or create a new one if none is available. After this, an application will use Compass to obtain a CompassSession in order to start managing the data with the Search Engine. Compass is a heavyweight object, usually created at application startup and shared within an application for CompassSession creation.
CompassSession as the name suggests, represents a working lightweight session within Compass (it is non thread safe). With a CompassSession, applications can save and retrieve any searchable data (declared in Compass mapping files) from the Search Engine. Applications work with CompassSession at either the Object level or Compass Resource level to save and retrieve data. In order to work with Objects within Compass, they must be specified using either OSEM or XSEM (with XSEM XmlObject). In order to work with Resources, they must be specified using RSEM (Resource can still be used with OSEM/RSEM to display search results, since Objects/Xml end up being converted to Resources). Compass will then retrieve the declared searchable data from the Object automatically when saving Objects within Compass. When querying the Search Engine, Compass provides a CompassHits interface which one can use to work with the search engine results (getting scores, resources and mapped objects).
CompassTransaction, retrieved from the CompassSession and is used to manage transactions within Compass. You can configure Compass Core to use either local transactions or JTA synchronization. Note, that unlike JDBC, automatic transaction registration will not happen, so we strongly recommend using the CompassTransaction abstraction for easy (configuration based) replacement of the transaction strategy.
After so many words, lets see a code snippet that shows the usage of the main compass interfaces:
CompassConfiguration conf = new CompassConfiguration().configure().addClass(Author.class); Compass compass = conf.buildCompass(); CompassSession session = compass.openSession(); CompassTransaction tx = null; try { tx = session.beginTransaction(); ... session.save(author); CompassHits hits = session.find("jack london"); Author a = (Author) hits.data(0); Resource r = hits.resource(0); ... tx.commit(); } catch (CompassException ce) { if (tx != null) tx.rollback(); } finally { session.close(); }
Compass::Core Compass interface manages the creation of CompassSession using the openSession() method. When beginTransaction() is called on the CompassTransaction, the session is bound to the created transaction (JTA, Spring or Local) and used throughout the life-cycle of the transaction. It means that if an additional session is opened within the current transaction, the originating session will be returned by the openSession() method.
When using the openSession method, Compass will automatically try and join an already running outer transaction. An outer transaction can be an already running local Compass transaction, a JTA transaction, or a Spring managed transaction. If Compass manages to join an existing outer transaction, the application does not need to call CompassSession#beginTransaction() or use CompassTransaction to manage the transaction (since it is already managed). This allows to simplify the usage of Compass within managed environments (CMT or Spring) where a transaction is already in progress by not requiring explicit Compass code to manage a Compass transaction.
Compass also provides a simple implementation of the template design pattern, using the CompassTemplate and the CompassCallback classes. Using it, one does not have to worry about the Compass session or transaction handling. The CompassTemplate provides all the session operations, except that they are transactional (a new session is opened and a new transaction is created and committed when calling them). It also provides the execute method, which accepts a callback class (usually an anonymous inner class), to execute within it operations that are wrapped within the same transaction.
An example of using the template is provided:
CompassConfiguration conf = new CompassConfiguration().configure().addClass(Author.class); Compass compass = conf.buildCompass(); CompassTemplate template = new CompassTemplate(compass); template.save(author); // open a session, transaction, and closes both Author a = (Author) template.execute(new CompassCallback() { public Object doInCompass(CompassSession session) { // all the actions here are within the same session // and transaction session.save(author); CompassHits hits = session.find("london"); ... return session.load(id); } });