View Full Version : JDBC-based bean definitions
karsten
Aug 15th, 2004, 05:54 PM
Just wanted to verify my understanding of the following issue at
http://opensource.atlassian.com/projects/spring/browse/SPR-95
Addresses this a new feature where I can store my bean definitions in a DB table instead of an XML file?
is this correct?
Because this would come quite nice to play with the Timer functionality in Spring. I could specify the timertasks in a DB table then which I need for a project.
Is there any possibility to work on this and contribute it?
cheers.
Colin Sampaleanu
Aug 15th, 2004, 06:09 PM
Karsten,
Yes, the existing JdbcBeanDefinitionReader can read bean definitions from a database, but it's not incredibly flexible. Additionally, there is the question of dynamic reconfiguration. One of the main reasons why somebody would put some data in a db (at least some of the time) is probably because they need to be able read that data dynamically, not just on program startup.
As for user contributions for this or any other area of Spring, sure, they are much appreciated. Any code can be submitted as a patch in Jira, and discussed in the dev list.
karsten
Aug 15th, 2004, 06:24 PM
Colin,
thanks for the quick reply.
I will have a closer look at this subject and come back with more thoughts/code.
Keep your great work up!
karsten
Aug 17th, 2004, 07:08 PM
I just wonder about some things with the functionality of retrieving bean definitions from a DB. Please correct me if I am wrong:
To retrieve bean configs from a DB, I need to store them as stated in the JdbcBeanDefinitionReader class (beanID, property name and value), then I need to instatiate a new JdbcBeanDefinitionReader, set a Datasource or JdbcTemplate on it. And I could do this with spring in the applicationContext.xml, or?
After that I have my own ServletContextListener implementation, which follows the spring ContextLoaderListener. In this class I retrieve the JdbcBeanDefinitionReader from the context and call the loadBeanDefinitions(String sql) method with the appropriate SQL.
The beans will get loaded into the same context as the others? or a new one?
Is this working at all, or am I missing something.
Thanx for clarifying.
rstearns01
Aug 21st, 2004, 11:30 AM
Karsten,
Yes, the existing JdbcBeanDefinitionReader can read bean definitions from a database, but it's not incredibly flexible. Additionally, there is the question of dynamic reconfiguration. One of the main reasons why somebody would put some data in a db (at least some of the time) is probably because they need to be able read that data dynamically, not just on program startup.
I need to do something similar in that it is "policy" that if a configuration file changes, the application must go through a complete 30-day round of regression testing; yet there is no such rule for changing a value in the database. :roll:
rstearns01
Aug 21st, 2004, 11:30 AM
Karsten,
Yes, the existing JdbcBeanDefinitionReader can read bean definitions from a database, but it's not incredibly flexible. Additionally, there is the question of dynamic reconfiguration. One of the main reasons why somebody would put some data in a db (at least some of the time) is probably because they need to be able read that data dynamically, not just on program startup.
I need to do something similar in that it is "policy" that if a configuration file changes, the application must go through a complete 30-day round of regression testing; yet there is no such rule for changing a value in the database. :roll:
MHarhen
Aug 28th, 2004, 04:53 PM
Karsten,
Yes, the existing JdbcBeanDefinitionReader can read bean definitions from a database, but it's not incredibly flexible. Additionally, there is the question of dynamic reconfiguration. One of the main reasons why somebody would put some data in a db (at least some of the time) is probably because they need to be able read that data dynamically, not just on program startup.
As for user contributions for this or any other area of Spring, sure, they are much appreciated. Any code can be submitted as a patch in Jira, and discussed in the dev list.
I have written some code to initialize bean properties using initialization parameters stored in various locations e.g. database table, servlet context, servlet init parameters, Map, Properties, etc. It works both during application initialization and later during application execution. i.e. it supports dynamic reinitialization of bean properties,
I would be happy to submit the code to the Spring project. Let me know if you are interested.
See my posting from August 30 for additional information
Colin Sampaleanu
Aug 28th, 2004, 08:55 PM
The best thing would be to put it on the wiki (Confluence) somewhere, so other people can get at it...
irbouho
Aug 28th, 2004, 09:59 PM
MHarhen,
Your approach seems very interesting. I have two questions with regards to beans configurations using PropertyMapper:
1. Is it possible to configure PropertyMapper to call some initialization methods after properties were updated (to emulate Spring' init-method)?
2. How do you manage "dynamic reconfiguration": reconfigure a bean that is being used by other beans.
I am asking these questions because I will be using such "hot-configuration/reconfiguration" in a future project.
Thank you.
MHarhen
Aug 29th, 2004, 12:33 AM
1. Is it possible to configure PropertyMapper to call some initialization methods after properties were updated (to emulate Spring' init-method)?
2. How do you manage "dynamic reconfiguration": reconfigure a bean that is being used by other beans.
Answers:
1. Yes - PropertyMapper has an initMethod property.
2. By dynamic reconfiguration, I mean changing the properties of a bean during execution. It is done by calling the PropertyMappers.refreshAll() method.
jbetancourt
Aug 29th, 2004, 05:23 AM
MHarhen,
I too would be interested in your approach also. For clustering and other crazy requirements we keep some properties in a central database. So during init we need to get them, then configure some root beans.
J. Betancourt
karsten
Aug 29th, 2004, 05:47 PM
MHarhen,
is there any ready to use code? any further information on where to get it?
thanx for the promising looking code.
MHarhen
Aug 30th, 2004, 02:25 AM
is there any ready to use code? any further information on where to get it?
thanx for the promising looking code.
The code is still in progress. It works, but I need to clean it up. I'll target completion in about a week, if not sooner.
MHarhen
Aug 30th, 2004, 10:23 PM
is there any ready to use code? any further information on where to get it?
thanx for the promising looking code.
Code has been updated as of September 5. See my September 5 posting.
MHarhen
Sep 6th, 2004, 12:06 AM
is there any ready to use code? any further information on where to get it?
thanx for the promising looking code.
I have written code to enable initialization of a bean using initialization parameters from a database table. The code can be downloaded from:
http://members.cox.net/jwebutil/InitParameters.zip
How to use it:
1. Create a bean class net.sourceforge.MyBean. To use the following example, create setWebMaster(...) and getWebMaster() methods.
2. Create a database table called "InitParametersTable", with columns named "Parameter" and "Value". You may change these using the SQL shown below.
Enter the names and values of the parameters you wish to use as the rows in the table.
e.g. Parameter: WEBMASTER
Value: The web master
3. Create a datasource with id="DATASOURCE" or whatever id you wish to use.
4. Create an InitParameters bean, specifying the DataSource and SQL needed to access the table.
<bean id="initParameters"
class="net.sourceforge.jwebutil.util.initparameters.InitP arametersFactory"
factory-method="createInstance">
<description>Database Init Parameters</description>
<constructor-arg index="0"><ref bean="DATASOURCE" /></constructor-arg>
<constructor-arg index="1">
<value>
<![CDATA[
SELECT Parameter, Value FROM InitParametersTable;
]]>
</value>
</constructor-arg>
</bean>
5. Create a bean, using the PropertyMapper factory. Specify the bean's class using the "targetClass" property. Specify the bean's properties using the "properties" property. Each key refers a property of the bean. Each value refers to the name of the Initialization Parameter in the database table.
<bean id="myBean" class="net.sourceforge.jwebutil.util.initparameters.Prope rtyMapper">
<description>Global Application Configuration properties</description>
<property name="targetClass"><value>net.sourceforge.MyBean</value></property>
<property name="initParameters"><ref bean="initParameters" /></property>
<property name="properties">
<props>
<prop key="webMaster">#WEBMASTER</prop>
</props>
</property>
</bean>
Notes:
1) Mandatory initialization parameters are indicated by a preceding "#". e.g. <prop key="webMaster">#WEBMASTER</prop>
2) Default values are indicated by a semi-colon followed by the default value. e.g. <prop key="webMaster">WEBMASTER;Tom Swift</prop>
3. You can specify a reference to a bean by preceding its name with a "*". e.g. <prop key="theBean">*theBeanRef</prop>
4. You can specify a value for a property by preceding its value with a "@". e.g. <prop key="webMaster">@Tom Swift@yahoo.com</prop>. In this case, the value of the property is used as-is, without looking it up in the InitParameters object.
5. All of your custom Property Editors are supported.
6. The InitializingBean and DisposableBean interfaces are supported. You can also specify a method to be called after all of the bean's properties are set - e.g. <property name="initMethod"><value>init</value></property>. In addition, you can specify a destroyMethod e.g. <property name="destroyMethod"><value>destroy</value></property>.
7. You can update all beans at any time by calling propertyMapManager().refreshAll()
8. You can update an individual bean at any time by calling propertyMapManager().refresh(theBean)
9. You can also use initialization parameters from the ServletContext, JNDI context, any Map, any Properties object, etc - see the InitParametersFactory class.
10. Use <property name="singleton"><value>false</value></property> to specify that the bean is a prototype. The default is "true", specifying a singleton.
11. Comments are appreciated...
karsten
Sep 9th, 2004, 11:49 AM
please correct me if I am wrong, just tried to understand your code and I might be wrong. This is how I understand the workflow:
1. the InitparameterFactory retrieves the Name/Value pairs from the DB with the passed SQL and Datasource.
2. for each bean/class where I want to use DB based properties, I declare a PropertyMapper with the target class property, a reference to the InitParametersFactory and a list of properties.
2.a. the PropertyMapper returns a bean of the class defined in target class
2.b. the properties are as followed:
key = the setter of the property in the target class
value = the value of the Property colum in the DB
2.c. the PropertyMapper calls the setters defined in the key values with the values from the DB where Property value = value in the props field
With a quick try I had the following issues:
with the factory-method attribute used in the InitParametersFactory one needs Spring 1.1; no problem, I merely used 1.0.2 before and ran into an error
I got a couple of ScheduledTimerTasks with properties like
<bean id="myTask" class="net.sourceforge.jwebutil.util.initparameters.Prope rtyMapper">
<property name="targetClass"><value>org.springframework.scheduling.timer.ScheduledTime rTask</value></property>
<property name="initParameters"><ref bean="initParameters" /></property>
<property name="properties">
<props>
<prop key="timerTask">@*myJob</prop>
<prop key="delay">delay</prop>
<prop key="period">period</prop>
<prop key="fixedRate">@true</prop>
</props>
</property>
</bean>
I had some problems with the bean reference timerTask. It was not possible
a) to combine it with a default value (*myJob;myJobBeanRef)
b) to combine it with a as-is value (@*myJobBeanRef)
was I doing something wrong?
I am getting your thoughts. More comments will follow.
I miss a bit the possibility to define the beans itself in the DB. Not via the propertyMapper, since in my case the number of timerTask is variable. but that is not so important.
MHarhen
Sep 9th, 2004, 09:44 PM
I had some problems with the bean reference timerTask. It was not possible
a) to combine it with a default value (*myJob;myJobBeanRef)
b) to combine it with a as-is value (@*myJobBeanRef)
was I doing something wrong?
karsten, thanks for your comments. Your workflow description is accurate.
Problem a) You are correct - a fix will require a 1 line change to PropertyMapper.createPropertyValues().
Problem b) From a quick look at PropertyMapper.createPropertyValues(), this should work, but I need to review it more carefully.
I'll post the fixes as soon as I can get to it.
MHarhen
Sep 11th, 2004, 07:22 PM
I'll post the fixes as soon as I can get to it
The updated code is available from : http://members.cox.net/jwebutil/InitParameters.zip
I was able to get a Timer working as follows:
<bean id="initParameters"
class="net.sourceforge.jwebutil.util.initparameters.InitP arametersFactory"
factory-method="createInstance">
<description>Database Init Parameters</description>
<constructor-arg index="0"><ref bean="DATASOURCE" /></constructor-arg>
<constructor-arg index="1">
<value>
<![CDATA[
SELECT Parameter, Value FROM InitParameters;
]]>
</value>
</constructor-arg>
</bean>
<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryB ean">
<property name="scheduledTimerTasks">
<list>
<ref local="myTask"/>
</list>
</property>
</bean>
<bean id="myJob" class="....MyTask" />
<bean id="myTask" class="net.sourceforge.jwebutil.util.initparameters.Prope rtyMapper">
<property name="targetClass"><value>org.springframework.scheduling.timer.ScheduledTime rTask</value></property>
<property name="initParameters"><ref bean="initParameters" /></property>
<property name="properties">
<props>
<prop key="timerTask">@*myJob</prop>
<prop key="delay">#delay</prop>
<prop key="period">#period</prop>
<prop key="fixedRate">@false</prop>
</props>
</property>
</bean>
In the above example, <prop key="timerTask">@*myJob</prop>
refers directly to a bean. The "#" in front of "delay" and "period" indicates that these parameters are mandatory - an exception will be thrown if not found.
You could also refer indirectly to a bean reference using a name stored in the database, with a default reference if there is no entry in the database.
<prop key="timerTask">*TIMERJOB;myJob</prop>
In the above example, TIMERJOB is the name of a parameter in the database table. The bean will be created with the value of this parameter. If the value of the parameter is null, a direct reference to the bean "myJob" will be used.
karsten
Sep 26th, 2004, 06:53 PM
Michael,
thx for the fixes and for firming up my understanding.
I also recognized that the issue at http://opensource.atlassian.com/projects/spring/browse/SPR-95 got updated from Rod.
But I haven't had the time for a closer look at it.
vBulletin® v3.7.3, Copyright ©2000-2008, Jelsoft Enterprises Ltd.