Community   SpringSource   Projects    Downloads    Documentation    Forums    Training   Exchange   Blogs

Go Back   Spring Community Forums > Core Spring Projects > Core Container

Reply
 
Thread Tools Display Modes
  #1  
Old Jun 24th, 2008, 04:29 AM
Jean Jean is offline
Member
 
Join Date: Mar 2005
Location: Tokyo, Japan
Posts: 88
Default Placeholder definition problem

I have the following bit of config:

Code:
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <!-- Configurer that replaces ${...} placeholders with values from a properties file -->
    <!-- (in this case, JDBC-related settings for the dataSource definition below) -->
    <context:property-placeholder location="classpath:hibernate.properties"/>

    <!-- Local DataSource that works in any environment -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${hibernate.connection.driver_class}"/>
        <property name="jdbcUrl" value="${hibernate.connection.url}"/>
        <property name="user" value="${hibernate.connection.username}"/>
<!-- etc -->
I have the following error when starting up the application:
Code:
ContextLoader.initWebApplicationContext:215 | Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in ServletContext resource [/WEB-INF/hibernateContext.xml]: Could not resolve placeholder 'hibernate.connection.driver_class'
	at org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.processProperties(PropertyPlaceholderConfigurer.java:268)
	at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:75)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:554)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:528)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:363)
	at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
It seems the property-placeholder doesn't work anymore.
I know this looks really basic, it has always worked, but it has stopped working and I really can't figure what's wrong.

The hibernate.properties file is right in the classpath after deployment, it should find it. I have other apps using a similar config and it's working as it should.

thanks for any help.
Reply With Quote
  #2  
Old Jun 24th, 2008, 09:06 AM
Marten Deinum Marten Deinum is offline
Senior Member
 
Join Date: Jun 2006
Location: The Netherlands
Posts: 9,471
Default

Well at a first glance I would say the 'hibernate.connection.driver_class' property isn't available in your application.properties file.
__________________
Marten Deinum
  • Senior Java Consultant
  • SpringSource Certified Trainer
Conspect ICT diensten
Blog
LinkedIn
Use the [ code ] tags, young padawan
Reply With Quote
  #3  
Old Jun 24th, 2008, 09:08 PM
Jean Jean is offline
Member
 
Join Date: Mar 2005
Location: Tokyo, Japan
Posts: 88
Default

hi Martin.

The hibernate.properties is right where it should be: /WEB-INF/classes and contains all the keys I need. From the IDE, everthing seems configured correctly. It can find the resource and all the keys in it.

Thanks for being supportive anyway, I'm really lost here.

Contrary to what I've written previously, this configuration also doesn't work in another application. That make me think there's a configuration problem somewhere, and probably so obvious that I can't see it

Here is what has change recently and I thought could be the cause:

I have recently introduced Spring context files in dependency jar. This started the whole problem.
To verify that, I deleted all dependencies and import related to the new dependencies in the main application Spring contexts, but the problem persist.

I fine tuned the Spring dependencies. I re-added the complete Spring-2.5.4.jar, but same problem.

I tried the prior standard
Code:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
instead of
Code:
context:property-placeholder
, but problem remains.

I'm on the edge of creating a Web application from scratch and try to get the
Code:
context:property-placeholder
to work...
Reply With Quote
  #4  
Old Jun 26th, 2008, 01:40 AM
Jean Jean is offline
Member
 
Join Date: Mar 2005
Location: Tokyo, Japan
Posts: 88
Default and the culprit is <import resource="classpath:commonContext.xml"/>

As said, the problem started when I introduced some dependencies containing Spring contexts.

I have created a Web application project from scratch with just one applicationContext.xml, one 'datasource' bean and on test.properties in the resources.

It works as expected. As soon as I add the dependency on my commons.jar and the <import resource="classpath:commonContext.xml"/> in the applicationContext.xml, I get the 'Could not resolve placeholder' error.

I'll investigate further the commonContext.xml config (which contains placeholders as well) but it starts to sound like a bug already since the later is a quite simple context file.

-jean
Reply With Quote
  #5  
Old Jun 26th, 2008, 02:13 AM
Jean Jean is offline
Member
 
Join Date: Mar 2005
Location: Tokyo, Japan
Posts: 88
Default possible bug???

finally, I've got a reproducible scheme.

If an applicationContext.xml import another context from a dependency (for instance <import resource="classpath:commonContext.xml"/>), which in turn use a propertyConfigurer, then it won't be able to use a propertyConfigurer itself.

Single propertyConfigurer contained in the commonsContext.xml
Code:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations" value="classpath:common-mail.properties"/>
    </bean>
To me, this ought to work. If it doesn't, it means that the only way to resolve a placeholder located in a dependency context is to set it through the dependant application (provided it works, and I hope it does because that's my only way out now!).
So I would rather put that as a bug. What do you think?
Reply With Quote
  #6  
Old Jun 26th, 2008, 03:08 AM
al0 al0 is offline
Senior Member
 
Join Date: Aug 2006
Location: Now Germany, previously Ukraine
Posts: 1,509
Default

Not, it seems not to be a bug for the following reasons -

  1. contextroperty-placeholder is intended as simplified solution for easiest cases (see Spring Reference), it has severely limited configuration capabilities and is not intended for configurations with many property placeholders in context
  2. All files substitute single context and all configurerers (which are BeanFactoryPostProcessor) work context-wide, not file-wide (really, they have no knowledge about files at all - generally speaking, context need not originate from files).
  3. Situation can be quite easily resolved - I'm almost sure that if you configure in your "main" context file PropertyPlaceholderConfigurer in "old" style and specify for each configurer ignoreUnresolvablePlaceholders="true" your problem would disappear.

Regards,
Oleksandr
Quote:
Originally Posted by Jean View Post
finally, I've got a reproducible scheme.

If an applicationContext.xml import another context from a dependency (for instance <import resource="classpath:commonContext.xml"/>), which in turn use a propertyConfigurer, then it won't be able to use a propertyConfigurer itself.

Single propertyConfigurer contained in the commonsContext.xml
Code:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations" value="classpath:common-mail.properties"/>
    </bean>
To me, this ought to work. If it doesn't, it means that the only way to resolve a placeholder located in a dependency context is to set it through the dependant application (provided it works, and I hope it does because that's my only way out now!).
So I would rather put that as a bug. What do you think?
Reply With Quote
  #7  
Old Jun 27th, 2008, 01:23 AM
Jean Jean is offline
Member
 
Join Date: Mar 2005
Location: Tokyo, Japan
Posts: 88
Post

thks Oleksandr

I'm sorry I couldn't find anything related in the forum.
I wasn't aware of the PropertyPlaceholderConfigurer would be context-wide nor of the ignoreUnresolvablePlaceholders prop (it's not mentioned in the reference documentation).

ignoreUnresolvablePlaceholders=true does solve the problem.

I'm still having the problem in a particular configuration that include only one PropertyPlaceholderConfigurer in the main applicationContext.xml though.

here is a scheme of the dependencies:

Code:
main -> commons.jar
     -> commons-scheduler.jar -> commons.jar
as for the contexts:

Code:
applicationContext.xml -> commonContext.xml -> mailContext.xml
schedulerContext.xml -> commonSchedulerContext.xml -> commonContext.xml -> mailContext.xml
so only one PropertyPlaceholderConfigurer in the applicationContext.xml, meaning no possible conflict. If the schedulerContext.xml is loaded through applicationContext.xml with an <import resource="schedulerContext.xml"/>, the application fails at runtime and gives the 'Could not resolve placeholder' error. Weird isn't it?

If instead of using the import directive, I add the schedulerContext in the web.xml list of context to load, the error disappear.
Reply With Quote
  #8  
Old Jun 27th, 2008, 03:27 AM
al0 al0 is offline
Senior Member
 
Join Date: Aug 2006
Location: Now Germany, previously Ukraine
Posts: 1,509
Default

Quote:
Originally Posted by Jean View Post
I'm sorry I couldn't find anything related in the forum.
Really, PropertyPlaceholderConfigurer was discussed here dozens of times and virtually each and every aspect

Quote:
I wasn't aware of the PropertyPlaceholderConfigurer would be context-wide
It is more or less (and rather more or less) self-evedent as it works on bean definitions and not on files.

Quote:
nor
of the ignoreUnresolvablePlaceholders prop (it's not mentioned in the reference documentation).
Sure not - Spring Reference can not (and should not) list each and every property of each mentioned Spring class, for this purpose Javadoc exists.
And if you want to go above the simpliest configurations the Javadoc reading (of used classes) is a must.


Quote:
If instead of using the import directive, I add the schedulerContext in the web.xml list of context to load, the error disappear.
Really confusing - it should work identically (while listing of used context in web.xml is preferrable as it reduces dependencies between files). But hard to say more without more detailed info -are you able to produce minimal test case that demostrates the problem and post it here (e.g. as zipped attachment)?

Regards,
Oleksandr
Reply With Quote
  #9  
Old Jun 30th, 2008, 02:02 AM
Jean Jean is offline
Member
 
Join Date: Mar 2005
Location: Tokyo, Japan
Posts: 88
Default

I understand what's causing the error now.
When I only have the main applicationContext.xml loaded through web.xml and a second one, say schedulerContext.xml, loaded with an <import> directive from the main context, I was getting again the 'Could not resolve placeholder' error.
It's another PropertyPlaceholderConfigurer bean configured in the schedulerContext.xml without the property "ignoreUnresolvablePlaceholders" set to true that is causing it.
If I set "ignoreUnresolvablePlaceholders=true" in the schedulerContext.xml PropertyPlaceholderConfigurer, I don't have the 'Could not resolve placeholder' error anymore.

As stated before though, if I load all the contexts with the web.xml and remove <import> directives, it works as well.

This is still a weird behavior. I'd be able to post a minimal web app reproducing the pb in a short time if you need.

Generally speaking, I end up setting "ignoreUnresolvablePlaceholders=true" for all PropertyPlaceholderConfigurer, whatever their "level" (dependencies or main level apps). This is a little confusing for me, I feel like I don't control the PlaceHolders correctly anymore.

What do you think about the following trick (from http://www.cwinters.com/news/display/3395): it basically is about using a different "placeholderPrefix" for each properties file. I guess the IDE would not recognize PlaceHolders anymore but it'd a very clean way to know from which properties file the PlaceHolders come from.

Code:
<bean id="appASettings"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="appA_settings.properties" />
        <property name="placeholderPrefix" value="$A{" />
    </bean>
  
    <bean id="appADataSource" 
        class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="$A{db.driver}" />
        <property name="url"             value="$A{db.url}" />
Reply With Quote
  #10  
Old Jun 30th, 2008, 02:49 AM
al0 al0 is offline
Senior Member
 
Join Date: Aug 2006
Location: Now Germany, previously Ukraine
Posts: 1,509
Default

Ok, you may use different prefix (or suffix) for each file, but I'm not sure if is is so bright idea (as each file in this case depend on some knowledge about all others, namely, that prefix is unique).

If you prefer to think out about your files as of "main" and "dependent" (while in reality they are all equal) I probably would have only one configurer (in main file only) and feed it with all property files (including files for "dependent" xml).

Regards,
Oleksandr
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -5. The time now is 09:37 PM.


Contegix provides first-class managed hosting and partial sponsorship of these forums.

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.