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!