Announcement Announcement Module
Collapse
No announcement yet.
Wiring a bean from a database Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Wiring a bean from a database

    I am wiring a bean with the port values from our developer machines. I would like to retrieve the value from a database. I think a custom property editor would be the right way to accomplish this. Is there another way of accomplishing this?

    Thanks,
    Bobby

  • #2
    You could use a PropertyPlaceholderConfigurer to externalize the properties. And there is another (spring) project that has created a few implementation (not only property files, but database access aswel), but I can`t find the link.

    Comment


    • #3
      Does anyone know where this is? I need it too!

      cheers,

      David

      Comment


      • #4
        Here is a configuration file which loads properties from a database using Apache Commons Configuration (whose connection properties are loaded from db.properties). Since I'm using two PropertyPlaceholderConfigurer, I needed to use a different placeholderPrefix for the file based one. That way the properties in the rest of the context uses normal syntax:

        Code:
        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
        <beans>
        	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        		<property name="location" value="db.properties"/>
        		<property name="placeholderPrefix" value="$&#123;init&#58;"/>
        	</bean>
        	
        	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        		<property name="properties">
        			<bean factory-class="org.apache.commons.configuration.ConfigurationConversion"
        	      		  factory-method="getProperties">
        		  		<constructor-arg>
        					<bean class="org.apache.commons.configuration.DatabaseConfiguration">
        				  		<constructor-arg>
        			   				<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        						      <property name="driverClassName" value="$&#123;init&#58;jdbc.driver&#125;"/>
        						      <property name="url" value="$&#123;init&#58;jdbc.url&#125;"/>
        						      <property name="username" value="$&#123;init&#58;jdbc.username&#125;"/>
        						      <property name="password" value="$&#123;init&#58;jdbc.password&#125;"/>
        						    </bean> 	
        						</constructor-arg>
          					    <constructor-arg value="$&#123;init&#58;table&#125;"/>
         					    <constructor-arg value="$&#123;init&#58;keyColumn&#125;"/>
        					    <constructor-arg value="$&#123;init&#58;valueColumn&#125;"/>
        				    </bean>
        				 </constructor-arg>
        			</bean>
        		</property>
        	</bean>
        </beans>

        Comment


        • #5
          Actually because of the recursive nature of my solution, you have to break it up into two contexts, with the bootstrap.xml being the parent to context.xml

          bootstrap.xml:
          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
          <beans>
          	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
          		<property name="location" value="db.properties"/>
          	</bean>
          
          	<bean id="myProps" class="org.apache.commons.configuration.ConfigurationConverter" factory-method="getProperties">
            		<constructor-arg>
          			<bean class="org.apache.commons.configuration.DatabaseConfiguration">
          		  		<constructor-arg>
          					<bean id="ds1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
          				      <property name="driverClassName" value="$&#123;jdbc.driver&#125;"/>
          				      <property name="url" value="$&#123;jdbc.url&#125;"/>
          				      <property name="username" value="$&#123;jdbc.username&#125;"/>
          				      <property name="password" value="$&#123;jdbc.password&#125;"/>
          				    </bean> 	
          		  		</constructor-arg>
          			    <constructor-arg value="$&#123;config.table&#125;"/>
          			    <constructor-arg value="$&#123;config.keyColumn&#125;"/>
          			    <constructor-arg value="$&#123;config.valueColumn&#125;"/>
          		    </bean>
          		 </constructor-arg>
          	</bean>
          		
          </beans>
          context.xml:
          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
          <beans>
          	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
          		<property name="properties" ref="myProps"/>
          	</bean>
          
          	<!-- Beans which use the db based properties goes here -->
          </beans>

          Comment


          • #6
            Late but for reference

            In order to avoid the above situation of creating hierachical contexts the same can be archived as follow:

            Code:
            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
            <beans>
              <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                <property name="propertiesArray">
                  <list>
                     <ref bean="myPropsFromFile"/>
                     <ref bean="myPropsFromDb"/>
                  </list>
                </property>
              </bean>
            
              <bean id="myPropsFromFile"
                class="org.springframework.beans.factory.config.PropertiesFactoryBean">
                <property name="location" value="db.properties"/>
              </bean>
            
              <bean id="myPropsFromDb" class="org.apache.commons.configuration.ConfigurationConverter" factory-method="getProperties">
                <constructor-arg>
                  <bean class="org.apache.commons.configuration.DatabaseConfiguration">
                    <constructor-arg>
                      <bean id="ds1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
                        <property name="driverClassName" ref="prop.jdbc.driver"/>
                        <property name="url" ref="prop.jdbc.url"/>
                        <property name="username" ref="prop.jdbc.username"/>
                        <property name="password" ref="prop.jdbc.password"/>
                      </bean>
                    </constructor-arg>
                    <constructor-arg ref="prop.config.table"/>
                    <constructor-arg ref="prop.config.keyColumn"/>
                    <constructor-arg ref="prop.config.valueColumn"/>
                  </bean>
                </constructor-arg>
              </bean>
            
              <bean id="prop.jdbc.driver"
                class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
                <property name="targetObject" ref="myPropsFromFile" />
                <property name="targetMethod" value="getProperty" />
                <property name="arguments">
                  <list>
                    <value>jdbc.driver</value>
                  </list>
                </property>
              </bean>
            
              <bean id="prop.jdbc.url"
                class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
                <property name="targetObject" ref="myPropsFromFile" />
                <property name="targetMethod" value="getProperty" />
                <property name="arguments">
                  <list>
                    <value>jdbc.url</value>
                  </list>
                </property>
              </bean>
            
              <bean id="prop.jdbc.username"
                class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
                <property name="targetObject" ref="myPropsFromFile" />
                <property name="targetMethod" value="getProperty" />
                <property name="arguments">
                  <list>
                    <value>jdbc.username</value>
                  </list>
                </property>
              </bean>
            
              <bean id="prop.jdbc.password"
                class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
                <property name="targetObject" ref="myPropsFromFile" />
                <property name="targetMethod" value="getProperty" />
                <property name="arguments">
                  <list>
                    <value>jdbc.password</value>
                  </list>
                </property>
              </bean>
            
              <bean id="prop.config.table"
                class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
                <property name="targetObject" ref="myPropsFromFile" />
                <property name="targetMethod" value="getProperty" />
                <property name="arguments">
                  <list>
                    <value>config.table</value>
                  </list>
                </property>
              </bean>
            
              <bean id="prop.config.keyColumn"
                class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
                <property name="targetObject" ref="myPropsFromFile" />
                <property name="targetMethod" value="getProperty" />
                <property name="arguments">
                  <list>
                    <value>config.keyColumn</value>
                  </list>
                </property>
              </bean>
            
              <bean id="prop.config.valueColumn"
                class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
                <property name="targetObject" ref="myPropsFromFile" />
                <property name="targetMethod" value="getProperty" />
                <property name="arguments">
                  <list>
                    <value>config.valueColumn</value>
                  </list>
                </property>
              </bean>
            
            </beans>
            This solves the problem by using the current proposition from spring but is quite verbose.
            In order to make it shorter to configure you can use the facory beans from http://opensource.atlassian.com/proj...rowse/SPR-2335 andf then the configuration will change to:

            Code:
            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
            <beans>
              <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                <property name="propertiesArray">
                  <list>
                     <ref bean="myPropsFromFile"/>
                     <ref bean="myPropsFromDb"/>
                  </list>
                </property>
              </bean>
            
              <bean id="myPropsFromFile"
                class="org.springframework.beans.factory.config.PropertiesFactoryBean">
                <property name="location" value="db.properties"/>
              </bean>
            
              <bean id="myPropsFromDb" class="org.apache.commons.configuration.ConfigurationConverter" factory-method="getProperties">
                <constructor-arg>
                  <bean class="org.apache.commons.configuration.DatabaseConfiguration">
                    <constructor-arg>
                      <bean id="ds1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
                        <property name="driverClassName" ref="myPropsFromFile[jdbc.driver]"/>
                        <property name="url" ref="myPropsFromFile[jdbc.url]"/>
                        <property name="username" ref="myPropsFromFile[jdbc.username]"/>
                        <property name="password" ref="myPropsFromFile[jdbc.password]"/>
                      </bean>
                    </constructor-arg>
                    <constructor-arg ref="myPropsFromFile[config.table]"/>
                    <constructor-arg ref="myPropsFromFile[config.keyColumn]"/>
                    <constructor-arg ref="myPropsFromFile[config.valueColumn]"/>
                  </bean>
                </constructor-arg>
              </bean>
            
              <bean name="myPropsFromFile[jdbc.driver]"
                class="org.springframework.beans.factory.config.PropertiesGetterFactoryBean"/>
                
              <bean name="myPropsFromFile[jdbc.url]"
                class="org.springframework.beans.factory.config.PropertiesGetterFactoryBean"/>    
            
              <bean name="myPropsFromFile[jdbc.username]"
                class="org.springframework.beans.factory.config.PropertiesGetterFactoryBean"/>
            
              <bean name="myPropsFromFile[jdbc.password]"
                class="org.springframework.beans.factory.config.PropertiesGetterFactoryBean"/>
            
              <bean name="myPropsFromFile[config.table]"
                class="org.springframework.beans.factory.config.PropertiesGetterFactoryBean"/>
            
              <bean name="myPropsFromFile[config.keyColumn]"
                class="org.springframework.beans.factory.config.PropertiesGetterFactoryBean"/>
            
              <bean name="myPropsFromFile[config.valueColumn]"
                class="org.springframework.beans.factory.config.PropertiesGetterFactoryBean"/>    
                
            </beans>
            Less verbose but no core Spring support.

            Comment


            • #7
              Link to runtime environment propery placeholder configurer

              It's possible this is the referenced PropertyPlaceholderConfigurer

              Comment


              • #8
                Not the same use case. Please read http://opensource.atlassian.com/proj...5#action_19719

                Comment


                • #9
                  Not sure if it helps, but Spring Modules provides integration with Commons Configuration.

                  Comment


                  • #10
                    The Spring modules factory bean looks interesting, but I couldn't find any documentation (except the extremely minimal javadocs). Could you add a section / example to the main HTML docs?

                    Comment


                    • #11
                      Sure - can you please raise an issue on JIRA to keep track of it? Thanks.

                      Comment


                      • #12
                        Getting an error

                        I tried uisng the above setup for a properties configurer. i get the following e rror
                        org.springframework.beans.NotWritablePropertyExcep tion: Invalid property 'propertiesArray' of bean class [org.springframework.beans.factory.config.PropertyP laceholderConfigurer]: Bean property 'proper
                        tiesArray' is not writable or has an invalid setter method: Does the parameter type of the setter match the return type of the getter?

                        Any idea why this is happening?
                        Regards,
                        Deepa

                        Comment


                        • #13
                          I would presume as the method does exist, the arguments being passed in don't match the expected ones. It expects Properties[].

                          http://static.springframework.org/sp...perties&#91;])

                          Comment

                          Working...
                          X