Announcement Announcement Module
Collapse
No announcement yet.
Using PropertyOverrideConfigurer to override value of Map property embedded in a bean Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Using PropertyOverrideConfigurer to override value of Map property embedded in a bean

    Hi,

    I am trying to use PropertyOverrideConfigurer to override a couple of values in a java.util.Properties object that is embedded inside of a bean defenition in the application context file.

    So say for example that I want to override the "file.path.input" property of the filePathProperties property of the bean someBeaName:

    Code:
      <bean id="someBeaName" class="com.package.SomeBeaName" >
        <property name="filePathProperties">
          <map>
            <entry key="file.path.input" value="file/path/input.xml"/>
            <entry key="file.path.output" value="file/path/output.xml"/>
            <entry key="file.path.script" value="file/path/script.ksh"/>
          </map>
        </property>
      </bean>

    Then how would i specify that in the properties file that I am going to load into the PropertyOverrideConfigurer?

    Code:
    someBeaName.filePathProperties.????=alternative/file/path/input.xml
    what would go in place of the ???? above?
    Any help is very much appreciated.

  • #2
    Code:
     
     <bean id="someBeaName" class="com.package.SomeBeaName" >
        <property name="filePathProperties">
          <map>
            <entry key="file.path.input" value="${file.path.input}"/>
            <entry key="file.path.output" value="file/path/output.xml"/>
            <entry key="file.path.script" value="file/path/script.ksh"/>
          </map>
        </property>
      </bean>
    And put this in a properties file that you load up:

    Code:
    file.path.input=alternative/file/path/input.xml

    Comment


    • #3
      I take it what you mean is you want to replace the whole Properties object rather than just one of the elements.

      Comment


      • #4
        I think the question was how to override (not replace) a single property. What about

        Code:
        someBeaName.filePathProperties[file.path.input]=alternative/file/path/input.xml
        I'm guessing it works based on what I know about BeanWrapperImpl but haven't tried it.

        Comment


        • #5
          cwilkes,
          If I try you suggestion then that would mean that I would have to use a PropertyPlaceholderConfigurer in my app context file. And that will probabley not work in my situation because Spring gives me an error when I use PropertyPlaceholderConfigurer twice in the ClassPathXmlApplicationContext that I am loading.

          The problem that I am having is that i have two context files, one that is common to all of my JUnits (contains database connetion and transaction bean defenitions), and I have another context file that is specific to each particular JUnit.

          In my JUnit's setUp() method I load both context files using the ClassPathXmlApplicationContext(String[] configLocation) constructor, where I pass in both context files as an array. But the problem is that I am already using a PropertyPlaceholderConfigurer in my first context file (which is common to all of my JUnits), and then when I try to use it again in my second context file (for my specific JUnit), then Spring gives me an error saying something like:

          [/context-file-name.xml]: Could not resolve placeholder 'folder.path.input'
          I came across this problem some while ago, and it really annoys me the fact that Spring does not allow us to load more than one PropertyPlaceholderConfigurer bean defenition in our ApplicationContext.

          david_syer, your suggestion might work, though i have not tried it yet.

          Thank you all for your help and suggestions.

          Comment


          • #6
            david_syer,

            I tried your suggestion, but I end up getting an error that says something like the following:

            org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'someBeaName' defined in class path resource [/context-file-name.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyExcep tion: Invalid property 'filePathProperties[file.path.input]' of bean class [com.package.SomeBeaName]: Cannot access indexed value in property referenced in indexed property path 'filePathProperties[file.path.input]'; nested exception is org.springframework.beans.NotReadablePropertyExcep tion: Invalid property 'filePathProperties[file.path.input]' of bean class [com.package.SomeBeaName]: Bean property 'filePathProperties[file.path.input]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
            ...
            [REMAINER OF STACK TRACE ERROR HAS BEEN OMITTED FOR BREVITY]

            Thanks for the suggestion though. I really appreciate your help.

            Comment


            • #7
              david_syer,

              Actually your suggestion does work. The problem was that I only had a setter method

              Code:
              public void setFilePathProperties(Properties filePathProperties)
              {
              	this.filePathProperties = filePathProperties;
              }
              defined in my bean class. After I add a corresponding getter method

              Code:
              public Properties getFilePathProperties()
              {
              	return filePathProperties;
              }
              the error went away, and it worked. Thanks.

              Though on a separate note, I wish Spring would fix their framework to allow us to defined more than one PropertyOverrideConfigurer for the same ApplicationContext object.

              Comment


              • #8
                Originally posted by al_zawia View Post
                Though on a separate note, I wish Spring would fix their framework to allow us to defined more than one PropertyOverrideConfigurer for the same ApplicationContext object.
                You can. You just need to ensure they are configured correctly e.g. setting the order and ignoreUnresolvablePlaceholders as required.

                Comment


                • #9
                  Originally posted by karldmoore View Post
                  You can. You just need to ensure they are configured correctly e.g. setting the order and ignoreUnresolvablePlaceholders as required.
                  You are correct. I was able to get it to work by setting the ignoreUnresolvablePlaceholders property to true on the PropertyPlaceholderConfigurer. Thanks for pointing that out to me

                  Comment


                  • #10
                    Originally posted by al_zawia View Post
                    You are correct. I was able to get it to work by setting the ignoreUnresolvablePlaceholders property to true on the PropertyPlaceholderConfigurer. Thanks for pointing that out to me
                    Not a problem, it's quite a useful trick!

                    Comment


                    • #11
                      Is it possible to override a factoryBean-created Properties object in the same way? Given this configuration:

                      <utilroperties id="JbossEnv" >
                      <prop key="java.naming.factory.initial">org.jboss.naming .NamingContextFactory</prop>
                      <prop key="java.naming.provider.url">jnp://localhost:1099</prop>
                      <prop key="java.naming.factory.url.pkgs">org.jboss.namin g.client</prop>
                      <prop key="jnp.timeout">5000</prop>
                      <prop key="jnp.sotimeout">5000</prop>
                      </utilroperties>
                      I'd really like to override a property with the syntax:

                      JbossEnv[java.naming.provider.url]=jnp://myhost:1099
                      but it doesn't seem possible.
                      Last edited by jeffdo; Oct 27th, 2009, 01:35 PM.

                      Comment


                      • #12
                        PropertyOverrideConfigurer to overrode a map property not working

                        Originally posted by Dave Syer View Post
                        I think the question was how to override (not replace) a single property. What about

                        Code:
                        someBeaName.filePathProperties[file.path.input]=alternative/file/path/input.xml
                        I'm guessing it works based on what I know about BeanWrapperImpl but haven't tried it.

                        I am not getting this usage. Can you please elaborate?
                        I want to override a map property from a properties file.
                        I have a property value in my properties files as follows:

                        beanName.mapProperty[key1] = value1 and in my appalicationContext.xml, I have something similar to

                        <entry key="key1" value="${beanName.mapProperty[key1}"/>.

                        But it's not getting replaced correctly when I run the application. It says "${beanName.mapProperty[key1}" is an invalid value.

                        Can you please help with this? if possible give me some examples that I can refer to.

                        Thanks!

                        Comment


                        • #13
                          Is this what you want?

                          Following is the bean that has the properties instance variable, it loads the default values in the constructor. Note that in the setter i do this.dbProperties.putAll(dbProperties); not this.dbProperties = dbProperties. I do this to keep old properties that will not get overriden.

                          Code:
                          public class DbPropsBean {
                          
                          	private Properties dbProperties = new Properties();
                          
                          	public DbPropsBean() {
                          		dbProperties.put("jdbc.driverclass", "oracle.jdbc.OracleDriver");
                          		dbProperties.put("hibernate.sql.dialect", "org.hibernate.dialect.Oracle9Dialect");
                          		dbProperties.put("jdbc.url", "jdbc:oracle:thin:@localhost:1521:xe");
                          	}
                          
                          	public Properties getDbProperties() {
                          		return dbProperties;
                          	}
                          
                          	public void setDbProperties(Properties dbProperties) {
                          		this.dbProperties.putAll(dbProperties);
                          	}
                          }
                          Spring configuration. You can put the properties that you want to override

                          Code:
                          	<bean
                          		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                          		<property name="locations" value="classpath:/database.properties" />
                          	</bean>
                          
                          	<bean id="dbProps" class="DbPropsBean">
                          		<property name="dbProperties">
                          			<props>
                          				<prop key="jdbc.url">${jdbc.url}</prop>
                          			</props>
                          		</property>
                          	</bean>
                          database.properties file,

                          Code:
                          jdbc.url=jdbc:oracle:thin:@remote:1521:xe
                          Test class,

                          Code:
                          public class TestClass {
                          
                          	private static ConfigurableApplicationContext appCtx;
                          
                          	public static void main(String[] args) {
                          		appCtx = new ClassPathXmlApplicationContext(
                          				new String[] { "applicationContext.xml" });
                          		
                          		DbPropsBean bean = (DbPropsBean) appCtx.getBean("dbProps");
                          		
                          		System.out.println(bean.getDbProperties().getProperty("jdbc.url"));
                          		
                          	}
                          }

                          Comment


                          • #14
                            I thought you used a Properties, but it was a map so it will be,

                            Bean definition,

                            Code:
                            	<bean id="dbMap" class="DbMapBean">
                            		<property name="dbPropMap">
                            			<map>
                            				<entry key="jdbc.url" value="${jdbc.url}" />
                            			</map>
                            		</property>
                            	</bean>
                            DbMapBean,

                            Code:
                            public class DbMapBean {
                            
                            	private Map<String, String> dbPropMap = new HashMap<String, String>();
                            	
                            	public DbMapBean() {
                            		dbPropMap.put("jdbc.driverclass", "oracle.jdbc.OracleDriver");
                            		dbPropMap.put("hibernate.sql.dialect", "org.hibernate.dialect.Oracle9Dialect");
                            		dbPropMap.put("jdbc.url", "jdbc:oracle:thin:@localhost:1521:xe");
                            	}
                            
                            	public void setDbPropMap(Map<String, String> dbPropMap) {
                            		this.dbPropMap.putAll(dbPropMap);
                            	}
                            
                            	public Map<String, String> getDbPropMap() {
                            		return dbPropMap;
                            	}
                            }
                            The property that is marked in red will get replaced by the one that is in the properties file

                            Comment


                            • #15
                              Hey i think you have missed the closing square bracket in the application context file

                              beanName.mapProperty[key1] = value1 and in my appalicationContext.xml, I have something similar to

                              <entry key="key1" value="${beanName.mapProperty[key1}"/>.

                              Comment

                              Working...
                              X