Announcement Announcement Module
Collapse
No announcement yet.
JdoDaoSupport requires it's wrapped in a transaction? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JdoDaoSupport requires it's wrapped in a transaction?

    I started using JdoDaoSupport today and found that I have to use transactions or things fail with a "transaction not active" message. With all of the other DaoSupport classes, I was able to declare transactions on my service objects rather than on DAOs. Is it a requirement that JdoDaoSupport children be wrapped like the following?

    I'm using JPOX 1.0.2.

    Code:
        <!-- UserDAO for JDO -->
        <bean id="userDAO" 
            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="transactionManager"><ref local="transactionManager"/></property>
            <property name="target">
                <bean class="org.appfuse.dao.jdo.UserDAOJdo" autowire="byName"/>
            </property>
            <property name="transactionAttributes">
                <props>
                    <prop key="save*">PROPAGATION_REQUIRED</prop>
                    <prop key="remove*">PROPAGATION_REQUIRED</prop>
                    <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
                </props>
            </property>
        </bean>
    Thanks,

    Matt

  • #2
    No, in fact it's still best form to wrap your service objects with transactions, and not the JdoDaoSupport-based DAOs.

    I'm confused thouugh, are you trying to run this with no transaction at all, or with a transaction around the service insteaf of around the dao? Where transactions come in is that if there is a wrapping transaction, a PersistenceManager instance will be synchronized to and associated with that transaction (either via JdoTransactionManager or JdoInterceptor, or via the first use of a JdoTemplate with the allowCreate flag set to true), but the latter certainly doesn't care at what scope the transaction exists.

    Can you provide a stack trace?

    Colin

    Comment


    • #3
      I'm basically trying to do what I've done with the Hibernate, Spring JDBC and iBATIS SupportDaos. I usually just declare a DAO, set it's dataSource, sessionFactory, persistenceManager or whatever it may be and then run with it. When I test these DAOs, there is no transactions declared on them.

      I tried to do the following with JDO:

      Code:
      	<bean id="persistenceManagerFactory" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
      		<property name="jdoProperties">
      			<props>
      				<prop key="javax.jdo.PersistenceManagerFactoryClass">org.jpox.PersistenceManagerFactoryImpl</prop>
      				<prop key="javax.jdo.option.ConnectionDriverName">com.mysql.jdbc.Driver</prop>
      				<prop key="javax.jdo.option.ConnectionUserName">root</prop>
      				<prop key="javax.jdo.option.ConnectionPassword"></prop>
      				<prop key="javax.jdo.option.ConnectionURL">jdbc&#58;mysql&#58;//localhost/appfuse</prop>
      				<prop key="org.jpox.autoCreateSchema">true</prop>
      				<prop key="org.jpox.validateTables">false</prop>
      				<prop key="org.jpox.validationConstraints">false</prop>
      			</props>
      		</property>
      	</bean>
      
          <bean id="transactionManager" class="org.springframework.orm.jdo.JdoTransactionManager">
      		<property name="persistenceManagerFactory"><ref bean="persistenceManagerFactory"/></property>
      	</bean>
      
          <bean id="userDAO" class="org.appfuse.dao.jdo.UserDAOJdo">
      		<property name="persistenceManagerFactory"><ref bean="persistenceManagerFactory"/></property>
      	</bean>
      But when I run my simple DAOTest, I get:

      Code:
          &#91;junit&#93; Testcase&#58; testGetUsers&#40;org.appfuse.dao.UserDAOTest&#41;&#58;        Caused an ERROR
          &#91;junit&#93; Transaction is not active; nested exception is org.jpox.exceptions.TransactionNotActiveE
      xception&#58; Transaction is not active
          &#91;junit&#93; org.springframework.orm.jdo.JdoUsageException&#58; Transaction is not active; nested excepti
      on is org.jpox.exceptions.TransactionNotActiveException&#58; Transaction is not active
          &#91;junit&#93; org.jpox.exceptions.TransactionNotActiveException&#58; Transaction is not active
          &#91;junit&#93;     at org.jpox.AbstractPersistenceManager.assertActiveTransaction&#40;AbstractPersistenceMa
      nager.java&#58;334&#41;
          &#91;junit&#93;     at org.jpox.AbstractPersistenceManager.makePersistent&#40;AbstractPersistenceManager.jav
      a&#58;797&#41;
          &#91;junit&#93;     at org.springframework.orm.jdo.JdoTemplate$7.doInJdo&#40;JdoTemplate.java&#58;217&#41;
          &#91;junit&#93;     at org.springframework.orm.jdo.JdoTemplate.execute&#40;JdoTemplate.java&#58;136&#41;
          &#91;junit&#93;     at org.springframework.orm.jdo.JdoTemplate.makePersistent&#40;JdoTemplate.java&#58;215&#41;
          &#91;junit&#93;     at org.appfuse.dao.jdo.UserDAOJdo.saveUser&#40;UserDAOJdo.java&#58;26&#41;
          &#91;junit&#93;     at org.appfuse.dao.UserDAOTest.testGetUsers&#40;UserDAOTest.java&#58;30&#41;
          &#91;junit&#93;     at sun.reflect.NativeMethodAccessorImpl.invoke0&#40;Native Method&#41;
          &#91;junit&#93;     at sun.reflect.NativeMethodAccessorImpl.invoke&#40;NativeMethodAccessorImpl.java&#58;39&#41;
          &#91;junit&#93;     at sun.reflect.DelegatingMethodAccessorImpl.invoke&#40;DelegatingMethodAccessorImpl.java
      &#58;25&#41;

      Comment


      • #4
        Re: JdoDaoSupport requires it's wrapped in a transaction?

        Originally posted by mraible
        Is it a requirement that JdoDaoSupport children be wrapped like the following?

        Code:
            <!-- UserDAO for JDO -->
            <bean id="userDAO" 
                class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                <property name="transactionManager"><ref local="transactionManager"/></property>
                <property name="target">
                    <bean class="org.appfuse.dao.jdo.UserDAOJdo" autowire="byName"/>
                </property>
                <property name="transactionAttributes">
                    <props>
                        <prop key="save*">PROPAGATION_REQUIRED</prop>
                        <prop key="remove*">PROPAGATION_REQUIRED</prop>
                        <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
                    </props>
                </property>
            </bean>
        If you take a look at the Kodo-Spring sample app, with KODO JDO they don't declare TX semantics on the DAO, only on Service POJO's. However, they use the ProxyFactoryBean + TransactionInterceptor approach, rather than the simpler TransactionProxyFactoryBean approach. Is there any difference between these 2 approaches?

        Comment


        • #5
          Matt is saying that he doesn't want to wrap transactionally at all.

          I don't have the JDO spect handy, and it's been a while since I've written production code with JDO (Kodo, in my case), which was always transactional anyways, but I'm about 100% sure that support for nontransactional (including persistent-nontransactional) states in JDO 1.0 is optional. So JPOX throwing an error when there is no transaciton is probably a JPOX implementation specific thing as opposed to a JDO specific thing.

          Personally, what I do for my Mapper/DAO tests is wrap the code inside a programmatic TransactionTemplate, using a TransactionManager and other beans coming from an appcontext specific (or at least one of the xml fragments) specific to that test. This allows usage and testing of multiple DAOs working together, or multiple calls into the same DAO to do sequential operations, used in the same fashion inside one encompassing transaction, as they would be in real-life code.

          Regards,

          Comment


          • #6
            Yeah, I looked at the Kodo-Spring example, and as far as I can tell, if there's a call to "makePersistent()" in a class - then that class has to be wrapped in a transaction. Of all the DAOs in the example, CategoryDAOImpl is the only one with a makePersistent() call and it's got a transaction interceptor defined in the Spring context file.

            Maybe JdoTemplate should be enhanced to create a new transaction if one doesn't exist?

            This would make testing easier. Also, it would be nice if the JDO support was more in-line w/ the other persistence frameworks (JDBC, Hibernate, iBATIS, OJB) - where a transaction is not required on the DAO.

            Comment


            • #7
              No, I really don't think it's the job of a template object to get involved in crreating transactions. It can ensure that stuff that needs to get synchronized with and bound to an existing tx gets done so, but it would not be consistent if JdoTemplate did this. W/regards to making it more in-line with the other persistence frameworks, I think this would actually make it less in-line with how the templates for the other persistence frameworks behave. But more to the point, it doesn't make sense for the template to create transactions because transactions should span the service layer, not individual DAOs.

              Again, this is a JPOX issue as far as I can tell, but I don't frankly really see it as an issue. In real life usage of a DAO you use a transaction, so it's actually cleaner or closer to that real-life usage to also test the DAO inside a transaction.

              Comment


              • #8
                Originally posted by Colin Sampaleanu
                Matt is saying that he doesn't want to wrap transactionally at all.

                I don't have the JDO spec handy, and it's been a while since I've written production code with JDO (Kodo, in my case), which was always transactional anyways, but I'm about 100% sure that support for nontransactional (including persistent-nontransactional) states in JDO 1.0 is optional. So JPOX throwing an error when there is no transaciton is probably a JPOX implementation specific thing as opposed to a JDO specific thing.
                Hi guys,

                javax.jdo.option.NontransactionalRead
                javax.jdo.option.NontransactionalWrite
                are both optional in JDO 1.0. JPOX does support NontransactionalRead though we have fixed a couple of bugs in that area in the last few days (but neither bug responsible for throwing TransactionNotActive exceptions). The fact is though, to use a JDO implementation without transactions you would need to set the NontransactionalRead property to "true".

                I'd guess that you need to add this to your "jdoProperties" if you want to run without transactions [if you look at the springjdo example for Kodo, you'll find this property being set in the jdoProperties section]

                Comment

                Working...
                X