Spring PropertyPlaceHolder

IngoLeiking

Grünschnabel
Hi,

kurze Frage. Ist es eigentlich möglich in einer RCP Eclipse Anwendung zum Beispiel Einstellung für die DB in den PreferenceTabs einzustellen, diese aber dennoch in Spring zu verwenden um eine DS zu konfigurieren. Kann man den PropertyPlaceHolder auf PlugIn-Preferences verweisen?

Gruß,
Ingo
 
Du könntest neben dem Schreiben des Propertiesfiles halt auch die DataSource direkt manipulieren. Die wird ja durch Setter konfiguriert. Laut API ist das wohl auch durchaus explizit so gewollt.

Hierbei bietet sich ein Aspekt als Lösungsform an. So kannst du den technischen Aspekt des Umkonfigurierens aus der allgemeinen Preferences Lösung heraushalten und verhinderst so die Dependency zur "LowLevel" DataSource. Ausserdem ist es dann ein leichtes, den Aspekt zu entfernen und einfach zu sagen: "DB Änderungen? Neustart required!"

Ich denk, man muss allerdings aufpassen, dass zu der Zeit nicht noch irgendwelche Verbindungen zur DB stehen, ein ORMapper ungeschriebene Objekte im Cache hält o.ä.

Gruß
Ollie
 
Hallo,

du könntest die DS zur Laufzeit "nachkonfigurieren", ob nun implizit via Aspect oder explizit von Hand bleibt dir überlassen, das geht ganz einfach über configureBean:
Java:
getApplicationContext().getAutowireCapableBeanFactory().configureBean(existingBean, beanName)

Müsstest halt mal ausprobieren ob sich die Änderungen dann auch auf verwender der DS auswirken (Hibernate SessionFactory etc.)
Afaik fragen die verwender die DS nach Connections. Wenn sich dort nun die Werte ändern liefert der Aufruf zu getConnection() beim nächsten mal eben ne andere Connection. Könnte aber sein, dass das beim afterPropertiesSet() auf die Nase fliegt... muss man eben ausprobieren.

Gruß Tom
 
Hi,

zunächst mal danke für die schnellen Antworten.

Gut, ich wusste gar das man die Beans direkt zur Laufzeit so verändern kann. Wieder was dazu gelernt...

Diese Änderungen werden jedoch nicht in den Spring-Konfig-Files persitiert oder? Sprich, beim Start der Anwendung/ Plugins müsste man immer die Properties der mit Spring konfigurierten Bean modifizieren, richtig? Zum Beispiel also im Activator? Jedoch ist hier eventuell Hibernate schon initialisiert, oder? Wann/ Wo sollte man also eurer Meinung nach die Props der DS überschreiben?

Ein Neustart der Anwendung, nachdem die Properties geändert wurden, sollte aber auf keinen Fall stören.

Gruß,

Ingo
 
Ich seh nicht mehr ganz durch.

Ausgangspunkt: du konfigurierst deine Datasource über einen PPC der das File database.properties irgendwo im classpath nutzt.

Die einfache Variante: lass deine Konfiguationsdialog einfach die Propertiesdatei neu schreiben und den Benutzer danach die Anwendung neu starten.

Die schönere Variante:siehe oben + du schreibst einen Aspekt, der eine Referenz auf die DataSource injected bekommt und nach dem erfolgreichen Schreiben der Konfiguration einfach die Setter auf der DataSource mit den neuen Werten ruft. Damit ist das Ding umkonfiguriert und getConnection() liefert die neue Verbindung zurück.

Den Umweg über die Springkonfiguration halte ich für Overdose, da so Konfigurationswissen in die Sourcen gelangt, die eigentlich nur in Spring Konfigurationsdateien liegen sollten.

REINHAUN!
 
Hi,

okay jetzt blick ich nicht mehr so ganz durch. ;-)

Bisher sieht es so aus:

In der Spring-Config stehen die DB Einstellungen direkt bei den DS Properties. Noch keine Verwendung von PlaceHoldern. Diese DS ist derzeit über AspectJ in die einzelnen Daos injeziert (CTW wie im Tutorial von Thomas. Danke nochmal hierfür. :) ).
Somit hat der Anwender derzeit keine Chance die Connection zu ändern. Frage ist also: Was ist der beste Weg dies zu erlauben?

Bei den Eclipse-Preference-Dialogen eines Pligins wird eine properties Datei von Eclipse erstellt,die kann jedoch nicht in Spring über PropertyPlaceHoldern herangezogen werden, oder? Wenn ja wie? Oder wie kann ich Eclipse dazu bewegen bestimmte Daten in eine Extra properties Datei zu schreiben. Nur von Hand? Dies wäre zumindest eine Möglichkeit...

Sorry, bin noch neu in der Thematik RCP, AspectJ & Spring...

Gruß und Danke,

Ingo
 
Ok, Danke,

dann werde ich zunächst erst mal das Versuchen. Ich denke mal das die Properties-File nicht im Bundle selbst sein muss, ich die PropertyFileLocation auch über "file:" angeben kann...

Schön wäre es dann halt wenn ich diese PropertyFile dann direkt über die Eclipse Preferences API modifizieren könnte und nicht selber über die commons configuration API schreiben muss...aber wenn es nicht anders gehen sollte....

Danke nochmals, Gruß,

Ingo
 
Schön wäre es dann halt wenn ich diese PropertyFile dann direkt über die Eclipse Preferences API modifizieren könnte und nicht selber über die commons configuration API schreiben muss...aber wenn es nicht anders gehen sollte....

Wenn das Eclipse RCP sowas anbietet umso besser. Bin da nicht so zu hause. Muss dann halt nur schauen, wie du dem PPC diese Location mitgeben kannst.

Gruß
Ollie
 
Hallo,

hier mal just 4 fun ein Beispiel, wie man Property Files programmatisch zur Laufzeit ändern und die Änderung gegenüber Spring propagieren kann


Java:
/**
 * 
 */
package de.tutorials;

import org.springframework.beans.factory.InitializingBean;

/**
 * @author Thomas.Darimont
 *
 */
public class DomainObject implements InitializingBean{
	String property;

	public String getProperty() {
		return property;
	}

	public void setProperty(String property) {
		this.property = property;
	}
	
	@Override
	public String toString() {
		return super.toString() + " " + this.property;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("init " + this);
	}
}

Java:
/**
 * 
 */
package de.tutorials;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Properties;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/**
 * @author Thomas.Darimont
 * 
 */
public class OnTheFlyPropertyPlaceHolderConfigurerExample {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		ApplicationContext applicationContext = new FileSystemXmlApplicationContext(
				"config/config.xml");

		DomainObject domainObject = (DomainObject) applicationContext
				.getBean(DomainObject.class.getName());
		System.out.println(domainObject);

		String propertyFileLocation = "config/config.properties";

		Properties properties = new Properties();
		properties.load(new FileInputStream(propertyFileLocation));
		properties.setProperty("propertyValue", "gugu");
		OutputStream outputStream = new FileOutputStream(propertyFileLocation);
		properties.store(outputStream, null);
		outputStream.close();

		
		System.out.println("refresh...");
		((ConfigurableApplicationContext) applicationContext).refresh();

		System.out.println("configure bean...");
		applicationContext.getAutowireCapableBeanFactory().configureBean(
				domainObject, DomainObject.class.getName());

		System.out.println(domainObject);

	}
}

config.xml
XML:
<?xml version="1.0" encoding="UTF-8"?>
<!--
  - Middle tier application context definition for the image database.
  -->
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">


    <context:property-placeholder location="config/config.properties"/>

    <bean class="de.tutorials.DomainObject"    >
        <property name="property" value="${propertyValue}"/>
    </bean>
                
</beans>

config.properties
Code:
propertyValue=bubu

Ausgabe:
Code:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.FileSystemXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
init de.tutorials.DomainObject@a352a5 bubu
de.tutorials.DomainObject@a352a5 bubu
refresh...
init de.tutorials.DomainObject@c7b00c gugu
configure bean...
init de.tutorials.DomainObject@a352a5 gugu
de.tutorials.DomainObject@a352a5 gugu

nach dem Lauf steht im properties File nur noch:
Code:
#Mon Mar 10 12:52:20 CET 2008
propertyValue=gugu

Das ist aber nur ein proof of concept... mitten im Betrieb einfach so refresh() am Context aufzurufen und die PPC BeanFactoryPostProcessors wieder laufen zu lassen bringt weitere Seiteneffekte mit sich...

Gruß Tom
 
Zuletzt bearbeitet von einem Moderator:

Neue Beiträge

Zurück