There are a couple of lifecycle events that are important in Jofti. For the IndexManager these are the init() and destroy methods used to control overall start-up and shutdown, and for the individual index it is the destroy() or remove() method that is used to shutdown the individual indexes.
The IndexManager is not mandated to be used as a singleton and accordingly has no getInstance() method equivalent. Instantiation of the manager, which is used to control access to the indexes it manages, is through the creation of new instance and its initialisation.
The init() method comes in two forms, one that takes no parameters to initialise the manager with no configuration and one that takes a configuration file, either in a filename or an inputStream.
So we can initialise the manager as shown below:
Or:IndexManager manager = new IndexManagerImpl(); manager.init();
IndexManager manager = new IndexManagerImpl();
manager.init("config-file.xml");
Irrespective of which method you use to start the manager, you can still use the programmatic methods for adding caches at a later stage.
The destroy() method for the IndexManager will stop the manager and attempt to destroy all the indexes registered with the manager. Note: this will attempt to shutdown the actual Caches as well - so if you are using an external cache that you do not want to shutdown, you must call remove() for this index first.
The individual Indexes do not have initialisation methods, that process is taken care of inside the manager when it itself initialises or the Index is added programmatically. However, the Indexes do have both a remove() and destroy() method. The difference between these two methods is that the remove only de-registers and clears the Index assocaited with the Cache, whereas the destroy() will attempt to shutdown the Cache instance and the Index.
Once either of these methods have been invoked you cannot continue to use the Index, and an attempt to do so will cause an Exception to be thrown.
The values objects that you place into a Cache can either be treated as mutable or immutable by Jofti. If you keep a reference to an Object that is put into the cache and change a property of that Object without putting the object back into the cache you can receive a false positive result. This is because Jofti will be unaware that the field now has a different value so the index will match but the value in the Cache will not.
To prevent this happening you have to configure the Cache adapter to check for mutable objects. If you only READ Objects and do not alter them then you can safely not have to use this setting. By default the setting is false - so it will NOT check for mutability.
For example:
// set up the test class
Contained contained = new Contained();
contained.setContainedField("test");
// add it into the cache
index.put("testContained", contained);
// try and retrieve it
Map results = index.query(
new MatchQuery( "com.test.NestedTestClass",
"contained.containedField","test"));
// now change the contained field
contained.setContainedField("other);
results = index.query(
new MatchQuery( "com.test.NestedTestClass",
"contained.containedField","test"));
Jofti will still return 1 result as matching your query as the Contained object did have this property at time of indexing.
In order to solve this Jofti has a configuration setting for each adaptor called "mutable-values". Setting this to true will cause Jofti to check the objects retrieved from the Cache against the indexed values, any fields that have changed will cause the object not to be returned from the search. /
However, you will still not be able to search for the new value until you call "put" again into the cache with the changed Object. It seems more suitable to allow the developers control of when a Mutable value is re-indexed by explicitly calling put rather than a search having a side-effect of re-indexing the object.
Be aware that the mutability checking does have a performance overhead on searching. However, if you do keep references to Objects in the cache and are likely to change attributes directly it is advisable to turn this feature on.
This can be achieved in the following manner:
Using the config file:
[?xml version="1.0"?]
[!DOCTYPE cache-config SYSTEM "cache-config.dtd"]
<indexes>
<!-- An instance of an index -->
<index name="test" init-method="init" destroy-method="destroy">
<!-- The type of index to use -->
<type>
com.jofti.tree.TreeIndex
</type>
<!-- The type of parser to use -->
<parser>
com.jofti.introspect.JavaBeanClassIntrospector
</parser>
<!-- The cache to use -->
<cache>
<!-- The adapter for this particular index -->
<adapter init-method="init" destroy-method="destroy">
<type>
com.jofti.cache.adapter.EhCacheAdapter
<type>
<!-- The configuration properties for
the cache implemetation -->
<init-properties>
<property name="file">
cache-configs/ehcache.xml
</property>
<property name="mutable-values">
true
</property>
</init-properties>
</adapter>
</cache>
<!--
Classes to be indexed
-->
<classes>
<class name="com.test.TestClass">
<property>privateField</property>
</class>
<class name="com.test.TestClass">
<property>contained.containedField</property>
</class>
</classes>
</index>
</indexes>
To achieve the same with the configuration object we would write:
DefaultIndexConfig config = new DefaultIndexConfig();
List simpleProperties = new ArrayList();
simpleProperties.add("privateField");
config.addMapping("com.test.SimpleTestClass",
simpleProperties);
Properties props = new Properties();
props.setProperty("mutable-values","true");
config.setAdapterProperties(props);
Index index = (Index)manager.addIndexedCache(config,new HashMap());
Jofti has ben written with other easy to use developer frameworks in mind. So the configuration for Jofti supports the dependency injection model used by frameworks such as Spring. Indeed, the whole application can be configured directly using Spring so Jofti can easily be plugged into existing projects.
For example:
<bean id="indexManager" class="com.jofti.manager.IndexManagerImpl"
init-method="init" destroy-method="destroy" >
<property name="configFile">
<value>index-config.xml</value>
</property>
</bean>
The above spring-beans.xml fragment shows how to configure the IndexManager with a configuration file.
You can also manually configure the Bean using the configuration object as shown in the earlier setting up the Index without configuration examples. (just translate the setters used in the examples to bean properties.)