Announcement Announcement Module
No announcement yet.
Making a transactional JDODaoSupport Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Making a transactional JDODaoSupport


    I'm trying to set up a transactional database access using JDO(JPOX) and Spring. The problem is I cannot succeed in making a transactional DAO bean. I am using the descriptive(TransactionProxyFactoryBean) approach. My xml configuration is as follows:
    <?xml version="1.0" encoding="UTF-8"?>
    	<bean id="simpleDAO" class="com.ess.test.dao.SimpleDAO" abstract="false"
    		singleton="true" lazy-init="default" autowire="default"
    		<property name="persistenceManagerFactory">
    			<ref bean="persistenceManagerFactory" ></ref>
    	<!-- Transaction Interceptor for Business Services -->
    	<bean id="txsd"
    		<property name="transactionManager">
    			<ref local="jdoTransactionManager" />
    		<property name="target">
    			<ref local="simpleDAO" />
    		<property name="transactionAttributes">
    				<prop key="*">PROPAGATION_REQUIRED</prop>
    				<prop key="save*">PROPAGATION_REQUIRED</prop>
    				<prop key="delete*">PROPAGATION_REQUIRED</prop>
    				<prop key="updateRecord">PROPAGATION_REQUIRED</prop>
    				<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
    As you can see, I have omitted certain bean definitions to keep it clear. This is not the whole config file, i also have definitions for jdoTransactionManager and persistenceManagerFactory beans.

    My Java code for SimpleDAO is:
    public class SimpleDAO extends JdoDaoSupport {
    	public SimpleDAO() {}
    It may look strange(not having any methods working with the database) but it is a legal java class and there must be no problems when using it.

    The invocation:
    ApplicationContext context = new ClassPathXmlApplicationContext(
    		        new String[] {"test-config.xml"});
    SimpleDAO s = (SimpleDAO)context.getBean("txsd"); //This is line 40

    What I get is:
    Exception in thread "main" java.lang.ClassCastException: $Proxy0
    at com.ess.test.SpringTestApp.<init>(SpringTestApp.ja va:40)
    at com.ess.test.SpringTestApp.main( :110)

    As you can see, I am getting the TransactionProxyFactoryBean from the factory, not the simpleDAO bean itself. I tried the simpleDAO first and the bean is instantiated without problems. However, when I use makePersistent from the bean I get the famous "Transaction is not active" exception e.g. it is not wrapped in a transaction(as you can see I added <prop key="*">PROPAGATION_REQUIRED</prop> just to be sure it is not my transaction configuration that is wrong).
    So I end up instantiating the TransactionProxyFactoryBean instead. This is working OK as long as the target class is not inherited from the JdoDaoSupport class(the given case). I tried to make transactional a service bean which has a reference to the SimpleDAO object - it works fine.

    So there is two base questions:
    1. Am I supposed to instantiate the TransactionProxyFactoryBean or its target?

    2. Is it wrong to wrap within transactions a JdoDaoSupport inheritor? (Yes, I have read about making transactional service beans which use the DAO object, however it should be working).

    However, there may be a 0 question: Is my configuration wrong?

    My spring version: 2.1-m1

    (not that it matters):
    JDO: 2
    JPOX: 1.6

  • #2
    OK, one thing I figured out: the different behaviour when inheriting the JdoDaoSupport is because JdoDaoSupport inherits DaoSupport, which implements the InitializingBean interface, thus causing the usage of JDK dynamic proxy instead of CGLIB, thus no casting to the class, only to interfaces.

    However, one question still remains: should I use
    1) beanFactory.getBean("-the id of the DAO bean itself-");
    2) beanFactory.getBean("-the id of the TransactionProxyFactoryBean-");

    As I already mentioned, no transaction takes place while using the first approach.


    • #3
      You need to use the bean name of the TransactionProxyFactoryBean, otherwise there isn't going to be a transaction applied. If you are programming to interfaces, you can fix this by casting to the interface instead of the implementation class. If not they you need to declare proxyTargetClass="true" on the proxy to enable CGLIB proxying.


      • #4
        Thanks for the help. Everything works fine when using CGLIB.


        • #5
          Programming to intefaces is generally regarded as a better practice. If you are happy with it and it's working, great.