Index: /trunk/grails-app/conf/BootStrap.groovy
===================================================================
--- /trunk/grails-app/conf/BootStrap.groovy	(revision 621)
+++ /trunk/grails-app/conf/BootStrap.groovy	(revision 622)
@@ -16,5 +16,5 @@
                 createDataService.createBaseData()
                 createDataService.createDemoData()
-                createDataService.startLucene()
+                createDataService.startSearchableIndex()
             }
             test {
@@ -22,5 +22,5 @@
                 createDataService.ensureSystemAndAdminAccess()
                 createDataService.createBaseData()
-                createDataService.startLucene(false)
+                createDataService.startSearchableIndex(false)
             }
             production {
@@ -28,5 +28,5 @@
                 createDataService.ensureSystemAndAdminAccess()
                 createDataService.createBaseData()
-                createDataService.startLucene()
+                createDataService.startSearchableIndex()
             }
         }
Index: /trunk/grails-app/conf/Config.groovy
===================================================================
--- /trunk/grails-app/conf/Config.groovy	(revision 621)
+++ /trunk/grails-app/conf/Config.groovy	(revision 622)
@@ -49,4 +49,20 @@
 grails.spring.bean.packages = []
 
+/**
+* Internal searchable index config.
+*/
+// Is set true by createDataService.startSearchableIndex() once bootstrap completes.
+appSearchable.cascadeOnUpdate = false
+
+/**
+* Directory configuration.
+* Pickup the Tomcat/Catalina directory else use the target or current dir.
+*/
+def fs = File.separator // Local variable.
+globalDirs.targetDir = new File("target${fs}").isDirectory() ? "target${fs}" : ''
+globalDirs.catalinaBase = System.properties.getProperty('catalina.base')
+globalDirs.logDirectory = globalDirs.catalinaBase ? "${globalDirs.catalinaBase}${fs}logs${fs}" : globalDirs.targetDir
+globalDirs.workDirectory = globalDirs.catalinaBase ? "${globalDirs.catalinaBase}${fs}work${fs}" : globalDirs.targetDir
+globalDirs.searchableIndexDirectory = "${globalDirs.workDirectory}SearchableIndex${fs}${appName}${fs}"
 
 /**
@@ -58,8 +74,4 @@
  * Basic log levels are ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
  */
-// Pickup the Tomcat/Catalina work directory else use the current or temp dir.
-def catalinaBase = System.properties.getProperty('catalina.base')
-def fs = File.separator
-def logDirectory = catalinaBase ? "${catalinaBase}${fs}logs${fs}" : ''
 
 log4j = {
@@ -73,5 +85,5 @@
         // Custom log file.
         rollingFile name:"appLog",
-                        file:"${logDirectory}${appName}.log".toString(),
+                        file:"${globalDirs.logDirectory}${appName}.log".toString(),
                         maxFileSize:'300kB',
                         maxBackupIndex:1,
@@ -99,6 +111,8 @@
     error 'grails.app.service.NavigationService'
     error 'grails.app.service.com.zeddware.grails.plugins.filterpane.FilterService'
+    info 'org.codehaus.groovy.grails.plugins.searchable'
+    //info 'org.compass'
     error 'grails.app.task' // Quartz jobs.
-    info 'grails.app.task.InventoryReindexJob'
+    info 'grails.app.task.InventoryIndexJob'
 
     // Move anything that should behave differently into this section.
Index: /trunk/grails-app/conf/Searchable.groovy
===================================================================
--- /trunk/grails-app/conf/Searchable.groovy	(revision 621)
+++ /trunk/grails-app/conf/Searchable.groovy	(revision 622)
@@ -1,2 +1,4 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
 /**
  * This {@link groovy.util.ConfigObject} script provides Grails Searchable Plugin configuration.
@@ -26,16 +28,11 @@
 
     /**
-     * The location of the Compass index
-     *
-     * Examples: "/home/app/compassindex", "ram://app-index" or null to use the default
-     *
-     * The default is "${user.home}/.grails/projects/${app.name}/searchable-index/${grails.env}"
-     */
-    // Pickup the Tomcat/Catalina work directory else use the current or temp dir.
-    def catalinaBase = System.properties.getProperty('catalina.base')
-    def fs = File.separator
-    def indexDirectory = catalinaBase ? "${catalinaBase}${fs}work${fs}Lucene${fs}" : "Lucene${fs}"
-
-    compassConnection = new File("${indexDirectory}${appName}").absolutePath
+    * The location of the Compass index
+    *
+    * Examples: "/home/app/compassindex", "ram://app-index" or null to use the default
+    *
+    * The default is "${user.home}/.grails/projects/${app.name}/searchable-index/${grails.env}"
+    */
+    compassConnection = new File(ConfigurationHolder.config.globalDirs.searchableIndexDirectory).absolutePath
 
     /**
Index: /trunk/grails-app/controllers/AppCoreController.groovy
===================================================================
--- /trunk/grails-app/controllers/AppCoreController.groovy	(revision 621)
+++ /trunk/grails-app/controllers/AppCoreController.groovy	(revision 622)
@@ -253,13 +253,11 @@
 
     /**
-    * Rebuild the lucene text search index.
+    * Rebuild the text search index.
     */
     @Secured(['ROLE_AppAdmin', 'ROLE_Manager'])
     def rebuildTextSearchIndex = {
-        log.info "Rebuilding lucene text search index."
-        searchableService.reindex()
-        log.info "Rebuilding lucene text search index, complete."
-
-        flash.message = g.message(code:"default.update.success", args:["Index ", ''])
+        InventoryIndexJob.triggerNow(['calledBy':'AppCoreController rebuildTextSearchIndex{}'])
+
+        flash.message = g.message(code:"appCore.rebuild.text.search.index")
         redirect(action: manager)
     }
Index: /trunk/grails-app/domain/Asset.groovy
===================================================================
--- /trunk/grails-app/domain/Asset.groovy	(revision 621)
+++ /trunk/grails-app/domain/Asset.groovy	(revision 622)
@@ -1,2 +1,4 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
 class Asset {
 
@@ -35,4 +37,14 @@
     }
 
+    def afterUpdate = {
+        // Update the Inventory searchable index, since cascading in searchable-0.5.5 is broken.
+        if(ConfigurationHolder.config.appSearchable.cascadeOnUpdate) {
+            try {
+                InventoryIndexJob.triggerNow(['calledBy':'Asset afterUpdate{}'])
+            }
+            catch(e) {log.error e}
+        } // if
+    } // afterUpdate
+
     //  This additional setter is used to convert the checkBoxList string or string array
     //  of ids selected to the corresponding domain objects.
Index: /trunk/grails-app/domain/InventoryGroup.groovy
===================================================================
--- /trunk/grails-app/domain/InventoryGroup.groovy	(revision 621)
+++ /trunk/grails-app/domain/InventoryGroup.groovy	(revision 622)
@@ -1,2 +1,4 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
 class InventoryGroup {
     String name
@@ -18,3 +20,13 @@
     }
 
+    def afterUpdate = {
+        // Update the Inventory searchable index, since cascading in searchable-0.5.5 is broken.
+        if(ConfigurationHolder.config.appSearchable.cascadeOnUpdate) {
+            try {
+                InventoryIndexJob.triggerNow(['calledBy':'InventoryGroup afterUpdate{}'])
+            }
+            catch(e) {log.error e}
+        } // if
+    } // afterUpdate
+
 }
Index: /trunk/grails-app/domain/InventoryLocation.groovy
===================================================================
--- /trunk/grails-app/domain/InventoryLocation.groovy	(revision 621)
+++ /trunk/grails-app/domain/InventoryLocation.groovy	(revision 622)
@@ -1,2 +1,4 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
 class InventoryLocation {
 
@@ -22,3 +24,13 @@
     }
 
+    def afterUpdate = {
+        // Update the Inventory searchable index, since cascading in searchable-0.5.5 is broken.
+        if(ConfigurationHolder.config.appSearchable.cascadeOnUpdate) {
+            try {
+                InventoryIndexJob.triggerNow(['calledBy':'InventoryLocation afterUpdate{}'])
+            }
+            catch(e) {log.error e}
+        } // if
+    } // afterUpdate
+
 }
Index: /trunk/grails-app/i18n/messages.properties
===================================================================
--- /trunk/grails-app/i18n/messages.properties	(revision 621)
+++ /trunk/grails-app/i18n/messages.properties	(revision 622)
@@ -423,2 +423,7 @@
 report.error.no.inventory.items.found=Error: no inventory items found, please run report again.
 report.error.too.many.inventory.items=Error: over {0} inventory items, please run report again.
+
+#
+# AppCore messages.
+#
+appCore.rebuild.text.search.index=The text search index is being rebuilt in the background, see log file for details.
Index: /trunk/grails-app/jobs/InventoryIndexJob.groovy
===================================================================
--- /trunk/grails-app/jobs/InventoryIndexJob.groovy	(revision 622)
+++ /trunk/grails-app/jobs/InventoryIndexJob.groovy	(revision 622)
@@ -0,0 +1,39 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
+/**
+* Provides a quartz job that rebuilds the searchable index for the inventory search.
+* With concurrent=false the next job is blocked until the previous job completes.
+* We need a hibernate session otherwise we get a LazyInitializationException, default is true but we specify it to be sure.
+* Rebuilding the index is required since searchable components are not updated when they change, that is
+* until the parent is updated and reindexed. Cascade update is broken in searchable-0.5.5
+*/
+class InventoryIndexJob {
+
+    def concurrent = false
+    def sessionRequired = true
+
+    static triggers = {
+        // Cron fields:
+        // 'Seconds Minutes Hours DOM Month DOW Year(Optional)'
+        // See: http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html
+        // Trigger every hour on the hour:
+        //cron name: 'RebuildInventoryIndex', cronExpression: "0 0 * * * ?"
+    }
+
+    def execute(context) {
+
+        // Some information can be accessed if we run with "def execute(context) ".
+        // For more info see: http://quartz.sourceforge.net/javadoc/org/quartz/JobExecutionContext.html
+        // log.debug context.getTrigger()
+        // log.debug context.getPreviousFireTime()
+        // log.debug context.getFireTime()
+
+        // Called by.
+        def calledBy =  context.mergedJobDataMap.get('calledBy')
+        log.info "Called By: " + calledBy
+
+        // Rebuild the Inventory searchable index.
+        log.info "Calling, Inventory.index()."
+        InventoryItem.index()
+    }
+}
Index: unk/grails-app/jobs/InventoryReindexJob.groovy
===================================================================
--- /trunk/grails-app/jobs/InventoryReindexJob.groovy	(revision 621)
+++ 	(revision )
@@ -1,34 +1,0 @@
-import org.codehaus.groovy.grails.commons.*
-
-/**
-* Provides a quartz job that reindex's the Lucene index for the Inventory domain class.
-* With concurrent=false the repeat interval starts after the previous job completes.
-* We need a hibernate session otherwise we get a LazyInitializationException, default is true but we specify it to be sure.
-*/
-class InventoryReindexJob {
-
-    def concurrent = false
-    def sessionRequired = true
-
-    static triggers = {
-        // Cron fields:
-        // 'Seconds Minutes Hours DOM Month DOW Year(Optional)'
-        // See: http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html
-        // Trigger every hour on the hour:
-        cron name: 'RebuildInventoryIndex', cronExpression: "0 0 * * * ?"
-    }
-
-    def execute() {
-
-        // Some information can be accessed if we run with "def execute(context) ".
-        // For more info see: http://quartz.sourceforge.net/javadoc/org/quartz/JobExecutionContext.html
-        // log.debug context.getTrigger()
-        // log.debug context.getPreviousFireTime()
-        // log.debug context.getFireTime()
-
-        // Reindex the Inventory domain class.
-        log.info "Rebuilding Lucene index, Inventory.reindex()."
-        InventoryItem.reindex()
-        log.info "Rebuilding Lucene index, complete."
-    }
-}
Index: /trunk/grails-app/services/CreateBulkDataService.groovy
===================================================================
--- /trunk/grails-app/services/CreateBulkDataService.groovy	(revision 621)
+++ /trunk/grails-app/services/CreateBulkDataService.groovy	(revision 622)
@@ -12,4 +12,5 @@
     def dateUtilService
     def appConfigService
+    def createDataService
     def searchableService
     def assignedGroupService
@@ -43,6 +44,5 @@
             return fail(code: 'default.not.development.environment.failure')
 
-        log.info "Stop mirroring lucene index."
-        searchableService.stopMirroring()
+        createDataService.stopSearchableIndex()
 
         log.info "Creating BULK data..."
@@ -83,9 +83,5 @@
         log.info "Creating BULK data...complete."
 
-        log.info "Start mirroring Lucene index."
-        searchableService.startMirroring()
-        log.info "Rebuilding Lucene index, bulkIndex."
-        searchableService.reindex()
-        log.info "Rebuilding Lucene index, complete."
+        createDataService.startSearchableIndex()
 
         return result
@@ -107,6 +103,5 @@
             return fail(code: 'default.not.development.environment.failure')
 
-        log.info "Stop mirroring Lucene index."
-        searchableService.stopMirroring()
+        createDataService.stopSearchableIndex()
 
         log.info "Creating BULK data..."
@@ -121,9 +116,5 @@
         log.info "Creating BULK data...complete."
 
-        log.info "Start mirroring Lucene index."
-        searchableService.startMirroring()
-        log.info "Rebuilding Lucene index, bulkIndex."
-        searchableService.reindex()
-        log.info "Rebuilding Lucene index, complete."
+        createDataService.startSearchableIndex()
 
         return result
Index: /trunk/grails-app/services/CreateDataService.groovy
===================================================================
--- /trunk/grails-app/services/CreateDataService.groovy	(revision 621)
+++ /trunk/grails-app/services/CreateDataService.groovy	(revision 622)
@@ -1,2 +1,4 @@
+import org.codehaus.groovy.grails.commons.ConfigurationHolder
+
 /**
 * Provides a data service to create base and demo data.
@@ -1525,31 +1527,33 @@
 
     /**
-    * Lucene index and mirroring is disabled at startup.
-    * Us this to start Lucene indexing after creating bootstrap data.
+    * SearchableIndex and mirroring is disabled at startup.
+    * Use this to start indexing after creating bootstrap data.
     * @param indexInNewThread Whether to run the index in a new thread, defaults to true.
     */
-    def startLucene(Boolean indexInNewThread = true) {
-        log.info "Start mirroring Lucene index."
+    def startSearchableIndex(Boolean indexInNewThread = true) {
+        log.info "Start mirroring searchable index."
+        ConfigurationHolder.config.appSearchable.cascadeOnUpdate = true
         searchableService.startMirroring()
         if(indexInNewThread) {
             Thread.start {
-                log.info "Rebuilding Lucene index, bulkIndex (new thread)."
+                log.info "Rebuilding searchable index, bulkIndex (new thread)."
                 searchableService.index()
-                log.info "Rebuilding Lucene index, complete."
+                log.info "Rebuilding searchable index, complete."
             }
         }
         else {
-            log.info "Rebuilding Lucene index, bulkIndex."
+            log.info "Rebuilding searchable index, bulkIndex."
             searchableService.index()
-            log.info "Rebuilding Lucene index, complete."
+            log.info "Rebuilding searchable index, complete."
         }
     }
 
     /**
-    * Lucene index and mirroring during bulk data creation may be slow.
-    * Us this to stop lucene indexing and restart with startLucene() after data creation.
+    * Searchable index and mirroring during bulk data creation may be slow.
+    * Use this to stop indexing and restart with startSearchableIndex() after data creation.
     */
-    def stopLucene() {
-        log.info "Stop mirroring lucene index."
+    def stopSearchableIndex() {
+        log.info "Stop mirroring searchable index."
+        ConfigurationHolder.config.appSearchable.cascadeOnUpdate = false
         searchableService.stopMirroring()
     }
Index: /trunk/grails-app/views/appCore/manager.gsp
===================================================================
--- /trunk/grails-app/views/appCore/manager.gsp	(revision 621)
+++ /trunk/grails-app/views/appCore/manager.gsp	(revision 622)
@@ -80,5 +80,5 @@
                                 <g:link action="rebuildTextSearchIndex">
                                     Rebuild
-                                </g:link> - Reindex the entire text search index.
+                                </g:link> - Rebuild the text search index.
                                 <br />
                             </td>
