Archive for October 2008
Using JPA with Spring 2.0 or the Java Agent issue
Maybe this article is the main reference about JPA in Spring 2.0. It’s a great resource to start playing with JPA technology but it does not include any comment relative to a key issue: load time weaving. This technique is responsible of any class transformation from generic database objects to customized domain beans.
Spring’s 2.0 reference include several options to perform this work hooking application’s container resources and describe standalone support via java agent (VM option -javaagent:/path/to/spring-agent.jar). In Spring 2.5 hooking options have been increased (p.e. Weblogic only is available since this version).
I was evaluating a migration from Hibernate to JPA but this issue make me doubt. It seems as if they were using a bazooka to kill a fly!
Dangerous Date manipulation
public static String getIncrementedDate(String someDate, int inc, String dateFormat) {
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
java.util.Date initDate = null;;
try {
initDate = formatter.parse(someDate);
} catch (java.text.ParseException e) {
e.printStackTrace();
}
long Fech = initDate.getTime() + inc*24*60*60*1000;
Date incrementedDate = new Date(Fech);
return formatter.format(incrementedDate);
}
public static void main(String...strings ) throws Exception {
System.out.println(getIncrementedDate("20081026", 1, "yyyyMMdd"));
}
Maybe you are expecting “20081027″ output for this program? You’re wrong. This code produces “20081026″.
Changing the hour (from 3:00 AM to 2:00 AM) on 26th October involves a mathematical difference of 24 + 1 hours between 26th October and 27th October.
Don’t use java.util.Date to manipulate dates in Java. Use Calendar instead.
Checking Oracle availability with Spring jdbc 2.0
Spring Jdbc uses its own Runtime Exception hierarchy in order to provide Exceptions from the database layer. Hence, no Exception is thrown by database methods encapsuling queries and error control can be delegate to services.
Catching DataAccessResourceFailureException and CannotGetJdbcConnectionException should be enough to detect that database is down. However in Spring exceptions hierarchy exists UncategorizedDataAccessException too. Several Oracle critical errors are translated by Spring under this category.
By default, only error codes appearing in org.springframework.jdbc.support.sql-error-codes.xml are mapped to Spring customized exceptions. In order to detect another error codes SQLErrorCodeSQLExceptionTranslator class is provided. Every database exception its translated by this mechanism. The point is to include here the complete oracle error code list for database unavailability.
JdbcTemplate initialization
JdbcTemplate jt = new JdbcTemplate(dataSource); CustomExceptionTranslator cet = new CustomExceptionTranslator(); fet.setDataSource(dataSource); jt.setExceptionTranslator(fet);
Custom SQLErrorCodeSQLExceptionTranslator
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
public class CustomExceptionTranslator extends SQLErrorCodeSQLExceptionTranslator {
// Oracle error codes uncategorized by Spring
private static final List<integer> ORACLE_CLOSED_ERROR_CODES =
Arrays.asList(1012, 1033, 1034, 1041, 1089, 1090, 1114,
12154, 12203, 12224, 12500, 12505, 12519, 12520,
12535, 12541, 12545, 12571, 1688, 17002, 17008,
17410, 17447, 23001, 27091, 27092, 27101, 3113, 3114);
/**
* Translate SQLExceptions to Spring RuntimeExceptions
*/
public DataAccessException translate(String task, String sql, SQLException sqlex) {
DataAccessException dae = super.translate(task, sql, sqlex);
if (dae instanceof DataAccessResourceFailureException ||
dae instanceof CannotGetJdbcConnectionException ||
ORACLE_CLOSED_ERROR_CODES.contains(sqlex.getErrorCode())) {
// Database is DOWN!
}
return dae;
}
}
Further information