Archive for the ‘springframework’ Category

How to extend SQLErrorCodesFactory

Tuesday, September 2nd, 2008

I found some interesting feature in springframework. Spring offers you to map sql error code to exception type. By default there is in springframework distribution file called sql-error-codes.xml which has definition for common databases ( DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase).

This keys are taken form java.sql.DatabaseMetaData databaseProductName property. Each driver should provide proper implementation. This post will provide you the way how to add another databases or extends definition to more sql codes.

As we read javadoc, the default file is bundled in spring.jar and it’s location is “org/springframework/jdbc/support/sql-error-codes.xml" so first solution is to simple extract this file, add what we want, and than put it back. This solution has many drawbacks e.g. when we upgrade we must repeat our steps once again. If we keep reading javadoc we read

Reads the default file in this package if not overridden by a file in the root of the class path (for example in the “/WEB-INF/classes” directory).

So the second option is to provide file called ’sql-error-codes.xml’ in the root path. Lets start coding.
Our App.java is very simple.

public class App {
public static void main(String[] args) {
SQLErrorCodesFactory errorCodes = SQLErrorCodesFactory.getInstance();
SQLErrorCodes errorCode = errorCodes.getErrorCodes(“MySQL”);
}
}

sql error codes default

If we run this in debug mode we can see something like this. This is default SQL error codes definition for MySQL database. Now we add the ’sql-error-codes.xml’. I’ve just copied MySQL bean from default file and added some codes to badSqlGrammarCodes. This time the result look like this:

sql error codes override

And here is execution log, interesting lines in bold:

Sep 2, 2008 9:54:46 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
Sep 2, 2008 9:54:46 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [sql-error-codes.xml]
Sep 2, 2008 9:54:46 PM org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition
INFO: Overriding bean definition for bean 'MySQL':
    replacing [Generic bean: ... defined in class path resource [org/springframework/jdbc/support/sql-error-codes.xml]]
    with [Generic bean: ...  defined in class path resource [sql-error-codes.xml]]
Sep 2, 2008 9:54:46 PM org.springframework.jdbc.support.SQLErrorCodesFactory
INFO: Found custom sql-error-codes.xml file at the root of the classpath
Sep 2, 2008 9:54:46 PM org.springframework.jdbc.support.SQLErrorCodesFactory
INFO: SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]

The point to remember is that our definition didn’t override all the definition but only definition with the same bean id. This is not so clear in SQLErrorCodesFactory javadoc, which suggest that we override all beans.

We can use this mechanism if we have different database, or if we want to extend or change sql code mapping to exception. The application is really simple but you can
download it, and try by yourself.

Bye.

java spring config

Friday, August 29th, 2008

There is a possibility to configure spring framework only in java. Yep no XML ;) .

There is a project spring-java-config. This project aims to provide a way to configure spring without XML. To use it with maven you should add repository to your pom and dependency

<repository>
  <id>spring-milestone</id>
  <name>Spring Milestone Repository</name>
  <url>http://s3.amazonaws.com/maven.springframework.org/milestone</url>
</repository>

<dependency>
   <groupId>org.springframework.javaconfig</groupId>
   <artifactId>spring-javaconfig</artifactId>
   <version>1.0.0.m3</version>
</dependency>

One thing to mention is to setup java 5 compiler, because spring java config use annotation.

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
      <source>1.5</source>
      <target>1.5</target>
      <encoding>UTF-8</encoding>
    </configuration>
  </plugin>

This config will provide as all the dependencies, we can start to configure our beans. The class which has bean configuration must be annotated by @Configuration annotation, and methods with @Bean annotation is equivalent to element. Resume : klas with @Configuration equals xml file with beans, and method with @Bean equals element.

config class

And the last thing is to use JavaConfigApplicationContext which accepts as constructor class annotated with @Configuration property. Below the main class.

main program

And this is basis, we can probably stop here but I provide some additional information. Depends on method visibility our bean is visible or not in the context.

  • The standard set of *Aware interfaces are supported.
  • You can use scopes, autowire and others features known from xml configuration
  • @Import is equivalent of xml’s <import>, and JavaConfigApplicationContext accepts more than one class as constructor parameter.
  • For web application we can use JavaConfigWebApplicationContext

I’m still watching the future of the project. Stay tuned ;)

about me

My name is Sebastian Pietrowski. I've finished Warsaw University as Master degree. I started my journey with Java 1.1 with Thread and JDBC programing in 1998 as I worked for merlin.pl. In 1999 I've passed Java Programer Certificate for Java 1.2, and was solution architect of merlin.pl infrastructure when we was moving from pl/sql to J2EE. It was great performance optimization with 10 times more req/sec than in requirements and 85 times faster as original solution.

Currently I work as Expert Software Development Java at F.Hoffmann-La Roche. The company was founded in 1896 and today, Roche employs over 80.000 people. After work I'm involved in activities related to Scala/Lift, Ruby/Rails/Merb, Python/Django. This is because I try to be pragmatic also I'm focused on application performance and tuning with success in my daily work.

My Yoda's motto: Do, or do not. There is no try.