A coworker and I were chatting regarding spring rowMappers and I did a little more research and found the following:
Spring’s simpleJdbcTemplate deprecated methods with parameterizedRowMapper in spring 3. The class ParameterizedRowMapper is not deprecated.
Spring’s jdbcTemplate however only has methods that take RowMapper<T> so it will continue to work with parameterizedRowMapper.
But it seems to me the direction of Spring is to go back to use genericized rowMapper e.g. RowMapper<T>. So for all of my new mappers, I will probably implement RowMapper<T> instead of ParameterizedRowMapper<T>.
I can’t seem to live without being able to search for my old blog posts. So I spent some time tonight looking into somehow porting my old pure-essence.net wordpress posts to somewhere public.
I noticed that I could import wordpress blogs via xml to wordpress.com now so I tried that. For the last 3 hours, I’ve been trying to get the stupid categories and tags to import correctly. And I’ve tried the tips from this blog entry but it did not help in my case. I’m going to try one last thing then I will give up for tonight.
Who’d known 10 years ago wordpress would have become my nemesis. It still contains my blog posts for the last 10 years.
If you have a strange requirement in the rowMapper to check if a column exists or not, you could try to catch a SQLException of invalid column name or you could try:
public static boolean doesColumnExist(String columnName, ResultSet rs) throws SQLException{
ResultSetMetaData meta = rs.getMetaData();
int numCol = meta.getColumnCount();
for (int i = 1; i <= numCol; i++) {
if(meta.getColumnName(i).equalsIgnoreCase(columnName)) {
return true;
}
}
return false;
}
我知道我这样说最终会让别人误会。我现在的感受好似徐怀钰的那首《爱像一场重感冒》。不但像,要走时我还真生了一场重感冒 。如果说ISL是一场三个月的恋爱真不算夸张。我现在像刚和男友说了分手般心酸。人一生的感情真是微妙。事业和爱情原来可以相提并论。事业上的爱恨情仇也是可以刻骨铭心的。
分了或走了,甜蜜回忆却上心头。英语因该说是bittersweet。我知道雨过天晴后留下会是美好。一番人生体验。学习到了新的技术。交了好些新朋友。
哦,ISL,虽然我们未能一起走到最后。我会常常想念你。像想念我的初恋男友一样。
在这我留给读者在我脑中的歌词。
徐怀钰 《爱像一场重感冒》
词:姚若龙
曲:Eric Lee
写了封信给你 好像依依不舍
刚寄出去马上又后悔了
多希望邮差能把地址看错 或是弄丢了
因为你是真的 和别人不一样
不然我不会那么感伤
但是我已爱到不能爱 让到不能让
还能怎样 不如倔强
倒数三秒 我会开始努力把你忘掉
有时候爱情就像是一场重感冒 等烧退了就好
找一天将心情当房子好好地打扫
我喜欢每次丢掉多馀的东西 那种轻松美好
A business rule at work requires some flexible configurations. I attempted to fulfill the need by create different spring batch steps/tasklets to execute each requirement based on a property value.
For example, step 1 will need to execute methodOne on the class Repository with the appropriate parameters. The method signature & parameters are determined by the tasklet1.chocie value in the env.properties.
I could write a bunch of if statements in each step. I wanted to see if there is a more dynamic way to do this.
I tried using Spring Framework and Java reflection.
My Git Repository for the example
Repository Class link
It has four methods: methodOne, methodOne(overloaded), methodTwo, methodThree.
TaskletExecution link
The POJO to hold the configuration needed to invoke the method using reflection.
- String methodName
- Object[] parameters
-
public Class[] getParameterClasses() { List> parameterClasses = new ArrayList >(); for (Object parameter : parameters) { parameterClasses.add(parameter.getClass()); } return parameterClasses.toArray(new Class[] {}); }
AbstractTasklet Class link
The parent class for all of the tasklets. It has the execute method that uses reflection to invoke the method using the TaskletExecution.
public void execute() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
log.info(String.format("in '%s' execute with choice '%s'", getTaskletName(), choice));
Method method = Repository.class.getMethod(taskletExecution().getMethodName(), taskletExecution().getParameterClasses());
Integer repositoryResult =(Integer)method.invoke(repository, taskletExecution().getParameters());
log.info(String.format("repository result = '%s'", repositoryResult));
}
The TaskletExecution is determined by the value of the tasklet#.choice property in the env.properties. It uses the property to look up the taskletExecution value in the taskletExecutions map that’s autowired to each tasklet via spring.
Example of a TaskletExecutions Map link
<util:map id="tasklet5Executions" value-type="net.pureessence.example.TaskletExecution">
<entry key-ref="choice1">
<bean class="net.pureessence.example.TaskletExecution">
<property name="methodName" value="methodThree"/>
<property name="parameters">
<list>
<bean class="java.lang.String">
<constructor-arg>
<value>51</value>
</constructor-arg>
</bean>
<bean class="java.lang.Integer">
<constructor-arg>
<value>52</value>
</constructor-arg>
</bean>
<bean class="java.lang.String">
<constructor-arg>
<value>tasklet5 arg3</value>
</constructor-arg>
</bean>
<bean class="net.pureessence.example.Type" factory-method="valueOf">
<constructor-arg>
<value>TYPE_3</value>
</constructor-arg>
</bean>
</list>
</property>
</bean>
</entry>
<entry key-ref="choice2">
<bean class="net.pureessence.example.TaskletExecution">
<property name="methodName" value="methodOne"/>
<property name="parameters">
<list>
<bean class="java.lang.String">
<constructor-arg>
<value>tasklet5 arg1</value>
</constructor-arg>
</bean>
<bean class="java.lang.Integer">
<constructor-arg>
<value>123599</value>
</constructor-arg>
</bean>
<bean class="net.pureessence.example.Type" factory-method="valueOf">
<constructor-arg>
<value>TYPE_3</value>
</constructor-arg>
</bean>
</list>
</property>
</bean>
</entry>
</util:map>
Personally I’m not overly thrilled with how verbose the spring config is. It took me a long time to figure out how to make it syntactically correct. The spring in depth site is a very good resource. In general, it takes a lot of xml to create maps in spring. I think at this point, it maybe a better idea to create static maps in each tasklet in Java for configurations.
My Git Repository for the example
Tried to add a new line with AT&T was almost impossible.
Got the new phone today and trying to activate it was usually painful.
- Their online activation gave the error: ACT015: We cannot process your request at this moment due to insufficient data. Please contact Customer Care at 1-800-331-0500.
- On the phone with the first customer service representative for 20 minutes. The representative insisted he could not activate the phone because we did not agree to their terms and services. We never got the email regarding the terms and services in order to AGREE to it. He didn’t consider a recorded verbal agreement was enough. In addition, we’ve been with AT&T for over 6 years and we figured we probably have agreed to their terms or services some prior time. The representative gave us another 866 number to call.
- On the phone with the 866 customer service representative for over 40 minutes. 39 minutes of the 40 on hold. She repeated she was working with their account management to activate the new line. Finally she hang up on us.
- Tried the online activate again and got the same error.
- Tried to forget about it for three hours.
- Just tried the new phone again, the SIM card registration error magically went away.
So for a long time, I wondered how you’d do the sql IN() using spring jdbcTemplate. Today I had an opportunity to work it out.
Normally I used
ListFoos = jdbcTemplate.query("select * from foo where name = ?", new Object[] { "foo1" }, new FooMapper() );
It’s not too friendly if you do
select * from food where name in ('foo1', 'foo2')
If you wish to use the “where in” sql, there is a pretty elegant way to do it in spring since spring 2.0 actually. I didn’t find out until today.
NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("names", Arrays.asList("foo1", "foo2"));
List Foos = namedParameterJdbcTemplate.query("select * from foo where name in (:names)",
parameters,
new FooMapper()
);
While reviewing an existing project at work, I notice it has many delete confirmation pages. In my opinion, delete confirmation PAGES should really just retire from the face of the earth. Seriously, why do we need to create a http request & html for the mere purpose of asking
“Are you sure you wish to delete blah?”
Yes, I’m Sure | No, go back
Often the URLs for delete confirmation pages are consisted of
some.host/someApplication/deleteConfirmation?toDelete=some+description&id=some+id
Delete confirmation should be an UI client side behavior to prevent the user from accidentally clicking on a delete link/button and forcing a backend change to the data that was not intended.

Preconditions
The delete actions are hyperlinks. There are many examples with delete actions as form submissions. My example expects the delete actions to be links such as delete.php?id=#. I believe this is a more challenging situation than a form submission. I will share my solution. I think ideally it will be nice for the jQuery UI dialog to return a boolean javascript variable but since it currently does not (and I’m not sure it ever will), I’m using window.location to load the delete action link.
View the example of the page without any jQuery
Please have some general knowledge regarding jQuery selectors. I will not go into details how that works.
Assume you have a way of using jQuery selectors to uniquely bind an onclick event to each delete link. For simplicity purpose, in my example, all of my delete links will have the css class deleteConfirmation.
jQuery UI example of a delete confirmation modal window
I will be using links from Google CDN in my example.
Step 1
Create a div with an unique id in your html markup. It doesn’t matter where it exists in your markup, it just need to exist. We will create the jQuery UI dialog off it.
<div id="jQueryDeleteConfirmationModalWindow"></div>
Step 2
When the DOM is loaded, create your jQuery UI dialog and have its autoOpen property set to false. This allows us to reuse this dialog for all delete confirmations.
// create the jQuery modal window and set autoOpen to false
$("#jQueryDeleteConfirmationModalWindow").dialog({
title: "Delete Confirmation",
autoOpen: false, // set this to false so we can manually open it
dialogClass: "jQueryDeleteConfirmationModalWindow",
closeOnEscape: false,
draggable: false,
width: 460,
height: 260,
modal: true,
buttons: {
"Yes, I'm sure": function() {
$( this ).dialog( "close" );
},
Cancel: function() {
$( this ).dialog( "close" );
}
},
resizable: false,
open: function() {
// scrollbar fix for IE
$('body').css('overflow','hidden');
},
close: function() {
// reset overflow
$('body').css('overflow','auto');
}
}); // end of dialog
Step 3
Bind the onclick events to the delete action links via the css class deleteConfirmation.
$('a.deleteConfirmation').click(function() {
var name = $(this).parent().parent().children('td.name').html(); // a.delete -> td -> tr -> td.name
name = jQuery.trim(name);
$("#jQueryDeleteConfirmationModalWindow").html('Are you sure you wish to delete ' + name + '?');
$("#jQueryDeleteConfirmationModalWindow").dialog('open');
return false;
});
Notice I also made it so my confirmation message will contain an unique description via the inner html property of another table cell of the same table row?
Step 4
If the user clicks on “Yes, I’m sure”, we want to execute the delete action. Therefore, my solution is to create a global variable that contains the value of the hyperlink the user clicked on and then set it to the window.location if the “Yes, I’m sure” is clicked on the modal window.
As the first line inside of the script tag, add
var deleteTheSelectedUrl = '';In the button “Yes, I’m sure”, after dialog close, add
if('' != jQuery.trim(deleteTheSelectedUrl)) {
window.location = deleteTheSelectedUrl;
}
In the onclick event binding, add as the first line
deleteTheSelectedUrl = $(this).attr('href');
View the final example
github repo
I’ve been actually down lately. Just came back from a visit of a therapist. I could barely sleep the last few weeks.
I found this in my facebook inbox which cheered me up a little. Thank you!
hi… my name is *removed for privacy*. are you the girl who ran beautiful php scripts and webdesign like a decade ago or so??! i think that’s was when i was just about starting college, i stumbled onto your site, and really fell in love with the heart and soul you poured into your online creations!! you even had some personal projects with which i deeply identified. i fell out of webdesign for many years after that, but am trying to return back to it, and came upon ‘dodo’s scripts’, and all the memories i had of visiting your creations and your stories came into place… you struck a resonant chord within me back in those days, and i thank you for that :) i’m sorry to other you like this as a total stranger, but you had a memorable impact on me at that point :) :) i hope you are having a serene and blissful year thus far. yours truly, *removed for privacy*
In addition, my friend Leah, who used to be an admin @ my message board Dodo’s Message Board, created a DMB facebook group. If you use to belong to dodosmb.com or regretless.org or regretless.com/board, please join us :)
Watched the spring framework 3.1 webinar today and it was pretty interesting.
Anyway, at work we are trying to possibly load property values from a database to resolve some tension between the developers and system specialists.
I played a little bit at home as how we would set this up. This is not a new issue obviously; many have solved it previously. I did it partly as an exercise to familiarize myself with cgywin, maven and intellij as they are the new tools I will be using at my new job :)
The things to accomplish
- Load properties to replace placeholders in spring config from both .properties file and a database table
- The configuration table will contain properties for more than one application
- Use another .properties file to initialize the datasource for the database configuration table.
Main libraries used
- Spring (3.0.3.RELEASE)
- H2 database (1.1.118)
- Spring modules (0.8a)
- Commons-configuration (1.6)
- JUnit (4.5)
- Spring-test (3.0.3.RELEASE)
I first created a simple project via maven. I assume you have maven installed with shell/batch access.
mvn archetype:generate -B -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.0 -DgroupId=net.pureessence -DartifactId=DatabaseConfiguration -Dversion=1.0 -Dpackage=net.pureessence.example
How I wired up the configuration datasource
I created a factory to create the datasource using org.apache.commons.dbcp.BasicDataSourceFactory.createDataSource(properties) and loaded the initial datasource properties statically via the class loader. For more information on the property keys used by BasicDataSourceFactory.createDataSource, visit this test case.
public static DataSource createDataSource(String propertyFilename) throws Exception {
Properties properties = new Properties();
InputStream in = PropertiesDataSourceFactory.class.getClassLoader().getResourceAsStream(propertyFilename);
properties.load(in);
in.close();
return BasicDataSourceFactory.createDataSource(properties);
}
<bean id="dataSource" class="net.pureessence.example.PropertiesDataSourceFactory" factory-method="createDataSource">
<constructor-arg type="java.lang.String" value="databaseForConfiguration.properties" />
</bean>
How I wired up the configuration
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:env.properties"
p:properties-ref="commonsConfigurationFactoryBean"/>
<bean id="commonsConfigurationFactoryBean" class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<constructor-arg ref="databaseConfiguration"/>
</bean>
<bean id="databaseConfiguration" class="org.apache.commons.configuration.DatabaseConfiguration">
<constructor-arg type="javax.sql.DataSource" ref="dataSource"/>
<constructor-arg name="table" value="configuration"/><!— configuration table name —>
<constructor-arg name="nameColumn" value="application"/><!— name column —>
<constructor-arg name="keyColumn" value="key"/><!— key column —>
<constructor-arg name="valueColumn" value="value"/><!— value column —>
<constructor-arg name="name">
<util:constant static-field="net.pureessence.example.Constants.APPLICATION_ONE"/>
</constructor-arg><!— name (specific configurations) —>
</bean>
<bean id="person" class="net.pureessence.example.Person"
p:firstName="${first.name}"
p:lastName="${last.name}"
p:email="${email}"
p:car="${car}" />
The property key “car” is loaded from env.properties while “first.name”, “last.name” and “email” properties are loaded from the database table.
Why it works
In order to load configuration/placeholders from a database table, the datasource has to be instaniated prior to the instaniation of all of the other beans with placeholders. The databsource factory creates the instance of the datasource via another properties file loaded outside of spring.
Note about the tests
The tests are set up to load the H2 database with the configuration table & data prior to the loading of the spring context in order for it to work
Source code
It contains both intellij and eclipse project files. You should have the m2eclipse plugin for eclipse installed in order to pull down the jars in pom.xml.
»>DOWNLOAD IT«<