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
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
MHarhen,
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.Originally Posted by karsten
Code has been updated as of September 5. See my September 5 posting.Originally Posted by karsten
I have written code to enable initialization of a bean using initialization parameters from a database table. The code can be downloaded from:Originally Posted by karsten
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.
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.Code:<bean id="initParameters" class="net.sourceforge.jwebutil.util.initparameters.InitParametersFactory" 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>
Notes:Code:<bean id="myBean" class="net.sourceforge.jwebutil.util.initparameters.PropertyMapper"> <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>
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...
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
I had some problems with the bean reference timerTask. It was not possibleCode:<bean id="myTask" class="net.sourceforge.jwebutil.util.initparameters.PropertyMapper"> <property name="targetClass"><value>org.springframework.scheduling.timer.ScheduledTimerTask</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>
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.
karsten, thanks for your comments. Your workflow description is accurate.Originally Posted by karsten
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.
The updated code is available from : http://members.cox.net/jwebutil/InitParameters.zipOriginally Posted by MHarhen
I was able to get a Timer working as follows:
In the above example,Code:<bean id="initParameters" class="net.sourceforge.jwebutil.util.initparameters.InitParametersFactory" 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.TimerFactoryBean"> <property name="scheduledTimerTasks"> <list> <ref local="myTask"/> </list> </property> </bean> <bean id="myJob" class="....MyTask" /> <bean id="myTask" class="net.sourceforge.jwebutil.util.initparameters.PropertyMapper"> <property name="targetClass"><value>org.springframework.scheduling.timer.ScheduledTimerTask</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>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.Code:<prop key="timerTask">@*myJob</prop>
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.
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.Code:<prop key="timerTask">*TIMERJOB;myJob</prop>
Michael,
thx for the fixes and for firming up my understanding.
I also recognized that the issue at http://opensource.atlassian.com/proj.../browse/SPR-95 got updated from Rod.
But I haven't had the time for a closer look at it.