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 ;-)

Donnerstag, 2. April 2009

jQuery – Thickbox : Dialog Öffnen aus einem Dialog per HTTP POST

jQuery Thickbox unterstütz primär das Dialoghandling per HTTP GET. Dies ist auch verständlich, da die API ja aus der Slideshow Ecke kommt, bei der in der Regel neue Bilder per a href angefordert werden und in einer Dialogbox angezeigt werden.

Will man die API allerdings in einer Web Applikation zum Einsatz von web2.0 Dialogboxen (Layern) verwenden, kommt es des Öfteren vor, dass man Daten aus der Dialogbox posten möchte und anschließend eine andere Dialogbox anzeigen möchte.

Szenario:

Login Box à Link (a href) Passwort vergessen à Passwort vergessen Box à Email Adresse abfragen und and Server posten à Email mit neu generiertem Passwort verschickien à Login Box anzeigen.

Anbei der Code der auf dem Submit Button liegen muss.

$(document).ready(function() {
$("#btn_send").click(function() {
$.ajax({
type: "POST",
url: $('#rememberPasswordForm').attr('action')

                 + "?width=400",
dataType: "html",
data: $('#rememberPasswordForm').serialize(),
success: function(data){

            //set content to diabox and reinitalize thickbox
$("#TB_ajaxContent").html(data);
tb_position();
$("#TB_load").remove();
tb_init("#TB_ajaxContent a.thickbox");
$("#TB_window").css({display:"block"});
}
});
});
$(".btn_close").click(tb_remove);
});


 

Der interessante Teil ist hier die Callback Funktion (success: function(data)…). In ihr ist der Thickbox Code zum Darstellen der zurückgelieferten Seite untergebracht. Hier wird neben der Darstellung noch die Initialisierung übernommen, damit in der "neuen" Dialogbox auch die Thickbox Funktionen zur Verfügung stehen.