Friday, September 11, 2009

Retry Spring Batch job due to database deadlock

I encountered the problem with Spring Batch where 2 jobs are started at the exact same time and a database deadlock occurs in Spring Batch database. It causes one job to fail as it was chosen as a deadlock victim.

com.rhd.ams.batch.AmsCommandLineBatchRunner: Job Terminated in error:
org.springframework.dao.DataAccessResourceFailureException: Could not increment identity; nested exception is java.sql.SQLException: Transaction (Process ID 114) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
at org.springframework.jdbc.support.incrementer.SqlServerMaxValueIncrementer.getNextKey(SqlServerMaxValueIncrementer.java:107) [spring-jdbc-2.5.6.jar:2.5.6]
at org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer.nextLongValue(AbstractDataFieldMaxValueIncrementer.java:125) [spring-jdbc-2.5.6.jar:2.5.6]
at org.springframework.batch.core.repository.dao.JdbcJobInstanceDao.createJobInstance(JdbcJobInstanceDao.java:66) [spring-batch-core-1.1.0.RELEASE.jar:na]
at org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:183) [spring-batch-core-1.1.0.RELEASE.jar:na]


There are other people encountered the same problem as well.
http://forum.springsource.org/archive/index.php/t-54954.html

I took suggestions from this link and changed the isolation level in a configuration file to be ISOLATION_READ_UNCOMMITTED or REPEATABLE_READ but still it doesn't solve the problem, although we got fewer deadlock occurrences.

So, I took a different approach by retrying a failed job instead. Spring provides RetryOperationsInterceptor. See http://static.springsource.org/spring-batch/trunk/reference/html-single/index.html#retry.

It can be done easily by just declaring retry operations in a configuration file:

   

org.springframework.dao.DeadlockLoserDataAccessException
org.springframework.dao.DataAccessResourceFailureException


















Thursday, April 30, 2009

Spring MVC vulnerabilites

This actually has been advised on Spring Source a while back.
Or you can check it out at http://www.ouncelabs.com/resources/126-two_security_vulnerabilities_in_the_spring_frameworks_mvc.

I want to mention one of the issues here:
To prevent unintentionally data binding, Spring suggests you to set which fields are allowed to be bound or edited using @InitBinder or the like.

Quote:
@Controller - Use the @InitBinder annotation to inject a WebDataBinder into a method used to configure it explicitly. Call setAllowedFields(String []) to restrict the fields allowed for that Controller class. If the set of allowedFields needs to vary per handler method, have your @InitBinder method accept a HttpServletRequest and key off the current request mapping.
--

The only thing I don't like is you have to specify form field names one by one or some regular expression to match multiple. It's quite tedious if there are a lot of fields!

Plus, if you rename any of your form fields, don't forget to change it here as well. Otherwise, you might be pulling your hair out wondering why some data are bound and some are not!

Wednesday, October 29, 2008

Special Characters in Spring MVC

You might be surprised to see when you type special characters on the form and in the controller, it comes in wrong e.g.
I typed a copy right sign, "©".  It came in as "©".
Even though I have already set my page's encoding to UTF-8, it didn't work.

The problem is Spring tried to encode using ISO-8859-1 still.  I think it is because, per Servlet standard, that is the default request/response encoding.

The solution is simple; we just have to explicitly set the encoding we want using CharacterEncodingFilter.  Thank to a post in Spring Forum.

Add the following to your web.xml.
<filter>
<filter-name>springCharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>springCharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Wednesday, October 8, 2008

Daily Puppy

I love Daily Puppy

It's my fix of the day!

Talking about dogs, there is a dog parade hosted by Justin Rudd of HautedDogs.org.

Sun, Oct 26, 2:30 p.m. 
The start/finish is at Livingston Park, 4900 E. Livingston Dr. (@ Park Ave. in Belmont Shore), Long Beach, 90803.

Thursday, October 2, 2008

jQuery.ScrollTo and Dynamic Content

I have a page which displays dynamic content pulled from the database.  I need to scroll the page to a specific element upon loading, so I look around and found that jQuery.ScrollTo is very helpful. I could write a code as simple as

$.scrollTo($('#div1'), 500)

where 
$('#div1') is the element I want my page to scroll to and 
500 is a length (in millisec) of animation showing a page scrolls from the top to that element.

Nice, right?

I stuck the code in $(document).ready() function. Rendered it in IE8. Looked Great. 
Tried in Firefox3. Ding! It doesn't work. I would expect the result the other way around... ;P

So, I tried another option - passing absolute position instead jquery object to scrollTo method.

$(document).ready(function() {
var pos = $('#div').position();
$.scrollTo(pos, 500);
});

Still, it doesn't work on FF! Worse, it threw exceptions:
[Exception... "Could not convert JavaScript argument arg 0 
[nsIDOMViewCSS.getComputedStyle]" nsresult: "0x80570009 
(NS_ERROR_XPC_BAD_CONVERT_JS)" 
location: "JS frame :: http://localhost:8888/scripts/jquery.js :: 
anonymous :: line 871" data: no]

WTH...

I googled around. These 2 links saved me.
Ok. I'm not crazy. This problem is a known problem. Position() returns a value properly only if the 
element is visible.

Ahhhh, I should try doing this AFTER my element is loaded on the page.

$(window).load(function() { 
$.scrollTo($('#div1'),500); });

This works!

Alright, let's try one more thing. I put the following snipplet in $(document).ready() function.

$('#div1').load(function() { 
$.scrollTo($('#div1'),500); });

It doesn't work.  Oh well,   the documentation explains it.
"When bound to the window element, the event fires when the user agent finishes loading all content within a document, including window, frames, objects and images. For elements, it fires when the target element and all of its content has finished loading. Note: load will work only if you set it before the element has completely loaded, if you set it after that nothing will happen. This doesn't happen in $(document).ready(), which jQuery handles it to work as expected, also when setting it after the DOM has loaded."

I will just stick to what works :)