This blog has moved to
http://blog.matthias-reining.com

Die bestehenden Artikel bleiben vorerst alle bei blogspot. Neue Artikel veröffentliche ich allerdings nur noch auf http://blog.matthias-reining.com

Dienstag, 28. April 2009

Hibernate Search indexBase Directory – relativer Pfad zum WebContainer

Wenn man den Hibernate Search Index im FileSystem ablegt (FSDirectoryProvider) wird dieser typischer Weise in der persistence.xml definiert (bei der Verwendung von JPA). Hier kann man allerdings nur einen relativen Pfad zum Index -Verzeichnis aus dem die Java Anwendung gestartet wurde angeben (bspw. TOMCAT_HOME$/bin) oder man gibt einen absoluten Pfad an.

Nachdem die persistence.xml im Normalfall Bestandteil der ausgelieferten Applikation ist, kommt ein absoluter Pfad eigentlich nicht in Frage (typisches Szenario: Entwicklung unter Windows - C:\app\luceneIdx; Livedeployment unter Linux - /usr/locale/app/luceneIdx).

Ein relativer Pfad ist allerdings auch nicht unbedingt schön - /usr/share/jboss/jboss-4.2.3GA/bin/luceneIdx…

Schön wäre meiner Meinung nach ein relativer Pfad zum AppServer wobei die Definition hierbei im Sourcecode liegt (XML Konfiguration gibt es wirklich schon zu genüge…)

Anbei einige Möglichkeiten den Pfad für Hibernate Search zu definieren:

Relativer Eintrag in der persistence.xml

<property name="hibernate.search.default.indexBase" value="luceneIdx" />

Nachteil: siehe Einleitung

Startparameter

-Dhibernate.search.default.indexBase=D:/luceneIdx

Beim Start der VM kann auch der Index angegeben werden; Hibernate Search verwendet dann diesen. So kann für jede Umgebung (Windows, Linux) ein absolutes Verzeichnis definiert

JBoss SystemProperties MBean

   <mbean code="org.jboss.varia.property.SystemPropertiesService"

        name="jboss.util:type=Service,name=SystemProperties">

    <!-- Load properties from each of the given comma separated URLs -->

    <attribute name="URLList">

        ./conf/lucene.properties

    </attribute>

   </mbean>

Lucene.properties

hibernate.search.default.indexBase=D:/luceneIdx3

Die Definition des Hibernate Search Index Directory findet nun in einem Property File statt (angesprochen über den JBoss System Properties MBean), dass für jede Serverumgebung unteschiedlich sein kann. Die Konfiguration liegt in der Applikation, das Property File kann auf jedem Server unterschiedlich sein.

Eigener DirectoryProvider

package com.nobiscum.provobis.search;

import java.io.File;
import java.util.Enumeration;
import java.util.Properties;

import org.hibernate.search.backend.configuration.MaskedProperty;
import org.hibernate.search.engine.SearchFactoryImplementor;
import org.hibernate.search.store.FSDirectoryProvider;

/**
* <p>
* This DirectoryProvider use the <i><jboss.server.data.dir>/luceneIdx</i> directory to store the
* Apache Lucene filesystem index.<br>
* For example the path looks like <i>&lt;JBOSS_HOME&gt;/server/provobis/data/luceneIdx</i>
* </p>
* <p>
* To use the FSRelativePathDirectoryProvider put following line in <code>persistence.xml</code><br>
*
* <pre>
* &lt;property name=&quot;hibernate.search.default.directory_provider&quot;
* value=&quot;com.nobiscum.provobis.search.FSRelativePathDirectoryProvider&quot; /&gt;
* </pre>
*
* </p>
*
* @author mre
* @see FSDirectoryProvider
*/
public class FSRelativePathDirectoryProvider extends FSDirectoryProvider {

@Override
public void initialize(String directoryProviderName, Properties properties,
SearchFactoryImplementor searchFactoryImplementor) {
// copy is necessary, see method description.
Properties p = copyProperties(properties);

// XXX AppServer dependency
String indexBase = System.getProperty("jboss.server.data.dir");
indexBase += File.separator + "luceneIdx";

p.put("indexBase", indexBase);
super.initialize(directoryProviderName, p, searchFactoryImplementor);
}

/**
* The <code>properties</code> parameter is not a {@link Properties} themselve, but rather a
* subclass ({@link MaskedProperty}. The {@link MaskedProperty} is read-only, less methods are
* implemented, the most throw an UnsupportedOperationException.
* <p>
* To manipulate the properties, a new <i>normal</i> {@link Properties} object is created. The
* values from the given properties are all copied into the new one.
*
* @param properties
* existing properties object
* @return new properties object, that contains all values from <code>properties</code>
*/
private Properties copyProperties(Properties properties) {
Properties newProperties = new Properties();
Enumeration<Object> keys = properties.keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
String value = properties.getProperty(key);
newProperties.put(key, value);
}
return newProperties;
}
}

Hier ist der Pfad relativ zum JBoss data Verzeichnis.

Eine schöne Lösung wie ich finde ;-)

Kommentare:

  1. Danke für die Lösungen! Suche schon länger nach einer Möglichkeit, den baseIndex "außerhalb" der App zu setzen. Wusste nicht, dass das auch via system properties funktioniert.

    Zum FSRelativePathDirectoryProvider:
    (1) Man könnte das Index-Verzeichnis (luceneIdx) auch noch via properties bestimmen, um für jede Anwendung ein eigenes Verzeichnis definieren zu können.
    (2) Ich denke, copyProperties ist nicht notwendig. Stattdessen reicht möglicherweise:
    Properties p = new Properties(properties);
    (p verwendet properties als defaults).

    AntwortenLöschen
  2. Enjoyed your approach to explaining how it works, hope to see more blog posts from you. thank you!

    Hibernate Online Training | Java Online Training


    Hibernate Training in Chennai Java Training in Chennai

    AntwortenLöschen