Question

I am new to Springs. I am trying to run JDBCTempalte example. I got ClassCastException. It doesn't make sense to me.

My Context file

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- I have removed my config, I have tried JDBC code it is working with this datasource-->
</bean>

<bean id="jdbcDAO" class="com.sarma.spring.jdbcEx.JDBCDAOImpl">
<property name="dataSource" ref="dataSource"/><!-- This is my jdbc example it is working-->
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <constructor-arg ref="dataSource"/>
</bean>

my main class

try{
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
org.springframework.jdbc.core.JdbcTemplate jdbc = (org.springframework.jdbc.core.JdbcTemplate)context.getBean("jdbcTemplate");
String query = "SELECT ACNT_NBR FROM eit.ACNT WHERE ACNT_ID=13057";
int o= jdbc.queryForInt(query);
}catch(Exception e){
    e.printStackTrace();
}

Output

2013-10-08 16:43:34 INFO  ClassPathXmlApplicationContext:513 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1c672d0: startup date [Tue Oct 08 16:43:34 EDT 2013]; root of context hierarchy
2013-10-08 16:43:34 INFO  XmlBeanDefinitionReader:316 - Loading XML bean definitions from class path resource [applicationContext.xml]
2013-10-08 16:43:34 INFO  DriverManagerDataSource:133 - Loaded JDBC driver: oracle.jdbc.driver.OracleDriver
java.lang.ClassCastException: $Proxy12 cannot be cast to org.springframework.jdbc.core.JdbcTemplate
    at com.sarma.spring.jdbcEx.main.JdbcExMain.main(JdbcExMain.java:45)

My 45 line is

org.springframework.jdbc.core.JdbcTemplate jdbc = (org.springframework.jdbc.core.JdbcTemplate)context.getBean("jdbcTemplate");

Did I make any mistake?? Thanks for your help

Thanks,

CVSR Sarma

Was it helpful?

Solution

A Spring bean is not usually proxied unless some special external behavior needs to be applied. For example, AOP advice, transaction management, bean scope, etc.

Your context seems to be incomplete. If you've declared some AOP joinpoint that matches a JdbcTemplate method, then that bean will be proxied. You can specify proxy settings, for example if Spring should proxy-target-class instead of the interface. If you have the CGLIB library on your classpath, you shouldn't have any problem by setting

<aop:config proxy-target-class="true"> ...

A small example of JDK proxies

public static void main(String[] args) throws Exception {
    JdbcTemplate template = new JdbcTemplate();
    Object proxy = Proxy.newProxyInstance(template.getClass().getClassLoader(), template.getClass().getInterfaces(), new ProxyJdbcTemplateHandler(template));
    System.out.println(proxy.getClass());
    System.out.println(proxy.getClass().getSuperclass());
    System.out.println(Arrays.toString(proxy.getClass().getInterfaces()));
}

public static class ProxyJdbcTemplateHandler implements InvocationHandler {
    private JdbcTemplate target;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        // do something with target
        return null;
    }

    public ProxyJdbcTemplateHandler(JdbcTemplate target) {
        this.target = target;
    }
}

prints

class $Proxy0
class java.lang.reflect.Proxy
[interface org.springframework.jdbc.core.JdbcOperations]

The proxy has the type of the superinterface of JdbcTemplate, but not the type itself. Its parent class is actually Proxy. For that you will need to use CGLIB proxies, by providing CGLIB jars on your classpath and specifying proxy-target-class="true" in your configuration.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top