Properties und Umgebungsvariablen in der Spring Konfiguration nutzen

veröffentlicht am 18. März 2012

Häufig möchte man Anwendungseinstellungen in einer Konfigurationsdatei zusammenfassen oder über Umgebungsvariablen beziehen. Spring bietet hierfür den PropertySourcesPlaceholderConfigurer (löst ab Spring 3.1 den PropertyPlaceholderConfigurer ab), mit dem sich Platzhalter in der Spring Konfiguration ersetzen lassen, und den PropertyOverrideConfigurer, mit dem vorbelegte Standardeinstellungen überschrieben werden können.

Für dieses Beispiel wird folgende Klasse verwendet, die mit Spring konfiguriert werden soll:

package de.patrickgotthard.example;

public class ExampleBean {

	private String hostname;
	private String username;
	private String password;
	private String userHome;

	public String getHostname() {return hostname;}
	public void setHostname(String hostname) {this.hostname = hostname;}

	public String getUsername() {return username;}
	public void setUsername(String username) {this.username = username;}

	public String getPassword() {return password;}
	public void setPassword(String password) {this.password = password;}

	public String getUserHome() {return userHome;}
	public void setUserHome(String userHome) {this.userHome = userHome;}

}

Zum Testen der Funktionalität kommt diese Klasse zum Einsatz:

package de.patrickgotthard.example;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {

		// Construct the spring application context
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

		// Register hook to shutdown Spring gracefully
		// See http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-factory-shutdown
		context.registerShutdownHook();

		ExampleBean bean = (ExampleBean) context.getBean("exampleBean");

		System.out.println(bean.getHostname());
		System.out.println(bean.getUsername());
		System.out.println(bean.getPassword());
		System.out.println(bean.getUserHome());
	}

}

PropertySourcesPlaceholderConfigurer

Zunächst wird der PropertySourcesPlaceholderConfigurer beleuchtet, mit dem sich Platzhalter ersetzen lassen. Die entsprechende Spring Konfiguration sieht wie folgt aus:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

	<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
		<property name="location" value="classpath:application.properties" />
	</bean>

	<bean id="exampleBean" class="de.patrickgotthard.example.ExampleBean">
		<property name="hostname" value="${hostname}" />
		<property name="username" value="${username}" />
		<property name="password" value="${password}" />
		<property name="userHome" value="${user.home}" />
	</bean>

</beans>

Zum Testen habe ich folgendes in die application.properties eingetragen:

username=admin
password=s3cr3t

Wie man sieht, sind die Platzhalter hostname und user.home nicht in der Properties Datei enthalten. user.home ist eine automatisch von der JVM gesetzte Umgebungsvariable und verweist auf das Benutzerverzeichnis des ausführenden Benutzers. hostname hingegen wird beim Starten der Anwendung manuell als Startparameter angegeben (-Dhostname=localhost). Beim Ausführen der Anwendung wird erwartungsgemäß folgendes auf der Konsole ausgegeben (lediglich das Benutzerverzeichnis sollte bei euch abweichen):

test
Patrick
s3cr3t
C:UsersPatrick

PropertyOverrideConfigurer

Als nächstes zeige ich euch den PropertyOverrideConfigurer. Er kommt dann zum Einsatz, wenn man Standardeinstellungen vorgeben will, die jedoch optional überschrieben werden sollen. Die entsprechende Spring Konfiguration sieht wie folgt aus:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

	<bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
		<property name="location" value="classpath:application.properties" />
	</bean>

	<bean id="exampleBean" class="de.patrickgotthard.example.ExampleBean">
		<property name="hostname" value="localhost" />
		<property name="username" value="root" />
		<property name="password" value="s3cret" />
		<property name="userHome" value="${user.home}" />
	</bean>

</beans>

In der application.properties stehen diesmal nur Werte für username und password. Beim Einsatz des PropertyOverrideConfigurer müssen die Parameter in der Form BeanID.Property=Value angegeben werden:

exampleBean.username=anotherUser
exampleBean.password=anotherS3cr3t

Bei der Ausführung des Programms wird nun folgendes ausgegeben:

localhost
anotherUser
anotherS3cr3t
${user.home}

Wie man sieht, wurde für hostname der Standardwert ausgegeben. username und password wurden hingegen wie erwartet überschrieben. Allerdings wurde nun die Umgebungsvariable user.home nicht aufgelöst. Die Lösung für dieses Problem findet ihr im nächsten Absatz.

Platzhalter mit dem PropertyOverrideConfigurer nutzen

Beim Einsatz des PropertyOverrideConfigurers wird die Ersetzung von Platzhaltern in der Spring Konfiguration deaktiviert. Manchmal ist man jedoch darauf angewiesen, dass sowohl der PropertyOverrideConfigurer verwendet wird, als auch die Platzhalter ersetzt werden. Die Lösung für dieses Problem besteht darin, sowohl den PropertySourcesPlaceholderConfigurer als auch den PropertyOverrideConfigurer zu verwenden.

Das folgende Beispiel demonstriert eine Lösung für folgendes Problem:

In der Spring Konfiguration werden Standardeinstellungen für die Anwendung eingetragen. Liegt jedoch eine Konfigurationsdatei für die Anwendung im Benutzerverzeichnis vor, sollen die darin definierten Einstellungen überschrieben werden.

Die Spring Konfiguration für diesen Anwendungsfall sieht wie folgt aus:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

	<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer" />

	<bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
		<property name="location" value="file:///${user.home}/application.properties" />
		<property name="ignoreResourceNotFound" value="true" />
	</bean>

	<bean id="exampleBean" class="de.patrickgotthard.example.ExampleBean">
		<property name="hostname" value="localhost" />
		<property name="username" value="username" />
		<property name="password" value="password" />
		<property name="userHome" value="${user.home}" />
	</bean>

</beans>

Beim PropertyOverrideConfigurer wird nun der Dateipfad ${user.home}/application.properties angegeben. Existiert diese Datei nicht, soll das Programm dennoch funktionsfähig sein, weshalb die Option ignoreResourceNotFound auf true gesetzt wird. Startet man die Anwendung nun ohne vorliegende application.properties, erscheint folgende Konsolenausgabe:

localhost
username
password
C:UsersPatrick

Nun legst du folgende application.properties in deinem Benutzerverzeichnis an:

exampleBean.username=anotherUser
exampleBean.password=anotherS3cr3t

Beim erneuten Ausführen der Anwendung, werden die definierten Parameter ersetzt und folgende Ausgabe erscheint in der Konsole:

localhost
anotherUser
anotherS3cr3t
C:UsersPatrick

Diese Konfiguration habe ich zum Beispiel einmal verwendet, um eine Embedded Derby Datenbank zu verwenden, wenn der Benutzer keine Konfiguration angegeben hat. Es bestand jedoch auch die Möglichkeit, die Konfigurationsdatei anzulegen und dort Verbindungsdaten für eine PostgreSQL oder MySQL Datenbank anzugeben.

Quellen und weiterführende Links

Hinterlasse einen Kommentar