Verbindungsparameter setzen mit PropertyPlaceholderConfigurer

11 views
Skip to first unread message

Sascha Schäfer

unread,
Aug 31, 2009, 6:49:14 AM8/31/09
to Spring User Group Germany
Hallo,

ich beschreibe vielleicht erstmal mein Problem im Allgemeinen.
In meinem Spring-Kontext definiere ich eine DataSource, dessen
Verbindungsparameter ich aber erst zur Laufzeit erfahre. Das heißt,
zum Zeitpunkt, an dem ich den Applicationkontext initialisiere,
bekomme ich erst die Verbindungsparameter. Also habe ich mir Gedanken
gemacht, wie ich die Verbindungsparameter zur Laufzeit in meiem
Programm setzen kann.

Dabei bin ich auf die Klasse PropertyPlaceholderConfigurer gekommen.
Ich schreiben also in meinen Springkontext folgende Zeilen:

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driverClassName}" /
>
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>

Nun versuche ich den Parameter in meinem Javacode zu setzen. Das sieht
folgendermaßen aus:

applicationContext = new ClassPathXmlApplicationContext( "spring/
dataService.xml" );
final PropertyPlaceholderConfigurer propertyPlaceholderConfigurer =
new PropertyPlaceholderConfigurer();
propertyPlaceholderConfigurer.setProperties
( connectionProperties.getConnectionProperties() );
propertyPlaceholderConfigurer.postProcessBeanFactory
( applicationContext.getBeanFactory() );

Bei Ausführung des Javacodes passiert aber nichts mit den Parametern
im Springkontext. Es kommt eine BeanCreationException mit dem Grund,
dass kein DriverClassName mit der Bezeichnung "$
{database.driverClassName}" gefunden werden kann. Was mache ich
falsch?

Das seltsame an der Geschichte ist, wenn ich statt des
ClassPathXmlApplicationContext eine XMLBeanFactory mit dem
Springkontext initialisiere, werden die Paremeter richtig gesetzt.
Allerdings benötige ich für meinen Programmablauf einen
Applicationkontext.

Ich habe im Netz erfahren, dass es sich dabei möglicherweise um einen
Bug handelt. Wenn das wirklich der Fall ist, gibt es denn dafür einen
Workaround?

Liebe Grüße
Sascha

Sascha Schäfer

unread,
Aug 31, 2009, 8:21:10 AM8/31/09
to Spring User Group Germany
Was noch zu erwähnen wäre, die Klasse ClassPathXmlApplicationContext
wirft sofort im Konstruktor eine Exception. Es kommt also gar nicht
dazu, dass der PropertyPlaceholderConfigurer aufgerufen wird. Wie kann
man denn nun verhindern, dass die DataSource sofort beim instantiieren
erzeugt wird, so dass der PropertyPlaceholderConfigurer ein Chance
hat, ausgeführt zu werden?

Liebe Grüße
Sascha

Sascha Schäfer

unread,
Aug 31, 2009, 10:12:26 AM8/31/09
to Spring User Group Germany
Ich habe gelesen, dass man mit default-lazy-init="true" im beans-
Element des Springskontext alle definierten Beans dazu bringt, erst
bei Bedarf instantiiert zu werden. Aber leider bewirkt diese
Einstellung in meinem Fall nichts. Der Exception wird weiterhin
geworfen.

Ich habe das Gefühl, dass der Grund für das sofortige Laden der Beans
darin liegt, dass ich das <tx:annotation-driven /> -Element zur
Konfiguarion meiner Transaktionen in meinen Kontext eingeführt habe.
Wenn ich das Element weglasse, dann werden nämlich meine Parameter wie
gewünscht durch den PropertyPlaceholderConfigurer gesetzt. Aber das
<tx:annotation-driven /> -Element brauche ich für meinen
Programmablauf. Hat jemand eine Idee für die Lösung meines Problems?

Liebe Grüße
Sascha

Sascha Schäfer

unread,
Sep 1, 2009, 9:45:09 AM9/1/09
to Spring User Group Germany
Kann mir denn wirklich niemand helfen? Vielleicht hat ja jemand einen
kleinen Tipp für mich? Im Moment bin ich sehr frustriert von Spring.

Grüße
Sascha

Thorsten Kamann

unread,
Sep 1, 2009, 9:50:35 AM9/1/09
to su...@googlegroups.com
Hallo Sascha,

warum muss das im Code passieren? Verwenden den doch in der Konfiguration. Das ist doch auch ziemlich praktikabel.

Viele Grüsse
Thorsten

2009/9/1 Sascha Schäfer <ders...@t-online.de>



--
Thorsten Kamann
Software-Architect, Consultant, Coaching
Germany, NRW

Business:
itemis products and solutions GmbH & Co. KG | Heinrichstraße 51 | 44536 Lünen

Rechtlicher Hinweis:
Amtsgericht Dortmund, HRA 15841
P.h.G.: Komplementär: itemis management GmbH | Amtsgericht Dortmund HRB 18939 | Geschäftsführer Jürgen Rödl

Personal:
thorste...@googlemail.com
http://www.thorsten-kamann.de/
callto://thorque

Fornax-Platform - Platform for developing MDSD-related Tools and components
http://www.fornax-platform.org/

Eberhard Wolff

unread,
Sep 1, 2009, 9:58:12 AM9/1/09
to su...@googlegroups.com
Hi,

der PropertyPlaceholderConfigurere ist ein BeanPostProcessor. Er geht
auf die *Bean Definitionen* der anderen Bean los und ändert sie. Das
geschieht bevor die anderen Beans initialisiert werden. Daher kann Dein
Code nicht funktionieren: Er wird erst nach dem Erzeugen der Beans
ausgeführt.

Ich würde entweder auf die Standard-Möglichkeiten des
PropertyPlaceholderConfigurere ausweichen (also Property Dateien oder
System Properties). Oder Du überschreibst loadProperties(Properties), so
dass es Deine eigenen Properties lädt. In jedem Fall muss der
PropertyPlaceholderConfigurer in der Spring-Konfiguration eingetragen
werden und nicht im Code erzeugt werden.

Gruß,

ich
--
Eberhard Wolff
Regional Director
SpringSource GmbH
Sitz der Gesellschaft: Uhlandstrasse 75 - D-10717 Berlin
Geschäftsführer: Steven Schuurman, Rod Johnson
Amtsgericht Charlottenburg - HRB 103773 B

http://www.springsource.com

Author, "Spring 2 - Framework für die Java Entwicklung"
http://www.spring-buch.de/

Founding Member Java Champions
https://java-champions.dev.java.net/

HiMail: eberhar...@springsource.com
Skype: ebr.wolff
Blog: http://JandIandMe.blogspot.com/



Sascha Schäfer

unread,
Sep 1, 2009, 10:27:08 AM9/1/09
to Spring User Group Germany
Hallo,

zunächst Danke für eure Anworten. Das mit dem Überschreien des
PropertyPlaceholderConfigurers wäre eine neue Möglichkeit, die ich
bisher noch nicht in Betracht gezogen habe.

Das Setzen der Verbindungsparameter für meine DataSource muss zur
Laufzeit geschehen, da ich erst zur Laufzeit die Information bekomme.
Inzwischen habe ich versucht mein Problem mit Hilfe des
PropertyOverrideConfigurers zu lösen. Ich habe innerhalb des Spring-
Kontext Standardparameter definiert. Mit dem folgendem Codeausschnitt
versuche ich, die Standardparameter zu überschreiben:

applicationContext = new ClassPathXmlApplicationContext( "spring/
dataService.xml" );

PropertyOverrideConfigurer propertyOverrideConfigurer = new
PropertyOverrideConfigurer();
propertyOverrideConfigurer.setProperties( myProperties );
propertyOverrideConfigurer.postProcessBeanFactory
( applicationContext.getBeanFactory() );

applicationContext.refresh();

Aber das hat leider nicht geholfen. Der PropertyOverrideConfigurer
läuft durch, aber meine DataSource versucht sich weiterhin zu der
Datenbank zu verbinden, die im Spring-Kontext für den Standardfall
definiert wurde. Was mache ich falsch?

Liebe Grüße
Sascha Schäfer

Eberhard Wolff

unread,
Sep 1, 2009, 10:52:30 AM9/1/09
to su...@googlegroups.com
Hallo,


On 01.09.09 16:27 "Sascha Schäfer" <ders...@t-online.de> wrote:

>
> Hallo,
>
> zunächst Danke für eure Anworten. Das mit dem Überschreien des
> PropertyPlaceholderConfigurers wäre eine neue Möglichkeit, die ich
> bisher noch nicht in Betracht gezogen habe.

Das ist der einzige Weg, der funktionieren wird.

> Das Setzen der Verbindungsparameter für meine DataSource muss zur
> Laufzeit geschehen, da ich erst zur Laufzeit die Information bekomme.
> Inzwischen habe ich versucht mein Problem mit Hilfe des
> PropertyOverrideConfigurers zu lösen. Ich habe innerhalb des Spring-
> Kontext Standardparameter definiert. Mit dem folgendem Codeausschnitt
> versuche ich, die Standardparameter zu überschreiben:
>
> applicationContext = new ClassPathXmlApplicationContext( "spring/
> dataService.xml" );
>
> PropertyOverrideConfigurer propertyOverrideConfigurer = new
> PropertyOverrideConfigurer();
> propertyOverrideConfigurer.setProperties( myProperties );
> propertyOverrideConfigurer.postProcessBeanFactory
> ( applicationContext.getBeanFactory() );
>
> applicationContext.refresh();
>
> Aber das hat leider nicht geholfen. Der PropertyOverrideConfigurer
> läuft durch, aber meine DataSource versucht sich weiterhin zu der
> Datenbank zu verbinden, die im Spring-Kontext für den Standardfall
> definiert wurde. Was mache ich falsch?

Der PropertyOverrideConfigurer ist ebenfalls ein BeanFactoryPostProcessor
und kann nicht funktionieren, wenn die Beans schon instanziiert sind.

Gruß,

Eberhard


--
Eberhard Wolff
Regional Director
SpringSource GmbH
Sitz der Gesellschaft: Uhlandstrasse 75 - D-10717 Berlin
Geschäftsführer: Steven Schuurman, Rod Johnson
Amtsgericht Charlottenburg - HRB 103773 B

http://www.springsource.com

Author, "Spring 2 - Framework für die Java Entwicklung"
http://www.spring-buch.de/

Founding Member Java Champions
https://java-champions.dev.java.net/

Mail: eberhar...@springsource.com


Skype: ebr.wolff
Blog: http://JandIandMe.blogspot.com/

Mailing List: http://www.springsource.com/newsletter


Sascha Schäfer

unread,
Sep 2, 2009, 2:33:02 AM9/2/09
to Spring User Group Germany
Hallo,

in einem anderen Forum habe ich eine andere Lösung gefunden. Ich habe
den BeanFactoryPostProcessor anscheinend nur falsch angewendet. Mit
folgendem Code läuft mein Programm:

applicationContext = new ClassPathXmlApplicationContext( "spring/
dataService.xml" );
PropertyOverrideConfigurer propertyOverrideConfigurer = new
PropertyOverrideConfigurer();
propertyOverrideConfigurer.setProperties( myProperties );
applicationContext.addBeanFactoryPostProcessor
( propertyOverrideConfigurer );
applicationContext.refresh();

Nun werden die Standardwerte überschrieben und bei Aufrufen der
DataSource werden die überschriebenen Parameter benutzt.

Liebe Grüße
Sascha

Eberhard Wolff

unread,
Sep 2, 2009, 3:00:04 AM9/2/09
to Spring User Group Germany, Sascha Schäfer
Hi,
nur werden Deine Beans nun beim Erzeugen des ApplicationContext erzeugt und beim refresh() weggeworfen und dann neu erzeugt. Bau eine Subklasse von PropertyPlaceholderConfigurer oder eben PropertyOverrideConfigurer und füge sie in die XML-Konfiguration ein.
Gruß,
Eberhard

Sascha Schäfer

unread,
Sep 2, 2009, 3:15:21 AM9/2/09
to Spring User Group Germany
Hallo,

betrachtet man die Performance scheint deine Lösung besser zu sein.
Ich werde das mal probieren.

Liebe Grüße
Sascha
Reply all
Reply to author
Forward
0 new messages