Announcement Announcement Module
Collapse
No announcement yet.
Spring 3M2 - @Value and PropertyPlaceholderConfigurer Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring 3M2 - @Value and PropertyPlaceholderConfigurer

    In Spring 2.5 we used a PropertyPlaceholderConfigurer to load up property files and inject the property values into beans using XML.

    We're trying to migrate to Spring 3.0 M2, and would like to use @Value to accomplish something similar. What would be the correct approach to do something similar to PropertyPlaceholderConfigurer?

    Can an @Value annotation access properties loaded by PropertyPlaceholderConfiguerer? Should we setup a separate PropertiesFactoryBean and inject from that (what's the syntax to do that?)?

    Any advice would be appreciated!
    -Jeremy

    P.S. Accidentally cross-posted this in Spring JavaConfig, but think it is more appropriate here.

  • #2
    I almost got this working. I can't find a way to reference the properties directly using EL or to reference the PropertyPlaceholderConfigurer. So we created a PropertiesFactoryBean which can be accessed via EL and used this as the source for the PropertyPlaceholderConfigerer.

    Problem #1: Difficult to access properties with dots in their name
    All of the examples of @Value show properties with no dots. So for example:
    Code:
    @Value("#{myProps.clientDir}")
    But if the property has a dot in it, this doesn't work:
    Code:
    @Value("#{myProps.client.dir}")
    After some experimenting, I finally figured out that the solution is to use this syntax:
    Code:
    @Value("#{myProps['client.dir']}")
    This is a lot more verbose than the old property configurer. I'd love if it just looked like this:
    Code:
    @Value("client.dir")
    Any validation on the best way to do this?

    Problem #2: Properties that reference other properties
    Using PropertyPlaceholderConfigurer, we used to have properties that built on other properties. Then we could change the base property at runtime and have that change cascade through other properties. Here's an example:
    Code:
    base.dir = /my/dir
    client.dir = ${base.dir}/clients
    Then we'd inject these into objects like this:
    Code:
    <property name="clientDir" value="${client.dir}"/>
    Based on my solution to Problem #1 above, when I first injected the property I set a breakpoint and saw that clientDir property was being set to "${base.dir}/clients" which means that the nested property wasn't being evaluated. So I tried updating my property values to match EL syntax:
    Code:
    base.dir = /my/dir
    client.dir = #{config['base.dir']}/clients
    This is uglier, but if it works, it works. But it doesn't work - the nested property also does not get evaluated using this approach.

    Any ideas or recommendations?

    Comment


    • #3
      Per my comment here: http://forum.springframework.org/sho...23&postcount=2, you should be able to dereference a properties object without braces, i.e:
      Code:
      #{myProps.propname}
      should work fine, instead of
      Code:
      #{myProps['propname']}
      Suggestion number one would be to get rid of the PropertiesFactoryBean usage, and go with
      Code:
      <util:properties/>
      instead.

      Again, per the response linked above, I've added a test to the Spring test suite that proves this works. Also mentioned there, in M3, you'll be able to use ${...} syntax in conjunction with PropertyPlaceholderConfiguration or <context: property-placeholder/>. This will be much more familiar to existing users, although not as dynamic as the #{...} syntax already mentioned here.

      Comment


      • #4
        Chris, please read my post a little closer as I clearly outlined my problems.

        Yes, dereferencing property "propname" works as "#{myProps.propname}" BUT dereferencing property "prop.name" does not work as "#{myProps.prop.name}".

        Also, this is the spring XML for our properties factory bean:
        Code:
            <bean id="applicationConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
                <property name="ignoreResourceNotFound" value="true"/>
                <property name="properties">
                    <props>
                        <prop key="email.override.address"></prop>
                        <prop key="email.subject.prefix"></prop>
                        <prop key="email.bcc.address"></prop>
                        <prop key="hibernate.cache.enabled">true</prop>
                        <prop key="hibernate.format.sql">false</prop>
                        <prop key="hibernate.jdbc.batch.size">20</prop>
                        <prop key="error.email.address"></prop>
                    </props>
                </property>
                <property name="locations">
                    <list>
                        <value>/WEB-INF/wildfire.default.properties</value>
                        <value>file:${wildfire.conf.dir}/staticversion.properties</value>
                        <value>file:${wildfire.conf.dir}/wildfire.properties</value>
                        <value>file:${wildfire.conf.dir}/wildfire.custom.properties</value>
                    </list>
                </property>
            </bean>
        As far as I can tell that is not a good candidate to be replaced with <util: properties/> since util: properties does not seem to offer the ability to read in from multiple property files, provide default values, ignore missing resources, etc.

        Any thoughts on dealing with my question #2 from before - regarding properties that reference other properties? Those work great with PropertyPlaceholderConfigurer, but I don't see an elegant way of accomplishing this with @Value

        Comment


        • #5
          Originally posted by Chris Beams View Post
          Also mentioned there, in M3, you'll be able to use ${...} syntax in conjunction with PropertyPlaceholderConfiguration or <context: property-placeholder/>.
          Chris,

          I've tried using ${...} syntax with M3 and it doesn't seem to work. Was this pushed out of M3? Is there a JIRA issue for this that I can watch?

          Thanks,
          Jeremy Haile

          Comment


          • #6
            Reference PropertyPlaceHolderConfigurer properties in @Value

            What I do is use a custom PropertyPlaceHolderConfigurer which exposes its properties (which the built in selfishly does not). For example:

            EnhancedPropertyPlaceholderConfigurer

            You will have to register it using the old
            Code:
            <bean id="propertyConfigurer" class="org.mortar.spring.beans.factory.config.EnhancedPropertyPlaceholderConfigurer">
            tag instead of the newer
            Code:
            <context:property-placeholder>
            so you can set an id an then reference it in your value tag as
            Code:
            @Value(#{propertyConfigurer.properties['foo.bar']})
            .

            P.S. you might be able to use the
            Code:
            <context:property/>
            tag, but It generates a huge and clumsy id something like org.springframework.beans.factory.config.PropertyP laceholderConfigurer#0

            Comment

            Working...
            X